• 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 <errno.h>
16 
17 #include "bootstage.h"
18 #include "hookmgr.h"
19 #include "init_hook.h"
20 #include "init_module_engine.h"
21 #include "plugin_adapter.h"
22 #include "securec.h"
23 
24 #define REBOOT_NAME_PREFIX "reboot,"
25 #define REBOOT_CMD_PREFIX "reboot."
26 #define REBOOT_REPLACE_PREFIX "reboot."
27 #define PARAM_CMD_MAX 100
28 
RebootHookWrapper(const HOOK_INFO * hookInfo,void * executionContext)29 static int RebootHookWrapper(const HOOK_INFO *hookInfo, void *executionContext)
30 {
31     RebootHookCtx *ctx = (RebootHookCtx *)executionContext;
32     InitRebootHook realHook = (InitRebootHook)hookInfo->hookCookie;
33     realHook(ctx);
34     return 0;
35 };
36 
InitAddRebootHook(InitRebootHook hook)37 int InitAddRebootHook(InitRebootHook hook)
38 {
39     HOOK_INFO info;
40     info.stage = INIT_REBOOT;
41     info.prio = 0;
42     info.hook = RebootHookWrapper;
43     info.hookCookie = (void *)hook;
44     return HookMgrAddEx(GetBootStageHookMgr(), &info);
45 }
46 
47 static ParamCmdInfo *g_rebootParamCmdInfos = NULL;
48 static int g_rebootParamCmdMaxNumber = 0;
49 static int g_rebootParamCmdValidNumber = 0;
Dup2String(const char * prefix,const char * str)50 static char *Dup2String(const char *prefix, const char *str)
51 {
52     if (str == NULL) {
53         return strdup("reboot");
54     }
55     size_t len = strlen(prefix) + strlen(str) + 1;
56     char *tmp = calloc(1, len);
57     PLUGIN_CHECK(tmp != NULL, return NULL, "Failed to alloc %s %s", prefix, str);
58     int ret = sprintf_s(tmp, len, "%s%s", prefix, str);
59     PLUGIN_CHECK(ret > 0, free(tmp);
60         return NULL, "Failed to sprintf %s %s", prefix, str);
61     return tmp;
62 }
63 
CheckParamCmdExist(const char * cmd)64 static int CheckParamCmdExist(const char *cmd)
65 {
66     if (g_rebootParamCmdInfos == NULL) {
67         return 0;
68     }
69     char *cmdName = Dup2String(REBOOT_CMD_PREFIX, cmd);
70     PLUGIN_CHECK(cmdName != NULL, return 0, "Failed to copy %s", cmd);
71     for (int i = 0; i < g_rebootParamCmdValidNumber; i++) {
72         if (strcmp(g_rebootParamCmdInfos[i].cmd, cmdName) == 0) {
73             free(cmdName);
74             return 1;
75         }
76     }
77     free(cmdName);
78     return 0;
79 }
80 
SetParamCmdInfo(ParamCmdInfo * currInfo,CmdExecutor executor,const char * cmd)81 static int SetParamCmdInfo(ParamCmdInfo *currInfo, CmdExecutor executor, const char *cmd)
82 {
83     do {
84         currInfo->name = Dup2String(REBOOT_NAME_PREFIX, cmd);
85         PLUGIN_CHECK(currInfo->name != NULL, break, "Failed to copy %s", cmd);
86         currInfo->replace = Dup2String(REBOOT_REPLACE_PREFIX, cmd);
87         PLUGIN_CHECK(currInfo->replace != NULL, break, "Failed to copy %s", cmd);
88         currInfo->cmd = Dup2String(REBOOT_CMD_PREFIX, cmd);
89         PLUGIN_CHECK(currInfo->cmd != NULL, break, "Failed to copy %s", cmd);
90         if (executor != NULL) {
91             int cmdId = AddCmdExecutor(currInfo->cmd, executor);
92             PLUGIN_CHECK(cmdId > 0, break, "Failed to add cmd %s", cmd);
93         }
94         PLUGIN_LOGV("SetParamCmdInfo '%s' '%s' '%s' ", currInfo->name, currInfo->cmd, currInfo->replace);
95         currInfo = NULL;
96         g_rebootParamCmdValidNumber++;
97         return 0;
98     } while (0);
99     if (currInfo != NULL) {
100         if (currInfo->name != NULL) {
101             free(currInfo->name);
102         }
103         if (currInfo->cmd != NULL) {
104             free(currInfo->cmd);
105         }
106         if (currInfo->replace != NULL) {
107             free(currInfo->replace);
108         }
109     }
110     return -1;
111 }
112 
AddRebootCmdExecutor_(const char * cmd,CmdExecutor executor)113 static int AddRebootCmdExecutor_(const char *cmd, CmdExecutor executor)
114 {
115     PLUGIN_CHECK(g_rebootParamCmdMaxNumber <= PARAM_CMD_MAX, return -1, "Param cmd max number exceed limit");
116     if (g_rebootParamCmdMaxNumber == 0 || g_rebootParamCmdMaxNumber <= g_rebootParamCmdValidNumber) {
117         g_rebootParamCmdMaxNumber += 5; // inc 5 once time
118         ParamCmdInfo *cmdInfos = calloc(1, sizeof(ParamCmdInfo) * g_rebootParamCmdMaxNumber);
119         PLUGIN_CHECK(cmdInfos != NULL, return -1, "Failed to add reboot cmd %s", cmd);
120         if (g_rebootParamCmdInfos != NULL) { // delete old
121             // copy from old
122             for (int i = 0; i < g_rebootParamCmdValidNumber; i++) {
123                 cmdInfos[i].name = g_rebootParamCmdInfos[i].name;
124                 cmdInfos[i].replace = g_rebootParamCmdInfos[i].replace;
125                 cmdInfos[i].cmd = g_rebootParamCmdInfos[i].cmd;
126             }
127             free(g_rebootParamCmdInfos);
128         }
129         g_rebootParamCmdInfos = cmdInfos;
130     }
131     PLUGIN_CHECK(g_rebootParamCmdValidNumber >= 0 && g_rebootParamCmdValidNumber < g_rebootParamCmdMaxNumber,
132         return -1, "Param cmd number exceed limit");
133     return SetParamCmdInfo(&g_rebootParamCmdInfos[g_rebootParamCmdValidNumber], executor, cmd);
134 }
135 
AddRebootCmdExecutor(const char * cmd,CmdExecutor executor)136 int AddRebootCmdExecutor(const char *cmd, CmdExecutor executor)
137 {
138     PLUGIN_CHECK(cmd != NULL && executor != NULL, return EINVAL, "Invalid input parameter");
139     int ret = CheckParamCmdExist(cmd);
140     if (ret != 0) {
141         PLUGIN_LOGI("Cmd %s exist", cmd);
142         return EEXIST;
143     }
144     return AddRebootCmdExecutor_(cmd, executor);
145 }
146 
GetStartupPowerCtl(size_t * size)147 const ParamCmdInfo *GetStartupPowerCtl(size_t *size)
148 {
149     RebootHookCtx context;
150     context.reason = "";
151     (void)HookMgrExecute(GetBootStageHookMgr(), INIT_REBOOT, (void *)(&context), NULL);
152     PLUGIN_LOGI("After install reboot module");
153     *size = g_rebootParamCmdValidNumber;
154     return g_rebootParamCmdInfos;
155 }
156 
InitRebootHook_(RebootHookCtx * ctx)157 static void InitRebootHook_(RebootHookCtx *ctx)
158 {
159 #ifndef STARTUP_INIT_TEST // do not install
160     ModuleMgrScan("init/reboot");
161 #endif
162     PLUGIN_LOGI("Install rebootmodule.");
163 }
164 
MODULE_CONSTRUCTOR(void)165 MODULE_CONSTRUCTOR(void)
166 {
167     // 执行reboot时调用,安装reboot模块
168     InitAddRebootHook(InitRebootHook_);
169 }
170 
MODULE_DESTRUCTOR(void)171 MODULE_DESTRUCTOR(void)
172 {
173     for (int i = 0; i < g_rebootParamCmdValidNumber; i++) {
174         if (g_rebootParamCmdInfos[i].name != NULL) {
175             free(g_rebootParamCmdInfos[i].name);
176         }
177         if (g_rebootParamCmdInfos[i].replace != NULL) {
178             free(g_rebootParamCmdInfos[i].replace);
179         }
180         if (g_rebootParamCmdInfos[i].cmd != NULL) {
181             free(g_rebootParamCmdInfos[i].cmd);
182         }
183     }
184     free(g_rebootParamCmdInfos);
185     g_rebootParamCmdInfos = NULL;
186 }