diff --git a/begetd.gni b/begetd.gni index ca18b9cc9..f77a56ad6 100644 --- a/begetd.gni +++ b/begetd.gni @@ -31,8 +31,6 @@ declare_args() { # config memory size for liteos-m config_ohos_startup_init_lite_memory_size = 5120 - # boot_kernel_extended_cmdline for extend cmdline - startup_init_feature_decode_group_file = false startup_init_test_performance = true @@ -45,4 +43,7 @@ declare_args() { startup_init_with_param_base = true startup_init_feature_decode_group_file = true } + + # begetutil extension module + startup_begetutil_extra_modules = "" } diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn index 4cb82406c..92692f67c 100755 --- a/interfaces/innerkits/BUILD.gn +++ b/interfaces/innerkits/BUILD.gn @@ -200,6 +200,10 @@ if (defined(ohos_lite)) { "//third_party/mbedtls:mbedtls_shared", ] deps += [ "//base/startup/init/services/param/base:param_base" ] + if (startup_begetutil_extra_modules != "") { + deps += [ startup_begetutil_extra_modules ] + } + external_deps = [ "c_utils:utils", "hilog_native:libhilog_base", diff --git a/interfaces/innerkits/syspara/param_comm.c b/interfaces/innerkits/syspara/param_comm.c index f89d7b092..4d7d82d8e 100644 --- a/interfaces/innerkits/syspara/param_comm.c +++ b/interfaces/innerkits/syspara/param_comm.c @@ -92,6 +92,8 @@ INIT_LOCAL_API int GetParameter_(const char *key, const char *def, char *value, return GetSystemError(ret); } +static PropertyValueProcessor propertyGetProcessor = NULL; + INIT_LOCAL_API const char *GetProperty(const char *key, const char **paramHolder) { BEGET_CHECK(paramHolder != NULL, return NULL); @@ -108,11 +110,21 @@ INIT_LOCAL_API const char *GetProperty(const char *key, const char **paramHolder free(res); return NULL; } + if (propertyGetProcessor != NULL) { + res = propertyGetProcessor(key, res); + } *paramHolder = res; } return *paramHolder; } +INIT_LOCAL_API PropertyValueProcessor SetPropertyGetProcessor(PropertyValueProcessor processor) +{ + PropertyValueProcessor prev = propertyGetProcessor; + propertyGetProcessor = processor; + return prev; +} + INIT_LOCAL_API const char *GetProductModel_(void) { static const char *productModel = NULL; diff --git a/interfaces/innerkits/syspara/param_comm.h b/interfaces/innerkits/syspara/param_comm.h index 5960b15cb..d4025510e 100755 --- a/interfaces/innerkits/syspara/param_comm.h +++ b/interfaces/innerkits/syspara/param_comm.h @@ -30,7 +30,10 @@ extern "C" { #define DEV_BUF_LENGTH 3 #define DEV_BUF_MAX_LENGTH 1024 +typedef char * (*PropertyValueProcessor)(const char *key, char *value); + INIT_LOCAL_API const char *GetProperty(const char *key, const char **paramHolder); +INIT_LOCAL_API PropertyValueProcessor SetPropertyGetProcessor(PropertyValueProcessor processor); INIT_LOCAL_API int GetParameter_(const char *key, const char *def, char *value, uint32_t len); INIT_LOCAL_API const char *GetProductModel_(void); diff --git a/services/include/init_utils.h b/services/include/init_utils.h index 5a01167dd..f4ceb8349 100644 --- a/services/include/init_utils.h +++ b/services/include/init_utils.h @@ -60,6 +60,14 @@ char *ReadFileToBuf(const char *configFile); int GetProcCmdlineValue(const char *name, const char *buffer, char *value, int length); char *ReadFileData(const char *fileName); +typedef struct tagNAME_VALUE_PAIR{ + const char *name; + const char *name_end; + const char *value; + const char *value_end; +} NAME_VALUE_PAIR; +int IterateNameValuePairs(const char *src, void (*iterator)(const NAME_VALUE_PAIR *nv, void *context), void *context); + int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum); void WaitForFile(const char *source, unsigned int maxSecond); size_t WriteAll(int fd, const char *buffer, size_t size); diff --git a/services/param/include/param_utils.h b/services/param/include/param_utils.h index 3a2d3c9a3..4a1e0bec7 100644 --- a/services/param/include/param_utils.h +++ b/services/param/include/param_utils.h @@ -37,16 +37,6 @@ typedef enum { #define PARAM_BUFFER_MAX (0x01 << 16) #endif -struct CmdLineEntry { - char *key; - int set; -}; - -typedef struct cmdLineInfo { - const char *name; - int (*processor)(const char *name, const char *value, int); -} cmdLineInfo; - #define FILENAME_LEN_MAX 255 #define MS_UNIT 1000 #ifndef UNUSED @@ -64,7 +54,6 @@ typedef struct cmdLineInfo { #define OHOS_CTRL_START "ohos.ctl.start=" #define OHOS_CTRL_STOP "ohos.ctl.stop=" #define OHOS_SERVICE_CTRL_PREFIX "ohos.servicectrl." -#define OHOS_BOOT "ohos.boot." #ifdef STARTUP_INIT_TEST #define PARAM_STATIC diff --git a/services/param/linux/BUILD.gn b/services/param/linux/BUILD.gn index 9f86df0d7..f1fab7588 100755 --- a/services/param/linux/BUILD.gn +++ b/services/param/linux/BUILD.gn @@ -74,9 +74,6 @@ if (defined(ohos_lite)) { include_dirs = param_include_dirs public_configs = [ ":exported_header_files" ] - if (defined(boot_kernel_extended_cmdline)) { - defines += [ "BOOT_EXTENDED_CMDLINE=\"${boot_kernel_extended_cmdline}\"" ] - } defines += [ "_GNU_SOURCE", "__LINUX__", @@ -112,10 +109,6 @@ if (defined(ohos_lite)) { "PARAM_SUPPORT_REAL_CHECK", ] - if (defined(boot_kernel_extended_cmdline)) { - defines += [ "BOOT_EXTENDED_CMDLINE=\"${boot_kernel_extended_cmdline}\"" ] - } - if (param_base_log) { defines += [ "PARAM_BASE_LOG" ] } diff --git a/services/param/manager/param_server.c b/services/param/manager/param_server.c index e8e390855..2ec68461a 100755 --- a/services/param/manager/param_server.c +++ b/services/param/manager/param_server.c @@ -18,43 +18,38 @@ #include "param_manager.h" #include "param_trie.h" -static int LoadSecurityLabel(const char *fileName) -{ - ParamWorkSpace *paramSpace = GetParamWorkSpace(); - PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); - PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); - PARAM_CHECK(fileName != NULL, return -1, "Invalid filename for load"); -#if !(defined __LITEOS_A__ || defined __LITEOS_M__) - // load security label - ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_DAC); - if (ops != NULL && ops->securityGetLabel != NULL) { - ops->securityGetLabel(fileName); - } -#endif - return 0; -} +/** + * Loading system parameter from /proc/cmdline by the following rules: + * 1) reserved cmdline with or without ohos.boot. prefix listed in CmdlineIterator + will be processed by the specified processor + * 2) cmdline not listed in CmdlineIterator but prefixed with ohos.boot will be add by default + * + * Special cases for sn: + * a) if sn value in cmdline is started with "/", it means a file to be read as parameter value + * b) if sn or ohos.boot.sn are not specified, try to generate sn by GenerateSnByDefault + */ +#define OHOS_CMDLINE_PARA_PREFIX "ohos.boot." +#define OHOS_CMDLINE_PARA_PREFIX_LEN 10 -static int GetParamValueFromBuffer(const char *name, const char *buffer, char *value, int length) -{ - size_t bootLen = strlen(OHOS_BOOT); - const char *tmpName = name + bootLen; - int ret = GetProcCmdlineValue(tmpName, buffer, value, length); - return ret; -} +typedef struct cmdLineInfo { + const char *name; + int (*processor)(const char *name, const char *value); +} cmdLineInfo; -static int CommonDealFun(const char *name, const char *value, int res) +typedef struct cmdLineIteratorCtx { + char *cmdline; + bool gotSn; +} cmdLineIteratorCtx; + +static int CommonDealFun(const char *name, const char *value) { int ret = 0; - if (res == 0) { - PARAM_LOGV("Add param from cmdline %s %s", name, value); - ret = CheckParamName(name, 0); - PARAM_CHECK(ret == 0, return ret, "Invalid param name %s", name); - PARAM_LOGV("Param name %s, value %s", name, value); - ret = WriteParam(name, value, NULL, 0); - PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value); - } else { - PARAM_LOGW("Get %s parameter value is null.", name); - } + PARAM_LOGV("Add param from cmdline %s %s", name, value); + ret = CheckParamName(name, 0); + PARAM_CHECK(ret == 0, return ret, "Invalid param name %s", name); + PARAM_LOGV("Param name %s, value %s", name, value); + ret = WriteParam(name, value, NULL, 0); + PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value); return ret; } @@ -82,71 +77,125 @@ static int ReadSnFromFile(const char *name, const char *file) return ret; } -static int SnDealFun(const char *name, const char *value, int res) +#define OHOS_SN_PARAM_NAME OHOS_CMDLINE_PARA_PREFIX"sn" + +static int SnDealFun(const char *name, const char *value) { - const char *snFileList [] = { - "/sys/block/mmcblk0/device/cid", - "/proc/bootdevice/cid" - }; int ret = CheckParamName(name, 0); PARAM_CHECK(ret == 0, return ret, "Invalid name %s", name); - if (value != NULL && res == 0 && value[0] != '/') { + if (value != NULL && value[0] != '/') { PARAM_LOGV("**** name %s, value %s", name, value); - ret = WriteParam(name, value, NULL, 0); + ret = WriteParam(OHOS_SN_PARAM_NAME, value, NULL, 0); PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value); return ret; } if (value != NULL && value[0] == '/') { - ret = ReadSnFromFile(name, value); + ret = ReadSnFromFile(OHOS_SN_PARAM_NAME, value); if (ret == 0) { return ret; } } - for (size_t i = 0; i < ARRAY_LENGTH(snFileList); i++) { - ret = ReadSnFromFile(name, snFileList[i]); - if (ret == 0) { - break; - } - } return ret; } +static void CmdlineIterator(const NAME_VALUE_PAIR *nv, void *context) +{ + const char *name; + char fullName[PARAM_NAME_LEN_MAX]; + cmdLineIteratorCtx *ctx = (cmdLineIteratorCtx *)context; + char *data = (char *)ctx->cmdline; + static const cmdLineInfo cmdLines[] = { + { "hardware", CommonDealFun }, + { "bootgroup", CommonDealFun }, + { "reboot_reason", CommonDealFun }, + { "bootslots", CommonDealFun }, + { "sn", SnDealFun }, + { "serialno", SnDealFun } + }; + + data[nv->name_end - data] = '\0'; + data[nv->value_end - data] = '\0'; + PARAM_LOGE("proc cmdline: name [%s], value [%s]", nv->name, nv->value); + + // Get name without prefix + name = nv->name; + if (strncmp(name, OHOS_CMDLINE_PARA_PREFIX, OHOS_CMDLINE_PARA_PREFIX_LEN) == 0) { + name = name + OHOS_CMDLINE_PARA_PREFIX_LEN; + } + + // Matching reserved cmdlines + for (size_t i = 0; i < ARRAY_LENGTH(cmdLines); i++) { + if (strcmp(name, cmdLines[i].name) == 0) { + snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1, OHOS_CMDLINE_PARA_PREFIX "%s", cmdLines[i].name); + PARAM_LOGE("proc cmdline %s matched.", fullName); + int ret = cmdLines[i].processor(fullName, nv->value); + if ((ret == 0) && (SnDealFun == cmdLines[i].processor)) { + ctx->gotSn = true; + } + return; + } + } + + if (name == nv->name) { + return; + } + + // cmdline with prefix but not matched, add to param by default + PARAM_LOGE("add proc cmdline param %s by default.", nv->name); + CommonDealFun(nv->name, nv->value); +} + +static void GenerateSnByDefault() { + const char *snFileList [] = { + "/sys/block/mmcblk0/device/cid", + "/proc/bootdevice/cid" + }; + + for (size_t i = 0; i < ARRAY_LENGTH(snFileList); i++) { + int ret = ReadSnFromFile(OHOS_CMDLINE_PARA_PREFIX "sn", snFileList[i]); + if (ret == 0) { + break; + } + } +} + INIT_LOCAL_API int LoadParamFromCmdLine(void) { - static const cmdLineInfo cmdLines[] = { - {OHOS_BOOT"hardware", CommonDealFun - }, - {OHOS_BOOT"bootgroup", CommonDealFun - }, - {OHOS_BOOT"reboot_reason", CommonDealFun - }, - {OHOS_BOOT"bootslots", CommonDealFun - }, - {OHOS_BOOT"sn", SnDealFun - } - }; - char *data = ReadFileData(BOOT_CMD_LINE); - PARAM_CHECK(data != NULL, return -1, "Failed to read file %s", BOOT_CMD_LINE); - char *value = calloc(1, PARAM_CONST_VALUE_LEN_MAX + 1); - PARAM_CHECK(value != NULL, free(data); - return -1, "Failed to read file %s", BOOT_CMD_LINE); + cmdLineIteratorCtx ctx; - for (size_t i = 0; i < ARRAY_LENGTH(cmdLines); i++) { - int ret = 0; -#ifdef BOOT_EXTENDED_CMDLINE - ret = GetParamValueFromBuffer(cmdLines[i].name, BOOT_EXTENDED_CMDLINE, value, PARAM_CONST_VALUE_LEN_MAX); - if (ret != 0) { - ret = GetParamValueFromBuffer(cmdLines[i].name, data, value, PARAM_CONST_VALUE_LEN_MAX); - } -#else - ret = GetParamValueFromBuffer(cmdLines[i].name, data, value, PARAM_CONST_VALUE_LEN_MAX); -#endif + ctx.gotSn = false; + ctx.cmdline = ReadFileData(BOOT_CMD_LINE); + PARAM_CHECK(ctx.cmdline != NULL, return -1, "Failed to read file %s", BOOT_CMD_LINE); - cmdLines[i].processor(cmdLines[i].name, value, ret); + IterateNameValuePairs(ctx.cmdline, CmdlineIterator, (void *)(&ctx)); + + // sn is critical, it must be specified + if (!ctx.gotSn) { + PARAM_LOGE("Generate default sn now ..."); + GenerateSnByDefault(); } - PARAM_LOGV("Parse cmdline finish %s", BOOT_CMD_LINE); - free(data); - free(value); + + free(ctx.cmdline); + return 0; +} + +/* + * Load parameters from files + */ + +static int LoadSecurityLabel(const char *fileName) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); + PARAM_CHECK(fileName != NULL, return -1, "Invalid filename for load"); +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) + // load security label + ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_DAC); + if (ops != NULL && ops->securityGetLabel != NULL) { + ops->securityGetLabel(fileName); + } +#endif return 0; } diff --git a/services/utils/init_utils.c b/services/utils/init_utils.c index eb48c348b..fe9398c88 100644 --- a/services/utils/init_utils.c +++ b/services/utils/init_utils.c @@ -202,6 +202,48 @@ char *ReadFileData(const char *fileName) return buffer; } +int IterateNameValuePairs(const char *src, void (*iterator)(const NAME_VALUE_PAIR *nv, void *context), void *context) +{ + int cnt = 0; + const char *seperator; + NAME_VALUE_PAIR nv; + if ((src == NULL) || (iterator == NULL)) { + return -1; + } + + do { + // Find space seperator + nv.name = src; + seperator = strchr(src, ' '); + if (seperator == NULL) { + // Last nv + nv.value_end = src + strlen(src); + src = NULL; + } else { + nv.value_end = seperator; + src = seperator + 1; + } + + // Find equal seperator + seperator = strchr(nv.name, '='); + if (seperator == NULL) { + // Invalid name value pair + continue; + } + if (seperator > nv.value_end) { + // name without value, just ignore + continue; + } + nv.name_end = seperator; + nv.value = seperator + 1; + + iterator(&nv, context); + cnt += 1; + } while (src != NULL); + + return cnt; +} + int GetProcCmdlineValue(const char *name, const char *buffer, char *value, int length) { INIT_ERROR_CHECK(name != NULL && buffer != NULL && value != NULL, return -1, "Failed get parameters");