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