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 }