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