1d9f0492fSopenharmony_ci
2d9f0492fSopenharmony_ci/*
3d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
4d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
5d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
6d9f0492fSopenharmony_ci * You may obtain a copy of the License at
7d9f0492fSopenharmony_ci *
8d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
9d9f0492fSopenharmony_ci *
10d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
11d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
12d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
14d9f0492fSopenharmony_ci * limitations under the License.
15d9f0492fSopenharmony_ci */
16d9f0492fSopenharmony_ci
17d9f0492fSopenharmony_ci#include "init_hook.h"
18d9f0492fSopenharmony_ci#include "init_service.h"
19d9f0492fSopenharmony_ci#include "init_utils.h"
20d9f0492fSopenharmony_ci#include "plugin_adapter.h"
21d9f0492fSopenharmony_ci#include "securec.h"
22d9f0492fSopenharmony_ci#include "init_module_engine.h"
23d9f0492fSopenharmony_ci#include "init_group_manager.h"
24d9f0492fSopenharmony_ci#include "init_param.h"
25d9f0492fSopenharmony_ci#include "hookmgr.h"
26d9f0492fSopenharmony_ci#include "bootstage.h"
27d9f0492fSopenharmony_ci
28d9f0492fSopenharmony_cistatic int ServiceExtDataCompareProc(ListNode *node, void *data)
29d9f0492fSopenharmony_ci{
30d9f0492fSopenharmony_ci    ServiceExtData *item = ListEntry(node, ServiceExtData, node);
31d9f0492fSopenharmony_ci    if (item->dataId == *(uint32_t *)data) {
32d9f0492fSopenharmony_ci        return 0;
33d9f0492fSopenharmony_ci    }
34d9f0492fSopenharmony_ci    return -1;
35d9f0492fSopenharmony_ci}
36d9f0492fSopenharmony_ci
37d9f0492fSopenharmony_cistatic ServiceExtData *GetServiceExtData_(Service *service, uint32_t id)
38d9f0492fSopenharmony_ci{
39d9f0492fSopenharmony_ci    ListNode *node = OH_ListFind(&service->extDataNode, (void *)&id, ServiceExtDataCompareProc);
40d9f0492fSopenharmony_ci    return (ServiceExtData *)node;
41d9f0492fSopenharmony_ci}
42d9f0492fSopenharmony_ci
43d9f0492fSopenharmony_ciServiceExtData *AddServiceExtData(const char *serviceName, uint32_t id, void *data, uint32_t dataLen)
44d9f0492fSopenharmony_ci{
45d9f0492fSopenharmony_ci    Service *service = GetServiceByName(serviceName);
46d9f0492fSopenharmony_ci    PLUGIN_CHECK(service != NULL, return NULL, "Can not find service for %s", serviceName);
47d9f0492fSopenharmony_ci    ServiceExtData *extData = GetServiceExtData_(service, id);
48d9f0492fSopenharmony_ci    if (extData != NULL) {
49d9f0492fSopenharmony_ci        return NULL;
50d9f0492fSopenharmony_ci    }
51d9f0492fSopenharmony_ci    extData = calloc(1, sizeof(ServiceExtData) + dataLen);
52d9f0492fSopenharmony_ci    PLUGIN_CHECK(extData != NULL, return NULL, "Can not alloc extData for %d", id);
53d9f0492fSopenharmony_ci    OH_ListInit(&extData->node);
54d9f0492fSopenharmony_ci    extData->dataId = id;
55d9f0492fSopenharmony_ci    if (data != NULL) {
56d9f0492fSopenharmony_ci        int ret = memcpy_s(extData->data, dataLen, data, dataLen);
57d9f0492fSopenharmony_ci        if (ret == 0) {
58d9f0492fSopenharmony_ci            OH_ListAddTail(&service->extDataNode, &extData->node);
59d9f0492fSopenharmony_ci            return extData;
60d9f0492fSopenharmony_ci        }
61d9f0492fSopenharmony_ci    } else {
62d9f0492fSopenharmony_ci        OH_ListAddTail(&service->extDataNode, &extData->node);
63d9f0492fSopenharmony_ci        return extData;
64d9f0492fSopenharmony_ci    }
65d9f0492fSopenharmony_ci    free(extData);
66d9f0492fSopenharmony_ci    return NULL;
67d9f0492fSopenharmony_ci}
68d9f0492fSopenharmony_ci
69d9f0492fSopenharmony_civoid DelServiceExtData(const char *serviceName, uint32_t id)
70d9f0492fSopenharmony_ci{
71d9f0492fSopenharmony_ci    Service *service = GetServiceByName(serviceName);
72d9f0492fSopenharmony_ci    PLUGIN_CHECK(service != NULL, return, "Can not find service for %s", serviceName);
73d9f0492fSopenharmony_ci    ServiceExtData *extData = GetServiceExtData_(service, id);
74d9f0492fSopenharmony_ci    if (extData == NULL) {
75d9f0492fSopenharmony_ci        return;
76d9f0492fSopenharmony_ci    }
77d9f0492fSopenharmony_ci    OH_ListRemove(&extData->node);
78d9f0492fSopenharmony_ci    free(extData);
79d9f0492fSopenharmony_ci}
80d9f0492fSopenharmony_ci
81d9f0492fSopenharmony_ciServiceExtData *GetServiceExtData(const char *serviceName, uint32_t id)
82d9f0492fSopenharmony_ci{
83d9f0492fSopenharmony_ci    Service *service = GetServiceByName(serviceName);
84d9f0492fSopenharmony_ci    PLUGIN_CHECK (service != NULL, return NULL, "Can not find service for %s", serviceName);
85d9f0492fSopenharmony_ci    return GetServiceExtData_(service, id);
86d9f0492fSopenharmony_ci}
87d9f0492fSopenharmony_ci
88d9f0492fSopenharmony_cistatic int JobParseHookWrapper(const HOOK_INFO *hookInfo, void *executionContext)
89d9f0492fSopenharmony_ci{
90d9f0492fSopenharmony_ci    JOB_PARSE_CTX *jobParseContext = (JOB_PARSE_CTX *)executionContext;
91d9f0492fSopenharmony_ci    JobParseHook realHook = (JobParseHook)hookInfo->hookCookie;
92d9f0492fSopenharmony_ci    realHook(jobParseContext);
93d9f0492fSopenharmony_ci    return 0;
94d9f0492fSopenharmony_ci};
95d9f0492fSopenharmony_ci
96d9f0492fSopenharmony_ciint InitAddJobParseHook(JobParseHook hook)
97d9f0492fSopenharmony_ci{
98d9f0492fSopenharmony_ci    HOOK_INFO info;
99d9f0492fSopenharmony_ci    info.stage = INIT_JOB_PARSE;
100d9f0492fSopenharmony_ci    info.prio = 0;
101d9f0492fSopenharmony_ci    info.hook = JobParseHookWrapper;
102d9f0492fSopenharmony_ci    info.hookCookie = (void *)hook;
103d9f0492fSopenharmony_ci
104d9f0492fSopenharmony_ci    return HookMgrAddEx(GetBootStageHookMgr(), &info);
105d9f0492fSopenharmony_ci}
106d9f0492fSopenharmony_ci
107d9f0492fSopenharmony_cistatic void SetLogLevelFunc(const char *value)
108d9f0492fSopenharmony_ci{
109d9f0492fSopenharmony_ci    unsigned int level;
110d9f0492fSopenharmony_ci    int ret = StringToUint(value, &level);
111d9f0492fSopenharmony_ci    PLUGIN_CHECK(ret == 0, return, "Failed make %s to unsigned int", value);
112d9f0492fSopenharmony_ci    PLUGIN_LOGI("Set log level is %d", level);
113d9f0492fSopenharmony_ci    SetInitLogLevel(level);
114d9f0492fSopenharmony_ci}
115d9f0492fSopenharmony_ci
116d9f0492fSopenharmony_cistatic int CmdSetLogLevel(int id, const char *name, int argc, const char **argv)
117d9f0492fSopenharmony_ci{
118d9f0492fSopenharmony_ci    UNUSED(id);
119d9f0492fSopenharmony_ci    UNUSED(name);
120d9f0492fSopenharmony_ci    PLUGIN_CHECK(argc >= 1, return -1, "Invalid input args");
121d9f0492fSopenharmony_ci    const char *value = strrchr(argv[0], '.');
122d9f0492fSopenharmony_ci    PLUGIN_CHECK(value != NULL, return -1, "Failed get \'.\' from string %s", argv[0]);
123d9f0492fSopenharmony_ci    SetLogLevelFunc(value + 1);
124d9f0492fSopenharmony_ci    return 0;
125d9f0492fSopenharmony_ci}
126d9f0492fSopenharmony_ci
127d9f0492fSopenharmony_cistatic int InitCmd(int id, const char *name, int argc, const char **argv)
128d9f0492fSopenharmony_ci{
129d9f0492fSopenharmony_ci    UNUSED(id);
130d9f0492fSopenharmony_ci    // process cmd by name
131d9f0492fSopenharmony_ci    PLUGIN_LOGI("InitCmd %s argc %d", name, argc);
132d9f0492fSopenharmony_ci    if (argc > 1 && strcmp(argv[0], "setloglevel") == 0) {
133d9f0492fSopenharmony_ci        SetLogLevelFunc(argv[1]);
134d9f0492fSopenharmony_ci    }
135d9f0492fSopenharmony_ci    return 0;
136d9f0492fSopenharmony_ci}
137d9f0492fSopenharmony_ci
138d9f0492fSopenharmony_cistatic int ParamSetInitCmdHook(const HOOK_INFO *hookInfo, void *cookie)
139d9f0492fSopenharmony_ci{
140d9f0492fSopenharmony_ci    AddCmdExecutor("setloglevel", CmdSetLogLevel);
141d9f0492fSopenharmony_ci    AddCmdExecutor("initcmd", InitCmd);
142d9f0492fSopenharmony_ci    return 0;
143d9f0492fSopenharmony_ci}
144d9f0492fSopenharmony_ci
145d9f0492fSopenharmony_cistatic int DumpTrigger(const char *fmt, ...)
146d9f0492fSopenharmony_ci{
147d9f0492fSopenharmony_ci    va_list vargs;
148d9f0492fSopenharmony_ci    va_start(vargs, fmt);
149d9f0492fSopenharmony_ci    InitLog(INIT_INFO, INIT_LOG_DOMAIN, INIT_LOG_TAG, fmt, vargs);
150d9f0492fSopenharmony_ci    va_end(vargs);
151d9f0492fSopenharmony_ci    return 0;
152d9f0492fSopenharmony_ci}
153d9f0492fSopenharmony_ci
154d9f0492fSopenharmony_cistatic void DumpServiceHook(void)
155d9f0492fSopenharmony_ci{
156d9f0492fSopenharmony_ci    // check and dump all jobs
157d9f0492fSopenharmony_ci    char dump[8] = {0}; // 8 len
158d9f0492fSopenharmony_ci    uint32_t len = sizeof(dump);
159d9f0492fSopenharmony_ci    (void)SystemReadParam("persist.init.debug.dump.trigger", dump, &len);
160d9f0492fSopenharmony_ci    PLUGIN_LOGV("boot dump trigger %s", dump);
161d9f0492fSopenharmony_ci    if (strcmp(dump, "1") == 0) {
162d9f0492fSopenharmony_ci        SystemDumpTriggers(1, DumpTrigger);
163d9f0492fSopenharmony_ci    }
164d9f0492fSopenharmony_ci    return;
165d9f0492fSopenharmony_ci}
166d9f0492fSopenharmony_ci
167d9f0492fSopenharmony_cistatic void InitLogLevelFromPersist(void)
168d9f0492fSopenharmony_ci{
169d9f0492fSopenharmony_ci    char logLevel[2] = {0}; // 2 is set param "persist.init.debug.loglevel" value length.
170d9f0492fSopenharmony_ci    uint32_t len = sizeof(logLevel);
171d9f0492fSopenharmony_ci    int ret = SystemReadParam(INIT_DEBUG_LEVEL, logLevel, &len);
172d9f0492fSopenharmony_ci    INIT_INFO_CHECK(ret == 0, return, "Can not get log level from param, keep the original loglevel.");
173d9f0492fSopenharmony_ci    SetLogLevelFunc(logLevel);
174d9f0492fSopenharmony_ci    return;
175d9f0492fSopenharmony_ci}
176d9f0492fSopenharmony_ci
177d9f0492fSopenharmony_cistatic int InitDebugHook(const HOOK_INFO *info, void *cookie)
178d9f0492fSopenharmony_ci{
179d9f0492fSopenharmony_ci    UNUSED(info);
180d9f0492fSopenharmony_ci    UNUSED(cookie);
181d9f0492fSopenharmony_ci    InitLogLevelFromPersist();
182d9f0492fSopenharmony_ci    DumpServiceHook();
183d9f0492fSopenharmony_ci    return 0;
184d9f0492fSopenharmony_ci}
185d9f0492fSopenharmony_ci
186d9f0492fSopenharmony_ci// clear extend memory
187d9f0492fSopenharmony_cistatic int BootCompleteCmd(const HOOK_INFO *hookInfo, void *executionContext)
188d9f0492fSopenharmony_ci{
189d9f0492fSopenharmony_ci    PLUGIN_LOGI("boot start complete");
190d9f0492fSopenharmony_ci    UNUSED(hookInfo);
191d9f0492fSopenharmony_ci    UNUSED(executionContext);
192d9f0492fSopenharmony_ci
193d9f0492fSopenharmony_ci    // clear hook
194d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_GLOBAL_INIT, NULL);
195d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_PRE_PARAM_SERVICE, NULL);
196d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_PARAM_LOAD_FILTER, NULL);
197d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, NULL);
198d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, NULL);
199d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_SERVICE_PARSE, NULL);
200d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, NULL);
201d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, NULL);
202d9f0492fSopenharmony_ci    HookMgrDel(GetBootStageHookMgr(), INIT_JOB_PARSE, NULL);
203d9f0492fSopenharmony_ci    // clear cmd
204d9f0492fSopenharmony_ci    RemoveCmdExecutor("loadSelinuxPolicy", -1);
205d9f0492fSopenharmony_ci
206d9f0492fSopenharmony_ci    PluginExecCmdByName("init_trace", "stop");
207d9f0492fSopenharmony_ci    // uninstall module of inittrace
208d9f0492fSopenharmony_ci    InitModuleMgrUnInstall("inittrace");
209d9f0492fSopenharmony_ci    return 0;
210d9f0492fSopenharmony_ci}
211d9f0492fSopenharmony_ci
212d9f0492fSopenharmony_ciMODULE_CONSTRUCTOR(void)
213d9f0492fSopenharmony_ci{
214d9f0492fSopenharmony_ci    HookMgrAdd(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, 0, BootCompleteCmd);
215d9f0492fSopenharmony_ci    InitAddGlobalInitHook(0, ParamSetInitCmdHook);
216d9f0492fSopenharmony_ci    // Depends on parameter service
217d9f0492fSopenharmony_ci    InitAddPostPersistParamLoadHook(0, InitDebugHook);
218d9f0492fSopenharmony_ci}
219