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 29static 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 37int 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 47static ParamCmdInfo *g_rebootParamCmdInfos = NULL; 48static int g_rebootParamCmdMaxNumber = 0; 49static int g_rebootParamCmdValidNumber = 0; 50static 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 66static 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 83static 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 115static 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 138int 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 149const 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 159static 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 167MODULE_CONSTRUCTOR(void) 168{ 169 // 执行reboot时调用,安装reboot模块 170 InitAddRebootHook(InitRebootHook_); 171} 172 173MODULE_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}