1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci#include <ctype.h>
16d9f0492fSopenharmony_ci#include <errno.h>
17d9f0492fSopenharmony_ci#include <limits.h>
18d9f0492fSopenharmony_ci
19d9f0492fSopenharmony_ci#include "param_manager.h"
20d9f0492fSopenharmony_ci#include "param_trie.h"
21d9f0492fSopenharmony_ci#ifdef SUPPORT_PARAM_LOAD_HOOK
22d9f0492fSopenharmony_ci#include "init_module_engine.h"
23d9f0492fSopenharmony_ci#endif
24d9f0492fSopenharmony_ci#include "securec.h"
25d9f0492fSopenharmony_ci#include "init_cmds.h"
26d9f0492fSopenharmony_ci#include "init_param.h"
27d9f0492fSopenharmony_ci
28d9f0492fSopenharmony_ci/**
29d9f0492fSopenharmony_ci * Loading system parameter from /proc/cmdline by the following rules:
30d9f0492fSopenharmony_ci *   1) reserved cmdline with or without ohos.boot. prefix listed in CmdlineIterator
31d9f0492fSopenharmony_ci        will be processed by the specified processor
32d9f0492fSopenharmony_ci *   2) cmdline not listed in CmdlineIterator but prefixed with ohos.boot will be add by default
33d9f0492fSopenharmony_ci *
34d9f0492fSopenharmony_ci *   Special cases for sn:
35d9f0492fSopenharmony_ci *     a) if sn value in cmdline is started with "/", it means a file to be read as parameter value
36d9f0492fSopenharmony_ci *     b) if sn or ohos.boot.sn are not specified, try to generate sn by GenerateSnByDefault
37d9f0492fSopenharmony_ci */
38d9f0492fSopenharmony_ci#define OHOS_CMDLINE_PARA_PREFIX        "ohos.boot."
39d9f0492fSopenharmony_ci#define OHOS_CMDLINE_CONST_PARA_PREFIX  "const.product."
40d9f0492fSopenharmony_ci#define OHOS_CMDLINE_PARA_PREFIX_LEN    10
41d9f0492fSopenharmony_ci#define IMPORT_PREFIX_LEN               7
42d9f0492fSopenharmony_ci
43d9f0492fSopenharmony_citypedef struct CmdLineInfo {
44d9f0492fSopenharmony_ci    const char *name;
45d9f0492fSopenharmony_ci    int (*processor)(const char *name, const char *value);
46d9f0492fSopenharmony_ci} CmdLineInfo;
47d9f0492fSopenharmony_ci
48d9f0492fSopenharmony_citypedef struct CmdLineInfoContainer {
49d9f0492fSopenharmony_ci    const CmdLineInfo *cmdLineInfo;
50d9f0492fSopenharmony_ci    size_t cmdLineInfoSize;
51d9f0492fSopenharmony_ci} CmdLineInfoContainer;
52d9f0492fSopenharmony_ci
53d9f0492fSopenharmony_citypedef struct CmdLineIteratorCtx {
54d9f0492fSopenharmony_ci    char *cmdline;
55d9f0492fSopenharmony_ci    bool gotSn;
56d9f0492fSopenharmony_ci    bool *matches;
57d9f0492fSopenharmony_ci} CmdLineIteratorCtx;
58d9f0492fSopenharmony_ci
59d9f0492fSopenharmony_cistatic int CommonDealFun(const char *name, const char *value)
60d9f0492fSopenharmony_ci{
61d9f0492fSopenharmony_ci    int ret = 0;
62d9f0492fSopenharmony_ci    PARAM_LOGV("Add param from cmdline %s %s", name, value);
63d9f0492fSopenharmony_ci    ret = CheckParamName(name, 0);
64d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return ret, "Invalid param name %s", name);
65d9f0492fSopenharmony_ci    PARAM_LOGV("Param name %s, value %s", name, value);
66d9f0492fSopenharmony_ci    ret = WriteParam(name, value, NULL, 0);
67d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value);
68d9f0492fSopenharmony_ci    return ret;
69d9f0492fSopenharmony_ci}
70d9f0492fSopenharmony_ci
71d9f0492fSopenharmony_cistatic int ReadSnFromFile(const char *name, const char *file)
72d9f0492fSopenharmony_ci{
73d9f0492fSopenharmony_ci    char *data = ReadFileData(file);
74d9f0492fSopenharmony_ci    PARAM_CHECK(data != NULL, return -1, "Read sn from %s file failed!", file);
75d9f0492fSopenharmony_ci
76d9f0492fSopenharmony_ci    int index = 0;
77d9f0492fSopenharmony_ci    for (size_t i = 0; i < strlen(data); i++) {
78d9f0492fSopenharmony_ci        // cancel \r\n
79d9f0492fSopenharmony_ci        if (*(data + i) == '\r' || *(data + i) == '\n') {
80d9f0492fSopenharmony_ci            break;
81d9f0492fSopenharmony_ci        }
82d9f0492fSopenharmony_ci        if (*(data + i) != ':') {
83d9f0492fSopenharmony_ci            *(data + index) = *(data + i);
84d9f0492fSopenharmony_ci            index++;
85d9f0492fSopenharmony_ci        }
86d9f0492fSopenharmony_ci    }
87d9f0492fSopenharmony_ci    data[index] = '\0';
88d9f0492fSopenharmony_ci    PARAM_LOGV("**** name %s, value %s", name, data);
89d9f0492fSopenharmony_ci    int ret = WriteParam(name, data, NULL, 0);
90d9f0492fSopenharmony_ci    free(data);
91d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return ret, "Failed to write param %s", name);
92d9f0492fSopenharmony_ci    return ret;
93d9f0492fSopenharmony_ci}
94d9f0492fSopenharmony_ci
95d9f0492fSopenharmony_ci#define OHOS_SN_PARAM_NAME OHOS_CMDLINE_PARA_PREFIX"sn"
96d9f0492fSopenharmony_ci
97d9f0492fSopenharmony_cistatic int SnDealFun(const char *name, const char *value)
98d9f0492fSopenharmony_ci{
99d9f0492fSopenharmony_ci    int ret = CheckParamName(name, 0);
100d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return ret, "Invalid name %s", name);
101d9f0492fSopenharmony_ci    if (value != NULL && value[0] != '/') {
102d9f0492fSopenharmony_ci        PARAM_LOGV("**** name %s, value %s", name, value);
103d9f0492fSopenharmony_ci        ret = WriteParam(OHOS_SN_PARAM_NAME, value, NULL, 0);
104d9f0492fSopenharmony_ci        PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value);
105d9f0492fSopenharmony_ci        return ret;
106d9f0492fSopenharmony_ci    }
107d9f0492fSopenharmony_ci    if (value != NULL && value[0] == '/') {
108d9f0492fSopenharmony_ci        ret = ReadSnFromFile(OHOS_SN_PARAM_NAME, value);
109d9f0492fSopenharmony_ci        if (ret == 0) {
110d9f0492fSopenharmony_ci            return ret;
111d9f0492fSopenharmony_ci        }
112d9f0492fSopenharmony_ci    }
113d9f0492fSopenharmony_ci    return ret;
114d9f0492fSopenharmony_ci}
115d9f0492fSopenharmony_ci
116d9f0492fSopenharmony_cistatic int Common2ConstDealFun(const char *name, const char *value)
117d9f0492fSopenharmony_ci{
118d9f0492fSopenharmony_ci    const char *tmpName;
119d9f0492fSopenharmony_ci    tmpName = name;
120d9f0492fSopenharmony_ci    if (strncmp(tmpName, OHOS_CMDLINE_PARA_PREFIX, OHOS_CMDLINE_PARA_PREFIX_LEN) == 0) {
121d9f0492fSopenharmony_ci        tmpName = tmpName + OHOS_CMDLINE_PARA_PREFIX_LEN;
122d9f0492fSopenharmony_ci    }
123d9f0492fSopenharmony_ci    char fullName[PARAM_NAME_LEN_MAX];
124d9f0492fSopenharmony_ci    int ret = snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1,
125d9f0492fSopenharmony_ci                         OHOS_CMDLINE_CONST_PARA_PREFIX"%s", tmpName);
126d9f0492fSopenharmony_ci    PARAM_CHECK(ret > 0, return ret, "snprinf_s failed");
127d9f0492fSopenharmony_ci    ret = CheckParamName(fullName, 0);
128d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return ret, "Invalid name %s", name);
129d9f0492fSopenharmony_ci    PARAM_LOGV("Param name %s, value %s", fullName, value);
130d9f0492fSopenharmony_ci    ret = WriteParam(fullName, value, NULL, 0);
131d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", fullName, value);
132d9f0492fSopenharmony_ci    return ret;
133d9f0492fSopenharmony_ci}
134d9f0492fSopenharmony_ci
135d9f0492fSopenharmony_cistatic int MatchReserverCmdline(const NAME_VALUE_PAIR* nv, CmdLineIteratorCtx *ctx, const char *name,
136d9f0492fSopenharmony_ci                                CmdLineInfoContainer *container)
137d9f0492fSopenharmony_ci{
138d9f0492fSopenharmony_ci    const char* tmpName = name;
139d9f0492fSopenharmony_ci    char fullName[PARAM_NAME_LEN_MAX];
140d9f0492fSopenharmony_ci    int ret = 0;
141d9f0492fSopenharmony_ci    const char* matched;
142d9f0492fSopenharmony_ci
143d9f0492fSopenharmony_ci    // Matching reserved cmdlines
144d9f0492fSopenharmony_ci    for (size_t i = 0; i < container->cmdLineInfoSize; i++) {
145d9f0492fSopenharmony_ci        // Check exact match
146d9f0492fSopenharmony_ci        if (strcmp(tmpName, (container->cmdLineInfo + i)->name) != 0) {
147d9f0492fSopenharmony_ci            // Check if contains ".xxx" for compatibility
148d9f0492fSopenharmony_ci            ret = snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1, ".%s",
149d9f0492fSopenharmony_ci                            (container->cmdLineInfo + i)->name);
150d9f0492fSopenharmony_ci            matched = strstr(tmpName, fullName);
151d9f0492fSopenharmony_ci            if (matched == NULL) {
152d9f0492fSopenharmony_ci                continue;
153d9f0492fSopenharmony_ci            }
154d9f0492fSopenharmony_ci            // Check if it is ended with pattern
155d9f0492fSopenharmony_ci            if (matched[ret] != '\0') {
156d9f0492fSopenharmony_ci                continue;
157d9f0492fSopenharmony_ci            }
158d9f0492fSopenharmony_ci        }
159d9f0492fSopenharmony_ci        ret = snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1,
160d9f0492fSopenharmony_ci                         OHOS_CMDLINE_PARA_PREFIX "%s", (container->cmdLineInfo + i)->name);
161d9f0492fSopenharmony_ci        if (ret <= 0) {
162d9f0492fSopenharmony_ci            continue;
163d9f0492fSopenharmony_ci        }
164d9f0492fSopenharmony_ci        if (ctx->matches[i]) {
165d9f0492fSopenharmony_ci            return PARAM_CODE_SUCCESS;
166d9f0492fSopenharmony_ci        }
167d9f0492fSopenharmony_ci        bool isSnSet = ((container->cmdLineInfo + i)->processor == SnDealFun);
168d9f0492fSopenharmony_ci        if (isSnSet && ctx->gotSn) {
169d9f0492fSopenharmony_ci            return PARAM_CODE_SUCCESS;
170d9f0492fSopenharmony_ci        }
171d9f0492fSopenharmony_ci        PARAM_LOGV("proc cmdline %s matched.", fullName);
172d9f0492fSopenharmony_ci        ret = (container->cmdLineInfo + i)->processor(fullName, nv->value);
173d9f0492fSopenharmony_ci        if (ret == 0) {
174d9f0492fSopenharmony_ci            ctx->matches[i] = true;
175d9f0492fSopenharmony_ci            if (isSnSet) {
176d9f0492fSopenharmony_ci                ctx->gotSn = true;
177d9f0492fSopenharmony_ci            }
178d9f0492fSopenharmony_ci        }
179d9f0492fSopenharmony_ci        return PARAM_CODE_SUCCESS;
180d9f0492fSopenharmony_ci    }
181d9f0492fSopenharmony_ci    return PARAM_CODE_NOT_FOUND;
182d9f0492fSopenharmony_ci}
183d9f0492fSopenharmony_ci
184d9f0492fSopenharmony_cistatic const CmdLineInfo CMDLINES[] = {
185d9f0492fSopenharmony_ci    { "hardware", CommonDealFun },
186d9f0492fSopenharmony_ci    { "bootgroup", CommonDealFun },
187d9f0492fSopenharmony_ci    { "reboot_reason", CommonDealFun },
188d9f0492fSopenharmony_ci    { "bootslots", CommonDealFun },
189d9f0492fSopenharmony_ci    { "sn", SnDealFun },
190d9f0492fSopenharmony_ci    { "root_package", CommonDealFun },
191d9f0492fSopenharmony_ci    { "serialno", SnDealFun },
192d9f0492fSopenharmony_ci    { "udid", Common2ConstDealFun },
193d9f0492fSopenharmony_ci    { "productid", Common2ConstDealFun }
194d9f0492fSopenharmony_ci};
195d9f0492fSopenharmony_ci
196d9f0492fSopenharmony_cistatic void CmdlineIterator(const NAME_VALUE_PAIR *nv, void *context)
197d9f0492fSopenharmony_ci{
198d9f0492fSopenharmony_ci    CmdLineIteratorCtx *ctx = (CmdLineIteratorCtx *)context;
199d9f0492fSopenharmony_ci    char *data = (char *)ctx->cmdline;
200d9f0492fSopenharmony_ci
201d9f0492fSopenharmony_ci    data[nv->nameEnd - data] = '\0';
202d9f0492fSopenharmony_ci    data[nv->valueEnd - data] = '\0';
203d9f0492fSopenharmony_ci    PARAM_LOGV("proc cmdline: name [%s], value [%s]", nv->name, nv->value);
204d9f0492fSopenharmony_ci
205d9f0492fSopenharmony_ci    // Get name without prefix
206d9f0492fSopenharmony_ci    const char *name = nv->name;
207d9f0492fSopenharmony_ci    if (strncmp(name, OHOS_CMDLINE_PARA_PREFIX, OHOS_CMDLINE_PARA_PREFIX_LEN) == 0) {
208d9f0492fSopenharmony_ci        name = name + OHOS_CMDLINE_PARA_PREFIX_LEN;
209d9f0492fSopenharmony_ci    }
210d9f0492fSopenharmony_ci
211d9f0492fSopenharmony_ci    CmdLineInfoContainer container = { 0 };
212d9f0492fSopenharmony_ci    container.cmdLineInfo = CMDLINES;
213d9f0492fSopenharmony_ci    container.cmdLineInfoSize = ARRAY_LENGTH(CMDLINES);
214d9f0492fSopenharmony_ci    if (MatchReserverCmdline(nv, ctx, name, &container) == 0) {
215d9f0492fSopenharmony_ci        PARAM_LOGV("match reserver cmd line success, name: %s, value: %s", nv->name, nv->value);
216d9f0492fSopenharmony_ci        return;
217d9f0492fSopenharmony_ci    }
218d9f0492fSopenharmony_ci    if (name == nv->name) {
219d9f0492fSopenharmony_ci        return;
220d9f0492fSopenharmony_ci    }
221d9f0492fSopenharmony_ci
222d9f0492fSopenharmony_ci    // cmdline with prefix but not matched, add to param by default
223d9f0492fSopenharmony_ci    PARAM_LOGI("add proc cmdline param %s by default.", nv->name);
224d9f0492fSopenharmony_ci    CommonDealFun(nv->name, nv->value);
225d9f0492fSopenharmony_ci}
226d9f0492fSopenharmony_ci
227d9f0492fSopenharmony_cistatic void GenerateSnByDefault(void)
228d9f0492fSopenharmony_ci{
229d9f0492fSopenharmony_ci    const char *snFileList [] = {
230d9f0492fSopenharmony_ci        "/sys/block/mmcblk0/device/cid",
231d9f0492fSopenharmony_ci        "/proc/bootdevice/cid"
232d9f0492fSopenharmony_ci    };
233d9f0492fSopenharmony_ci
234d9f0492fSopenharmony_ci    for (size_t i = 0; i < ARRAY_LENGTH(snFileList); i++) {
235d9f0492fSopenharmony_ci        int ret = ReadSnFromFile(OHOS_CMDLINE_PARA_PREFIX "sn", snFileList[i]);
236d9f0492fSopenharmony_ci        if (ret == 0) {
237d9f0492fSopenharmony_ci            break;
238d9f0492fSopenharmony_ci        }
239d9f0492fSopenharmony_ci    }
240d9f0492fSopenharmony_ci}
241d9f0492fSopenharmony_ci
242d9f0492fSopenharmony_ciINIT_LOCAL_API int LoadParamFromCmdLine(void)
243d9f0492fSopenharmony_ci{
244d9f0492fSopenharmony_ci    CmdLineIteratorCtx ctx;
245d9f0492fSopenharmony_ci
246d9f0492fSopenharmony_ci    ctx.gotSn = false;
247d9f0492fSopenharmony_ci    ctx.cmdline = ReadFileData(BOOT_CMD_LINE);
248d9f0492fSopenharmony_ci    PARAM_CHECK(ctx.cmdline != NULL, return -1, "Failed to read file %s", BOOT_CMD_LINE);
249d9f0492fSopenharmony_ci    bool matches[ARRAY_LENGTH(CMDLINES)] = {false};
250d9f0492fSopenharmony_ci    ctx.matches = matches;
251d9f0492fSopenharmony_ci    IterateNameValuePairs(ctx.cmdline, CmdlineIterator, (void *)(&ctx));
252d9f0492fSopenharmony_ci
253d9f0492fSopenharmony_ci    // sn is critical, it must be specified
254d9f0492fSopenharmony_ci    if (!ctx.gotSn) {
255d9f0492fSopenharmony_ci        PARAM_LOGE("Generate default sn now ...");
256d9f0492fSopenharmony_ci        GenerateSnByDefault();
257d9f0492fSopenharmony_ci    }
258d9f0492fSopenharmony_ci
259d9f0492fSopenharmony_ci    free(ctx.cmdline);
260d9f0492fSopenharmony_ci    return 0;
261d9f0492fSopenharmony_ci}
262d9f0492fSopenharmony_ci
263d9f0492fSopenharmony_ci/*
264d9f0492fSopenharmony_ci * Load parameters from files
265d9f0492fSopenharmony_ci */
266d9f0492fSopenharmony_ci
267d9f0492fSopenharmony_cistatic int LoadSecurityLabel(const char *fileName)
268d9f0492fSopenharmony_ci{
269d9f0492fSopenharmony_ci    ParamWorkSpace *paramSpace = GetParamWorkSpace();
270d9f0492fSopenharmony_ci    PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
271d9f0492fSopenharmony_ci    PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
272d9f0492fSopenharmony_ci    PARAM_CHECK(fileName != NULL, return -1, "Invalid filename for load");
273d9f0492fSopenharmony_ci#if !(defined __LITEOS_A__ || defined __LITEOS_M__)
274d9f0492fSopenharmony_ci    // load security label
275d9f0492fSopenharmony_ci    ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_DAC);
276d9f0492fSopenharmony_ci    if (ops != NULL && ops->securityGetLabel != NULL) {
277d9f0492fSopenharmony_ci        if (ops->securityGetLabel(fileName) == PARAM_CODE_REACHED_MAX) {
278d9f0492fSopenharmony_ci            PARAM_LOGE("[startup_failed]Load Security Lable failed! system reboot! %d", SYS_PARAM_INIT_FAILED);
279d9f0492fSopenharmony_ci            ExecReboot("panic");
280d9f0492fSopenharmony_ci        };
281d9f0492fSopenharmony_ci    }
282d9f0492fSopenharmony_ci#endif
283d9f0492fSopenharmony_ci    return 0;
284d9f0492fSopenharmony_ci}
285d9f0492fSopenharmony_ci
286d9f0492fSopenharmony_cistatic int LoadOneParam_(const uint32_t *context, const char *name, const char *value)
287d9f0492fSopenharmony_ci{
288d9f0492fSopenharmony_ci    uint32_t mode = *(uint32_t *)context;
289d9f0492fSopenharmony_ci    int ret = CheckParamName(name, 0);
290d9f0492fSopenharmony_ci    if (ret != 0) {
291d9f0492fSopenharmony_ci        return 0;
292d9f0492fSopenharmony_ci    }
293d9f0492fSopenharmony_ci
294d9f0492fSopenharmony_ci#ifdef SUPPORT_PARAM_LOAD_HOOK
295d9f0492fSopenharmony_ci    PARAM_LOAD_FILTER_CTX filter;
296d9f0492fSopenharmony_ci
297d9f0492fSopenharmony_ci    // Filter by hook
298d9f0492fSopenharmony_ci    filter.name = name;
299d9f0492fSopenharmony_ci    filter.value = value;
300d9f0492fSopenharmony_ci    filter.ignored = 0;
301d9f0492fSopenharmony_ci    HookMgrExecute(GetBootStageHookMgr(), INIT_PARAM_LOAD_FILTER, (void *)&filter, NULL);
302d9f0492fSopenharmony_ci
303d9f0492fSopenharmony_ci    if (filter.ignored) {
304d9f0492fSopenharmony_ci        PARAM_LOGV("Default parameter [%s] [%s] ignored", name, value);
305d9f0492fSopenharmony_ci        return 0;
306d9f0492fSopenharmony_ci    }
307d9f0492fSopenharmony_ci#endif
308d9f0492fSopenharmony_ci
309d9f0492fSopenharmony_ci    PARAM_LOGV("Add default parameter [%s] [%s]", name, value);
310d9f0492fSopenharmony_ci    return WriteParam(name, value, NULL, mode & LOAD_PARAM_ONLY_ADD);
311d9f0492fSopenharmony_ci}
312d9f0492fSopenharmony_ci
313d9f0492fSopenharmony_cistatic int LoadFileFromImport(char *target, uint32_t mode)
314d9f0492fSopenharmony_ci{
315d9f0492fSopenharmony_ci    if (strstr(target, ".para.dac")) {
316d9f0492fSopenharmony_ci        LoadSecurityLabel(target);
317d9f0492fSopenharmony_ci    } else {
318d9f0492fSopenharmony_ci        LoadDefaultParams(target, mode);
319d9f0492fSopenharmony_ci    }
320d9f0492fSopenharmony_ci    return 0;
321d9f0492fSopenharmony_ci}
322d9f0492fSopenharmony_ci
323d9f0492fSopenharmony_ci// Content format of .import.para is "import /dir/param.para"
324d9f0492fSopenharmony_ci// Use ${} to pass parameter like "import /dir/${const.product.productid}.para"
325d9f0492fSopenharmony_cistatic int LoadParamFromImport_(char *buffer, const int buffSize, uint32_t mode)
326d9f0492fSopenharmony_ci{
327d9f0492fSopenharmony_ci    int spaceCount = 0;
328d9f0492fSopenharmony_ci    while (*(buffer + IMPORT_PREFIX_LEN + spaceCount) == ' ') {
329d9f0492fSopenharmony_ci        spaceCount++;
330d9f0492fSopenharmony_ci    }
331d9f0492fSopenharmony_ci    char *target = calloc(PATH_MAX, 1);
332d9f0492fSopenharmony_ci    PARAM_CHECK(target != NULL, return -1, "Failed to alloc memory");
333d9f0492fSopenharmony_ci    if (strncpy_s(target, PATH_MAX, buffer + IMPORT_PREFIX_LEN + spaceCount, buffSize) != 0) {
334d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to get value of import.");
335d9f0492fSopenharmony_ci        free(target);
336d9f0492fSopenharmony_ci        return -1;
337d9f0492fSopenharmony_ci    }
338d9f0492fSopenharmony_ci    char *tmp = NULL;
339d9f0492fSopenharmony_ci    if ((tmp = strstr(target, "\n"))) {
340d9f0492fSopenharmony_ci        *tmp = '\0';
341d9f0492fSopenharmony_ci    }
342d9f0492fSopenharmony_ci    char *tmpParamValue = calloc(PARAM_VALUE_LEN_MAX + 1, sizeof(char));
343d9f0492fSopenharmony_ci    if (tmpParamValue == NULL) {
344d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to alloc memory");
345d9f0492fSopenharmony_ci        free(target);
346d9f0492fSopenharmony_ci        return -1;
347d9f0492fSopenharmony_ci    }
348d9f0492fSopenharmony_ci    int ret = GetParamValue(target, strlen(target), tmpParamValue, PARAM_VALUE_LEN_MAX);
349d9f0492fSopenharmony_ci    if (ret == 0) {
350d9f0492fSopenharmony_ci        LoadFileFromImport(tmpParamValue, mode);
351d9f0492fSopenharmony_ci    }
352d9f0492fSopenharmony_ci    PARAM_LOGI("Load params from import %s return %d.", tmpParamValue, ret);
353d9f0492fSopenharmony_ci    free(tmpParamValue);
354d9f0492fSopenharmony_ci    free(target);
355d9f0492fSopenharmony_ci    return ret;
356d9f0492fSopenharmony_ci}
357d9f0492fSopenharmony_ci
358d9f0492fSopenharmony_cistatic int LoadParamFromImport(const char *fileName, void *context)
359d9f0492fSopenharmony_ci{
360d9f0492fSopenharmony_ci    char realPath[PATH_MAX] = "";
361d9f0492fSopenharmony_ci    realpath(fileName, realPath);
362d9f0492fSopenharmony_ci    FILE *fp = fopen(realPath, "r");
363d9f0492fSopenharmony_ci    if (fp == NULL) {
364d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to open file '%s' error:%d ", fileName, errno);
365d9f0492fSopenharmony_ci        return -1;
366d9f0492fSopenharmony_ci    }
367d9f0492fSopenharmony_ci
368d9f0492fSopenharmony_ci    const int buffSize = PATH_MAX;
369d9f0492fSopenharmony_ci    char *buffer = calloc(buffSize, sizeof(char));
370d9f0492fSopenharmony_ci    PARAM_CHECK(buffer != NULL, (void)fclose(fp);
371d9f0492fSopenharmony_ci        return -1, "Failed to alloc memory");
372d9f0492fSopenharmony_ci
373d9f0492fSopenharmony_ci    uint32_t mode = *(int *)context;
374d9f0492fSopenharmony_ci    while (fgets(buffer, buffSize, fp) != NULL) {
375d9f0492fSopenharmony_ci        buffer[buffSize - 1] = '\0';
376d9f0492fSopenharmony_ci        if (!strncmp(buffer, "import ", IMPORT_PREFIX_LEN)) {
377d9f0492fSopenharmony_ci            (void)LoadParamFromImport_(buffer, buffSize, mode);
378d9f0492fSopenharmony_ci        }
379d9f0492fSopenharmony_ci    }
380d9f0492fSopenharmony_ci    (void)fclose(fp);
381d9f0492fSopenharmony_ci    free(buffer);
382d9f0492fSopenharmony_ci    return 0;
383d9f0492fSopenharmony_ci}
384d9f0492fSopenharmony_ci
385d9f0492fSopenharmony_cistatic int LoadDefaultParam_(const char *fileName, uint32_t mode,
386d9f0492fSopenharmony_ci    const char *exclude[], uint32_t count, int (*loadOneParam)(const uint32_t *, const char *, const char *))
387d9f0492fSopenharmony_ci{
388d9f0492fSopenharmony_ci    uint32_t paramNum = 0;
389d9f0492fSopenharmony_ci    char realPath[PATH_MAX] = "";
390d9f0492fSopenharmony_ci    realpath(fileName, realPath);
391d9f0492fSopenharmony_ci    FILE *fp = fopen(realPath, "r");
392d9f0492fSopenharmony_ci    if (fp == NULL) {
393d9f0492fSopenharmony_ci        PARAM_LOGW("Failed to open file '%s' error:%d ", fileName, errno);
394d9f0492fSopenharmony_ci        return -1;
395d9f0492fSopenharmony_ci    }
396d9f0492fSopenharmony_ci
397d9f0492fSopenharmony_ci    const int buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10;  // 10 max len
398d9f0492fSopenharmony_ci    char *buffer = calloc(buffSize, sizeof(char));
399d9f0492fSopenharmony_ci    PARAM_CHECK(buffer != NULL, (void)fclose(fp);
400d9f0492fSopenharmony_ci        return -1, "Failed to alloc memory");
401d9f0492fSopenharmony_ci
402d9f0492fSopenharmony_ci    while (fgets(buffer, buffSize, fp) != NULL) {
403d9f0492fSopenharmony_ci        buffer[buffSize - 1] = '\0';
404d9f0492fSopenharmony_ci        int ret = SplitParamString(buffer, exclude, count, loadOneParam, &mode);
405d9f0492fSopenharmony_ci        PARAM_ONLY_CHECK(ret != PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH,
406d9f0492fSopenharmony_ci                        (void)fclose(fp); free(buffer); return PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH);
407d9f0492fSopenharmony_ci        if (mode == LOAD_PARAM_ONLY_ADD && ret == PARAM_CODE_READ_ONLY) {
408d9f0492fSopenharmony_ci            PARAM_WARNING_CHECK(ret == 0, continue, "Set param '%s' error:%d with only add mode", buffer, ret);
409d9f0492fSopenharmony_ci        } else {
410d9f0492fSopenharmony_ci            PARAM_CHECK(ret == 0, continue, "Failed to set param '%s' error:%d ", buffer, ret);
411d9f0492fSopenharmony_ci        }
412d9f0492fSopenharmony_ci        paramNum++;
413d9f0492fSopenharmony_ci    }
414d9f0492fSopenharmony_ci    (void)fclose(fp);
415d9f0492fSopenharmony_ci    free(buffer);
416d9f0492fSopenharmony_ci    PARAM_LOGV("Load %u default parameters success from %s.", paramNum, fileName);
417d9f0492fSopenharmony_ci    return 0;
418d9f0492fSopenharmony_ci}
419d9f0492fSopenharmony_ci
420d9f0492fSopenharmony_cistatic int ProcessParamFile(const char *fileName, void *context)
421d9f0492fSopenharmony_ci{
422d9f0492fSopenharmony_ci    static const char *exclude[] = {"ctl.", "selinux.restorecon_recursive"};
423d9f0492fSopenharmony_ci    uint32_t mode = *(int *)context;
424d9f0492fSopenharmony_ci    int ret = LoadDefaultParam_(fileName, mode, exclude, ARRAY_LENGTH(exclude), LoadOneParam_);
425d9f0492fSopenharmony_ci    if (ret == PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH) {
426d9f0492fSopenharmony_ci        PARAM_LOGE("[startup_failed]default_param memory is not enough, system reboot! %d", SYS_PARAM_INIT_FAILED);
427d9f0492fSopenharmony_ci        ExecReboot("panic");
428d9f0492fSopenharmony_ci    }
429d9f0492fSopenharmony_ci    return ret;
430d9f0492fSopenharmony_ci}
431d9f0492fSopenharmony_ci
432d9f0492fSopenharmony_ciint LoadParamsFile(const char *fileName, bool onlyAdd)
433d9f0492fSopenharmony_ci{
434d9f0492fSopenharmony_ci    return LoadDefaultParams(fileName, onlyAdd ? LOAD_PARAM_ONLY_ADD : LOAD_PARAM_NORMAL);
435d9f0492fSopenharmony_ci}
436d9f0492fSopenharmony_ci
437d9f0492fSopenharmony_ciint LoadDefaultParams(const char *fileName, uint32_t mode)
438d9f0492fSopenharmony_ci{
439d9f0492fSopenharmony_ci    PARAM_CHECK(fileName != NULL, return -1, "Invalid filename for load");
440d9f0492fSopenharmony_ci    PARAM_LOGI("Load default parameters from %s.", fileName);
441d9f0492fSopenharmony_ci    struct stat st;
442d9f0492fSopenharmony_ci    if ((stat(fileName, &st) == 0) && !S_ISDIR(st.st_mode)) {
443d9f0492fSopenharmony_ci        if (strstr(fileName, ".para.dac")) {
444d9f0492fSopenharmony_ci            return LoadSecurityLabel(fileName);
445d9f0492fSopenharmony_ci        } else {
446d9f0492fSopenharmony_ci            return ProcessParamFile(fileName, &mode);
447d9f0492fSopenharmony_ci        }
448d9f0492fSopenharmony_ci    } else {
449d9f0492fSopenharmony_ci        (void)ReadFileInDir(fileName, ".para", ProcessParamFile, &mode);
450d9f0492fSopenharmony_ci        (void)ReadFileInDir(fileName, ".para.import", LoadParamFromImport, &mode);
451d9f0492fSopenharmony_ci        return LoadSecurityLabel(fileName);
452d9f0492fSopenharmony_ci    }
453d9f0492fSopenharmony_ci}
454d9f0492fSopenharmony_ci
455d9f0492fSopenharmony_ciINIT_LOCAL_API void LoadParamFromBuild(void)
456d9f0492fSopenharmony_ci{
457d9f0492fSopenharmony_ci    PARAM_LOGI("load parameters from build ");
458d9f0492fSopenharmony_ci#ifdef INCREMENTAL_VERSION
459d9f0492fSopenharmony_ci    if (strlen(INCREMENTAL_VERSION) > 0) {
460d9f0492fSopenharmony_ci        WriteParam("const.product.incremental.version", INCREMENTAL_VERSION, NULL, LOAD_PARAM_NORMAL);
461d9f0492fSopenharmony_ci    }
462d9f0492fSopenharmony_ci#endif
463d9f0492fSopenharmony_ci#ifdef BUILD_TYPE
464d9f0492fSopenharmony_ci    if (strlen(BUILD_TYPE) > 0) {
465d9f0492fSopenharmony_ci        WriteParam("const.product.build.type", BUILD_TYPE, NULL, LOAD_PARAM_NORMAL);
466d9f0492fSopenharmony_ci    }
467d9f0492fSopenharmony_ci#endif
468d9f0492fSopenharmony_ci#ifdef BUILD_USER
469d9f0492fSopenharmony_ci    if (strlen(BUILD_USER) > 0) {
470d9f0492fSopenharmony_ci        WriteParam("const.product.build.user", BUILD_USER, NULL, LOAD_PARAM_NORMAL);
471d9f0492fSopenharmony_ci    }
472d9f0492fSopenharmony_ci#endif
473d9f0492fSopenharmony_ci#ifdef BUILD_TIME
474d9f0492fSopenharmony_ci    if (strlen(BUILD_TIME) > 0) {
475d9f0492fSopenharmony_ci        WriteParam("const.product.build.date", BUILD_TIME, NULL, LOAD_PARAM_NORMAL);
476d9f0492fSopenharmony_ci    }
477d9f0492fSopenharmony_ci#endif
478d9f0492fSopenharmony_ci#ifdef BUILD_HOST
479d9f0492fSopenharmony_ci    if (strlen(BUILD_HOST) > 0) {
480d9f0492fSopenharmony_ci        WriteParam("const.product.build.host", BUILD_HOST, NULL, LOAD_PARAM_NORMAL);
481d9f0492fSopenharmony_ci    }
482d9f0492fSopenharmony_ci#endif
483d9f0492fSopenharmony_ci#ifdef BUILD_ROOTHASH
484d9f0492fSopenharmony_ci    if (strlen(BUILD_ROOTHASH) > 0) {
485d9f0492fSopenharmony_ci        WriteParam("const.ohos.buildroothash", BUILD_ROOTHASH, NULL, LOAD_PARAM_NORMAL);
486d9f0492fSopenharmony_ci    }
487d9f0492fSopenharmony_ci#endif
488d9f0492fSopenharmony_ci}
489d9f0492fSopenharmony_ci
490d9f0492fSopenharmony_cistatic int LoadOneParamAreaSize_(const uint32_t *context, const char *name, const char *value)
491d9f0492fSopenharmony_ci{
492d9f0492fSopenharmony_ci    uint32_t size = (uint32_t)strtoul(value, NULL, DECIMAL_BASE);
493d9f0492fSopenharmony_ci    PARAM_LOGV("LoadOneParamAreaSize_ [%s] [%s]", name, value);
494d9f0492fSopenharmony_ci    ParamWorkSpace *paramSpace = GetParamWorkSpace();
495d9f0492fSopenharmony_ci    PARAM_CHECK(paramSpace != NULL && paramSpace->workSpace != NULL,
496d9f0492fSopenharmony_ci        return -1, "Invalid workspace name %s", name);
497d9f0492fSopenharmony_ci    WorkSpaceSize *spaceSize = GetWorkSpaceSize(GetWorkSpace(WORKSPACE_INDEX_SIZE));
498d9f0492fSopenharmony_ci    PARAM_CHECK(spaceSize != NULL, return PARAM_CODE_ERROR, "Failed to get workspace size");
499d9f0492fSopenharmony_ci    static char buffer[SELINUX_CONTENT_LEN] = {0};
500d9f0492fSopenharmony_ci    int ret = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "u:object_r:%s:s0", name);
501d9f0492fSopenharmony_ci    PARAM_CHECK(ret > 0, return PARAM_CODE_ERROR, "Failed to snprintf workspace name");
502d9f0492fSopenharmony_ci
503d9f0492fSopenharmony_ci    for (uint32_t i = WORKSPACE_INDEX_BASE + 1; i < spaceSize->maxLabelIndex; i++) {
504d9f0492fSopenharmony_ci        if (paramSpace->workSpace[i] == NULL) {
505d9f0492fSopenharmony_ci            continue;
506d9f0492fSopenharmony_ci        }
507d9f0492fSopenharmony_ci        if (strcmp(paramSpace->workSpace[i]->fileName, buffer) == 0) {
508d9f0492fSopenharmony_ci            spaceSize->spaceSize[i] = size;
509d9f0492fSopenharmony_ci            paramSpace->workSpace[i]->spaceSize = size;
510d9f0492fSopenharmony_ci            break;
511d9f0492fSopenharmony_ci        }
512d9f0492fSopenharmony_ci    }
513d9f0492fSopenharmony_ci    return 0;
514d9f0492fSopenharmony_ci}
515d9f0492fSopenharmony_ci
516d9f0492fSopenharmony_ciINIT_LOCAL_API void LoadParamAreaSize(void)
517d9f0492fSopenharmony_ci{
518d9f0492fSopenharmony_ci    LoadDefaultParam_("/sys_prod/etc/param/ohos.para.size", 0, NULL, 0, LoadOneParamAreaSize_);
519d9f0492fSopenharmony_ci    LoadDefaultParam_(PARAM_AREA_SIZE_CFG, 0, NULL, 0, LoadOneParamAreaSize_);
520d9f0492fSopenharmony_ci}
521