• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <ctype.h>
16 #include <errno.h>
17 #include <limits.h>
18 
19 #include "param_manager.h"
20 #include "param_trie.h"
21 #ifdef SUPPORT_PARAM_LOAD_HOOK
22 #include "init_module_engine.h"
23 #endif
24 #include "securec.h"
25 #include "init_cmds.h"
26 #include "init_param.h"
27 
28 /**
29  * Loading system parameter from /proc/cmdline by the following rules:
30  *   1) reserved cmdline with or without ohos.boot. prefix listed in CmdlineIterator
31         will be processed by the specified processor
32  *   2) cmdline not listed in CmdlineIterator but prefixed with ohos.boot will be add by default
33  *
34  *   Special cases for sn:
35  *     a) if sn value in cmdline is started with "/", it means a file to be read as parameter value
36  *     b) if sn or ohos.boot.sn are not specified, try to generate sn by GenerateSnByDefault
37  */
38 #define OHOS_CMDLINE_PARA_PREFIX        "ohos.boot."
39 #define OHOS_CMDLINE_PARA_PREFIX_LEN    10
40 
41 typedef struct CmdLineInfo {
42     const char *name;
43     int (*processor)(const char *name, const char *value);
44 } CmdLineInfo;
45 
46 typedef struct CmdLineIteratorCtx {
47     char *cmdline;
48     bool gotSn;
49 } CmdLineIteratorCtx;
50 
CommonDealFun(const char * name,const char * value)51 static int CommonDealFun(const char *name, const char *value)
52 {
53     int ret = 0;
54     PARAM_LOGV("Add param from cmdline %s %s", name, value);
55     ret = CheckParamName(name, 0);
56     PARAM_CHECK(ret == 0, return ret, "Invalid param name %s", name);
57     PARAM_LOGV("Param name %s, value %s", name, value);
58     ret = WriteParam(name, value, NULL, 0);
59     PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value);
60     return ret;
61 }
62 
ReadSnFromFile(const char * name,const char * file)63 static int ReadSnFromFile(const char *name, const char *file)
64 {
65     char *data = ReadFileData(file);
66     PARAM_CHECK(data != NULL, return -1, "Read sn from %s file failed!", file);
67 
68     int index = 0;
69     for (size_t i = 0; i < strlen(data); i++) {
70         // cancel \r\n
71         if (*(data + i) == '\r' || *(data + i) == '\n') {
72             break;
73         }
74         if (*(data + i) != ':') {
75             *(data + index) = *(data + i);
76             index++;
77         }
78     }
79     data[index] = '\0';
80     PARAM_LOGV("**** name %s, value %s", name, data);
81     int ret = WriteParam(name, data, NULL, 0);
82     free(data);
83     PARAM_CHECK(ret == 0, return ret, "Failed to write param %s", name);
84     return ret;
85 }
86 
87 #define OHOS_SN_PARAM_NAME OHOS_CMDLINE_PARA_PREFIX"sn"
88 
SnDealFun(const char * name,const char * value)89 static int SnDealFun(const char *name, const char *value)
90 {
91     int ret = CheckParamName(name, 0);
92     PARAM_CHECK(ret == 0, return ret, "Invalid name %s", name);
93     if (value != NULL && value[0] != '/') {
94         PARAM_LOGV("**** name %s, value %s", name, value);
95         ret = WriteParam(OHOS_SN_PARAM_NAME, value, NULL, 0);
96         PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value);
97         return ret;
98     }
99     if (value != NULL && value[0] == '/') {
100         ret = ReadSnFromFile(OHOS_SN_PARAM_NAME, value);
101         if (ret == 0) {
102             return ret;
103         }
104     }
105     return ret;
106 }
107 
CmdlineIterator(const NAME_VALUE_PAIR * nv,void * context)108 static void CmdlineIterator(const NAME_VALUE_PAIR *nv, void *context)
109 {
110     int ret;
111     const char *name;
112     const char *matched;
113     char fullName[PARAM_NAME_LEN_MAX];
114     CmdLineIteratorCtx *ctx = (CmdLineIteratorCtx *)context;
115     char *data = (char *)ctx->cmdline;
116     static const CmdLineInfo CMDLINES[] = {
117         { "hardware", CommonDealFun },
118         { "bootgroup", CommonDealFun },
119         { "reboot_reason", CommonDealFun },
120         { "bootslots", CommonDealFun },
121         { "sn", SnDealFun },
122         { "root_package", CommonDealFun },
123         { "serialno", SnDealFun }
124     };
125 
126     data[nv->nameEnd - data] = '\0';
127     data[nv->valueEnd - data] = '\0';
128     PARAM_LOGV("proc cmdline: name [%s], value [%s]", nv->name, nv->value);
129 
130     // Get name without prefix
131     name = nv->name;
132     if (strncmp(name, OHOS_CMDLINE_PARA_PREFIX, OHOS_CMDLINE_PARA_PREFIX_LEN) == 0) {
133         name = name + OHOS_CMDLINE_PARA_PREFIX_LEN;
134     }
135 
136     // Matching reserved cmdlines
137     for (size_t i = 0; i < ARRAY_LENGTH(CMDLINES); i++) {
138         // Check exact match
139         if (strcmp(name, CMDLINES[i].name) != 0) {
140             // Check if contains ".xxx" for compatibility
141             ret = snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1, ".%s", CMDLINES[i].name);
142             matched = strstr(name, fullName);
143             if (matched == NULL) {
144                 continue;
145             }
146             // Check if it is ended with pattern
147             if (matched[ret] != '\0') {
148                 continue;
149             }
150         }
151         ret = snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1,
152             OHOS_CMDLINE_PARA_PREFIX "%s", CMDLINES[i].name);
153         if (ret <= 0) {
154             continue;
155         }
156         PARAM_LOGV("proc cmdline %s matched.", fullName);
157         ret = CMDLINES[i].processor(fullName, nv->value);
158         if ((ret == 0) && (SnDealFun == CMDLINES[i].processor)) {
159             ctx->gotSn = true;
160         }
161         return;
162     }
163 
164     if (name == nv->name) {
165         return;
166     }
167 
168     // cmdline with prefix but not matched, add to param by default
169     PARAM_LOGE("add proc cmdline param %s by default.", nv->name);
170     CommonDealFun(nv->name, nv->value);
171 }
172 
GenerateSnByDefault(void)173 static void GenerateSnByDefault(void)
174 {
175     const char *snFileList [] = {
176         "/sys/block/mmcblk0/device/cid",
177         "/proc/bootdevice/cid"
178     };
179 
180     for (size_t i = 0; i < ARRAY_LENGTH(snFileList); i++) {
181         int ret = ReadSnFromFile(OHOS_CMDLINE_PARA_PREFIX "sn", snFileList[i]);
182         if (ret == 0) {
183             break;
184         }
185     }
186 }
187 
LoadParamFromCmdLine(void)188 INIT_LOCAL_API int LoadParamFromCmdLine(void)
189 {
190     CmdLineIteratorCtx ctx;
191 
192     ctx.gotSn = false;
193     ctx.cmdline = ReadFileData(BOOT_CMD_LINE);
194     PARAM_CHECK(ctx.cmdline != NULL, return -1, "Failed to read file %s", BOOT_CMD_LINE);
195 
196     IterateNameValuePairs(ctx.cmdline, CmdlineIterator, (void *)(&ctx));
197 
198     // sn is critical, it must be specified
199     if (!ctx.gotSn) {
200         PARAM_LOGE("Generate default sn now ...");
201         GenerateSnByDefault();
202     }
203 
204     free(ctx.cmdline);
205     return 0;
206 }
207 
208 /*
209  * Load parameters from files
210  */
211 
LoadSecurityLabel(const char * fileName)212 static int LoadSecurityLabel(const char *fileName)
213 {
214     ParamWorkSpace *paramSpace = GetParamWorkSpace();
215     PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
216     PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
217     PARAM_CHECK(fileName != NULL, return -1, "Invalid filename for load");
218 #if !(defined __LITEOS_A__ || defined __LITEOS_M__)
219     // load security label
220     ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_DAC);
221     if (ops != NULL && ops->securityGetLabel != NULL) {
222         ops->securityGetLabel(fileName);
223     }
224 #endif
225     return 0;
226 }
227 
LoadOneParam_(const uint32_t * context,const char * name,const char * value)228 static int LoadOneParam_(const uint32_t *context, const char *name, const char *value)
229 {
230     uint32_t mode = *(uint32_t *)context;
231     int ret = CheckParamName(name, 0);
232     if (ret != 0) {
233         return 0;
234     }
235 
236 #ifdef SUPPORT_PARAM_LOAD_HOOK
237     PARAM_LOAD_FILTER_CTX filter;
238 
239     // Filter by hook
240     filter.name = name;
241     filter.value = value;
242     filter.ignored = 0;
243     HookMgrExecute(GetBootStageHookMgr(), INIT_PARAM_LOAD_FILTER, (void *)&filter, NULL);
244 
245     if (filter.ignored) {
246         PARAM_LOGV("Default parameter [%s] [%s] ignored", name, value);
247         return 0;
248     }
249 #endif
250 
251     PARAM_LOGV("Add default parameter [%s] [%s]", name, value);
252     return WriteParam(name, value, NULL, mode & LOAD_PARAM_ONLY_ADD);
253 }
254 
LoadDefaultParam_(const char * fileName,uint32_t mode,const char * exclude[],uint32_t count,int (* loadOneParam)(const uint32_t *,const char *,const char *))255 static int LoadDefaultParam_(const char *fileName, uint32_t mode,
256     const char *exclude[], uint32_t count, int (*loadOneParam)(const uint32_t *, const char *, const char *))
257 {
258     uint32_t paramNum = 0;
259     char realPath[PATH_MAX] = "";
260     realpath(fileName, realPath);
261     FILE *fp = fopen(realPath, "r");
262     if (fp == NULL) {
263         PARAM_LOGE("Failed to open file '%s' error:%d ", fileName, errno);
264         return -1;
265     }
266 
267     const int buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10;  // 10 max len
268     char *buffer = malloc(buffSize);
269     PARAM_CHECK(buffer != NULL, (void)fclose(fp);
270         return -1, "Failed to alloc memory");
271 
272     while (fgets(buffer, buffSize, fp) != NULL) {
273         buffer[buffSize - 1] = '\0';
274         int ret = SplitParamString(buffer, exclude, count, loadOneParam, &mode);
275         PARAM_ONLY_CHECK(ret != PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH, return PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH);
276         PARAM_CHECK(ret == 0, continue, "Failed to set param '%s' error:%d ", buffer, ret);
277         paramNum++;
278     }
279     (void)fclose(fp);
280     free(buffer);
281     PARAM_LOGV("Load %u default parameters success from %s.", paramNum, fileName);
282     return 0;
283 }
284 
ProcessParamFile(const char * fileName,void * context)285 static int ProcessParamFile(const char *fileName, void *context)
286 {
287     static const char *exclude[] = {"ctl.", "selinux.restorecon_recursive"};
288     uint32_t mode = *(int *)context;
289     int ret = LoadDefaultParam_(fileName, mode, exclude, ARRAY_LENGTH(exclude), LoadOneParam_);
290     if (ret == PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH) {
291         PARAM_LOGE("default_param memory is not enough, system reboot!");
292         ExecReboot("panic");
293     }
294     return ret;
295 }
296 
LoadParamsFile(const char * fileName,bool onlyAdd)297 int LoadParamsFile(const char *fileName, bool onlyAdd)
298 {
299     return LoadDefaultParams(fileName, onlyAdd ? LOAD_PARAM_ONLY_ADD : LOAD_PARAM_NORMAL);
300 }
301 
LoadDefaultParams(const char * fileName,uint32_t mode)302 int LoadDefaultParams(const char *fileName, uint32_t mode)
303 {
304     PARAM_CHECK(fileName != NULL, return -1, "Invalid filename for load");
305     PARAM_LOGI("Load default parameters from %s.", fileName);
306     struct stat st;
307     if ((stat(fileName, &st) == 0) && !S_ISDIR(st.st_mode)) {
308         (void)ProcessParamFile(fileName, &mode);
309     } else {
310         (void)ReadFileInDir(fileName, ".para", ProcessParamFile, &mode);
311     }
312 
313     // load security label
314     return LoadSecurityLabel(fileName);
315 }
316 
LoadParamFromBuild(void)317 INIT_LOCAL_API void LoadParamFromBuild(void)
318 {
319     PARAM_LOGI("load parameters from build ");
320 #ifdef INCREMENTAL_VERSION
321     if (strlen(INCREMENTAL_VERSION) > 0) {
322         WriteParam("const.product.incremental.version", INCREMENTAL_VERSION, NULL, LOAD_PARAM_NORMAL);
323     }
324 #endif
325 #ifdef BUILD_TYPE
326     if (strlen(BUILD_TYPE) > 0) {
327         WriteParam("const.product.build.type", BUILD_TYPE, NULL, LOAD_PARAM_NORMAL);
328     }
329 #endif
330 #ifdef BUILD_USER
331     if (strlen(BUILD_USER) > 0) {
332         WriteParam("const.product.build.user", BUILD_USER, NULL, LOAD_PARAM_NORMAL);
333     }
334 #endif
335 #ifdef BUILD_TIME
336     if (strlen(BUILD_TIME) > 0) {
337         WriteParam("const.product.build.date", BUILD_TIME, NULL, LOAD_PARAM_NORMAL);
338     }
339 #endif
340 #ifdef BUILD_HOST
341     if (strlen(BUILD_HOST) > 0) {
342         WriteParam("const.product.build.host", BUILD_HOST, NULL, LOAD_PARAM_NORMAL);
343     }
344 #endif
345 #ifdef BUILD_ROOTHASH
346     if (strlen(BUILD_ROOTHASH) > 0) {
347         WriteParam("const.ohos.buildroothash", BUILD_ROOTHASH, NULL, LOAD_PARAM_NORMAL);
348     }
349 #endif
350 }
351 
LoadOneParamAreaSize_(const uint32_t * context,const char * name,const char * value)352 static int LoadOneParamAreaSize_(const uint32_t *context, const char *name, const char *value)
353 {
354     int ret = CheckParamName(name, 0);
355     if (ret != 0) {
356         return 0;
357     }
358     ret = CheckParamValue(NULL, name, value, PARAM_TYPE_INT);
359     PARAM_CHECK(ret == 0, return 0, "Invalid value %s for %s", value, name);
360     PARAM_LOGV("LoadOneParamAreaSize_ [%s] [%s]", name, value);
361     char buffer[PARAM_NAME_LEN_MAX] = {0};
362     int len = sprintf_s(buffer, sizeof(buffer), "const.%s", name);
363     PARAM_CHECK(len > 0, return 0, "Failed to format value %s for %s", value, name);
364     return AddParamEntry(WORKSPACE_INDEX_BASE, PARAM_TYPE_INT, buffer, value);
365 }
366 
LoadParamAreaSize(void)367 INIT_LOCAL_API void LoadParamAreaSize(void)
368 {
369     LoadDefaultParam_("/sys_prod/etc/param/ohos.para.size", 0, NULL, 0, LoadOneParamAreaSize_);
370     LoadDefaultParam_(PARAM_AREA_SIZE_CFG, 0, NULL, 0, LoadOneParamAreaSize_);
371 }
372