1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci#include <errno.h> 16d9f0492fSopenharmony_ci 17d9f0492fSopenharmony_ci#include "bootstage.h" 18d9f0492fSopenharmony_ci#include "hookmgr.h" 19d9f0492fSopenharmony_ci#include "init_hook.h" 20d9f0492fSopenharmony_ci#include "init_module_engine.h" 21d9f0492fSopenharmony_ci#include "plugin_adapter.h" 22d9f0492fSopenharmony_ci#include "securec.h" 23d9f0492fSopenharmony_ci 24d9f0492fSopenharmony_ci#define REBOOT_NAME_PREFIX "reboot," 25d9f0492fSopenharmony_ci#define REBOOT_CMD_PREFIX "reboot." 26d9f0492fSopenharmony_ci#define REBOOT_REPLACE_PREFIX "reboot." 27d9f0492fSopenharmony_ci#define PARAM_CMD_MAX 100 28d9f0492fSopenharmony_ci 29d9f0492fSopenharmony_cistatic int RebootHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) 30d9f0492fSopenharmony_ci{ 31d9f0492fSopenharmony_ci RebootHookCtx *ctx = (RebootHookCtx *)executionContext; 32d9f0492fSopenharmony_ci InitRebootHook realHook = (InitRebootHook)hookInfo->hookCookie; 33d9f0492fSopenharmony_ci realHook(ctx); 34d9f0492fSopenharmony_ci return 0; 35d9f0492fSopenharmony_ci}; 36d9f0492fSopenharmony_ci 37d9f0492fSopenharmony_ciint InitAddRebootHook(InitRebootHook hook) 38d9f0492fSopenharmony_ci{ 39d9f0492fSopenharmony_ci HOOK_INFO info; 40d9f0492fSopenharmony_ci info.stage = INIT_REBOOT; 41d9f0492fSopenharmony_ci info.prio = 0; 42d9f0492fSopenharmony_ci info.hook = RebootHookWrapper; 43d9f0492fSopenharmony_ci info.hookCookie = (void *)hook; 44d9f0492fSopenharmony_ci return HookMgrAddEx(GetBootStageHookMgr(), &info); 45d9f0492fSopenharmony_ci} 46d9f0492fSopenharmony_ci 47d9f0492fSopenharmony_cistatic ParamCmdInfo *g_rebootParamCmdInfos = NULL; 48d9f0492fSopenharmony_cistatic int g_rebootParamCmdMaxNumber = 0; 49d9f0492fSopenharmony_cistatic int g_rebootParamCmdValidNumber = 0; 50d9f0492fSopenharmony_cistatic char *Dup2String(const char *prefix, const char *str) 51d9f0492fSopenharmony_ci{ 52d9f0492fSopenharmony_ci if (str == NULL) { 53d9f0492fSopenharmony_ci char *tmpstr = strdup("reboot"); 54d9f0492fSopenharmony_ci PLUGIN_CHECK(tmpstr != NULL, return NULL, "Failed to get str"); 55d9f0492fSopenharmony_ci return tmpstr; 56d9f0492fSopenharmony_ci } 57d9f0492fSopenharmony_ci size_t len = strlen(prefix) + strlen(str) + 1; 58d9f0492fSopenharmony_ci char *tmp = calloc(1, len); 59d9f0492fSopenharmony_ci PLUGIN_CHECK(tmp != NULL, return NULL, "Failed to alloc %s %s", prefix, str); 60d9f0492fSopenharmony_ci int ret = sprintf_s(tmp, len, "%s%s", prefix, str); 61d9f0492fSopenharmony_ci PLUGIN_CHECK(ret > 0, free(tmp); 62d9f0492fSopenharmony_ci return NULL, "Failed to sprintf %s %s", prefix, str); 63d9f0492fSopenharmony_ci return tmp; 64d9f0492fSopenharmony_ci} 65d9f0492fSopenharmony_ci 66d9f0492fSopenharmony_cistatic int CheckParamCmdExist(const char *cmd) 67d9f0492fSopenharmony_ci{ 68d9f0492fSopenharmony_ci if (g_rebootParamCmdInfos == NULL) { 69d9f0492fSopenharmony_ci return 0; 70d9f0492fSopenharmony_ci } 71d9f0492fSopenharmony_ci char *cmdName = Dup2String(REBOOT_CMD_PREFIX, cmd); 72d9f0492fSopenharmony_ci PLUGIN_CHECK(cmdName != NULL, return 0, "Failed to copy %s", cmd); 73d9f0492fSopenharmony_ci for (int i = 0; i < g_rebootParamCmdValidNumber; i++) { 74d9f0492fSopenharmony_ci if (strcmp(g_rebootParamCmdInfos[i].cmd, cmdName) == 0) { 75d9f0492fSopenharmony_ci free(cmdName); 76d9f0492fSopenharmony_ci return 1; 77d9f0492fSopenharmony_ci } 78d9f0492fSopenharmony_ci } 79d9f0492fSopenharmony_ci free(cmdName); 80d9f0492fSopenharmony_ci return 0; 81d9f0492fSopenharmony_ci} 82d9f0492fSopenharmony_ci 83d9f0492fSopenharmony_cistatic int SetParamCmdInfo(ParamCmdInfo *currInfo, CmdExecutor executor, const char *cmd) 84d9f0492fSopenharmony_ci{ 85d9f0492fSopenharmony_ci do { 86d9f0492fSopenharmony_ci currInfo->name = Dup2String(REBOOT_NAME_PREFIX, cmd); 87d9f0492fSopenharmony_ci PLUGIN_CHECK(currInfo->name != NULL, break, "Failed to copy %s", cmd); 88d9f0492fSopenharmony_ci currInfo->replace = Dup2String(REBOOT_REPLACE_PREFIX, cmd); 89d9f0492fSopenharmony_ci PLUGIN_CHECK(currInfo->replace != NULL, break, "Failed to copy %s", cmd); 90d9f0492fSopenharmony_ci currInfo->cmd = Dup2String(REBOOT_CMD_PREFIX, cmd); 91d9f0492fSopenharmony_ci PLUGIN_CHECK(currInfo->cmd != NULL, break, "Failed to copy %s", cmd); 92d9f0492fSopenharmony_ci if (executor != NULL) { 93d9f0492fSopenharmony_ci int cmdId = AddCmdExecutor(currInfo->cmd, executor); 94d9f0492fSopenharmony_ci PLUGIN_CHECK(cmdId > 0, break, "Failed to add cmd %s", cmd); 95d9f0492fSopenharmony_ci } 96d9f0492fSopenharmony_ci PLUGIN_LOGV("SetParamCmdInfo '%s' '%s' '%s' ", currInfo->name, currInfo->cmd, currInfo->replace); 97d9f0492fSopenharmony_ci currInfo = NULL; 98d9f0492fSopenharmony_ci g_rebootParamCmdValidNumber++; 99d9f0492fSopenharmony_ci return 0; 100d9f0492fSopenharmony_ci } while (0); 101d9f0492fSopenharmony_ci if (currInfo != NULL) { 102d9f0492fSopenharmony_ci if (currInfo->name != NULL) { 103d9f0492fSopenharmony_ci free(currInfo->name); 104d9f0492fSopenharmony_ci } 105d9f0492fSopenharmony_ci if (currInfo->cmd != NULL) { 106d9f0492fSopenharmony_ci free(currInfo->cmd); 107d9f0492fSopenharmony_ci } 108d9f0492fSopenharmony_ci if (currInfo->replace != NULL) { 109d9f0492fSopenharmony_ci free(currInfo->replace); 110d9f0492fSopenharmony_ci } 111d9f0492fSopenharmony_ci } 112d9f0492fSopenharmony_ci return -1; 113d9f0492fSopenharmony_ci} 114d9f0492fSopenharmony_ci 115d9f0492fSopenharmony_cistatic int AddRebootCmdExecutor_(const char *cmd, CmdExecutor executor) 116d9f0492fSopenharmony_ci{ 117d9f0492fSopenharmony_ci PLUGIN_CHECK(g_rebootParamCmdMaxNumber <= PARAM_CMD_MAX, return -1, "Param cmd max number exceed limit"); 118d9f0492fSopenharmony_ci if (g_rebootParamCmdMaxNumber == 0 || g_rebootParamCmdMaxNumber <= g_rebootParamCmdValidNumber) { 119d9f0492fSopenharmony_ci g_rebootParamCmdMaxNumber += 5; // inc 5 once time 120d9f0492fSopenharmony_ci ParamCmdInfo *cmdInfos = calloc(1, sizeof(ParamCmdInfo) * g_rebootParamCmdMaxNumber); 121d9f0492fSopenharmony_ci PLUGIN_CHECK(cmdInfos != NULL, return -1, "Failed to add reboot cmd %s", cmd); 122d9f0492fSopenharmony_ci if (g_rebootParamCmdInfos != NULL) { // delete old 123d9f0492fSopenharmony_ci // copy from old 124d9f0492fSopenharmony_ci for (int i = 0; i < g_rebootParamCmdValidNumber; i++) { 125d9f0492fSopenharmony_ci cmdInfos[i].name = g_rebootParamCmdInfos[i].name; 126d9f0492fSopenharmony_ci cmdInfos[i].replace = g_rebootParamCmdInfos[i].replace; 127d9f0492fSopenharmony_ci cmdInfos[i].cmd = g_rebootParamCmdInfos[i].cmd; 128d9f0492fSopenharmony_ci } 129d9f0492fSopenharmony_ci free(g_rebootParamCmdInfos); 130d9f0492fSopenharmony_ci } 131d9f0492fSopenharmony_ci g_rebootParamCmdInfos = cmdInfos; 132d9f0492fSopenharmony_ci } 133d9f0492fSopenharmony_ci PLUGIN_CHECK(g_rebootParamCmdValidNumber >= 0 && g_rebootParamCmdValidNumber < g_rebootParamCmdMaxNumber, 134d9f0492fSopenharmony_ci return -1, "Param cmd number exceed limit"); 135d9f0492fSopenharmony_ci return SetParamCmdInfo(&g_rebootParamCmdInfos[g_rebootParamCmdValidNumber], executor, cmd); 136d9f0492fSopenharmony_ci} 137d9f0492fSopenharmony_ci 138d9f0492fSopenharmony_ciint AddRebootCmdExecutor(const char *cmd, CmdExecutor executor) 139d9f0492fSopenharmony_ci{ 140d9f0492fSopenharmony_ci PLUGIN_CHECK(cmd != NULL && executor != NULL, return EINVAL, "Invalid input parameter"); 141d9f0492fSopenharmony_ci int ret = CheckParamCmdExist(cmd); 142d9f0492fSopenharmony_ci if (ret != 0) { 143d9f0492fSopenharmony_ci PLUGIN_LOGI("Cmd %s exist", cmd); 144d9f0492fSopenharmony_ci return EEXIST; 145d9f0492fSopenharmony_ci } 146d9f0492fSopenharmony_ci return AddRebootCmdExecutor_(cmd, executor); 147d9f0492fSopenharmony_ci} 148d9f0492fSopenharmony_ci 149d9f0492fSopenharmony_ciconst ParamCmdInfo *GetStartupPowerCtl(size_t *size) 150d9f0492fSopenharmony_ci{ 151d9f0492fSopenharmony_ci RebootHookCtx context; 152d9f0492fSopenharmony_ci context.reason = ""; 153d9f0492fSopenharmony_ci (void)HookMgrExecute(GetBootStageHookMgr(), INIT_REBOOT, (void *)(&context), NULL); 154d9f0492fSopenharmony_ci PLUGIN_LOGI("After install reboot module"); 155d9f0492fSopenharmony_ci *size = g_rebootParamCmdValidNumber; 156d9f0492fSopenharmony_ci return g_rebootParamCmdInfos; 157d9f0492fSopenharmony_ci} 158d9f0492fSopenharmony_ci 159d9f0492fSopenharmony_cistatic void InitRebootHook_(RebootHookCtx *ctx) 160d9f0492fSopenharmony_ci{ 161d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST // do not install 162d9f0492fSopenharmony_ci ModuleMgrScan("init/reboot"); 163d9f0492fSopenharmony_ci#endif 164d9f0492fSopenharmony_ci PLUGIN_LOGI("Install rebootmodule."); 165d9f0492fSopenharmony_ci} 166d9f0492fSopenharmony_ci 167d9f0492fSopenharmony_ciMODULE_CONSTRUCTOR(void) 168d9f0492fSopenharmony_ci{ 169d9f0492fSopenharmony_ci // 执行reboot时调用,安装reboot模块 170d9f0492fSopenharmony_ci InitAddRebootHook(InitRebootHook_); 171d9f0492fSopenharmony_ci} 172d9f0492fSopenharmony_ci 173d9f0492fSopenharmony_ciMODULE_DESTRUCTOR(void) 174d9f0492fSopenharmony_ci{ 175d9f0492fSopenharmony_ci for (int i = 0; i < g_rebootParamCmdValidNumber; i++) { 176d9f0492fSopenharmony_ci if (g_rebootParamCmdInfos[i].name != NULL) { 177d9f0492fSopenharmony_ci free(g_rebootParamCmdInfos[i].name); 178d9f0492fSopenharmony_ci } 179d9f0492fSopenharmony_ci if (g_rebootParamCmdInfos[i].replace != NULL) { 180d9f0492fSopenharmony_ci free(g_rebootParamCmdInfos[i].replace); 181d9f0492fSopenharmony_ci } 182d9f0492fSopenharmony_ci if (g_rebootParamCmdInfos[i].cmd != NULL) { 183d9f0492fSopenharmony_ci free(g_rebootParamCmdInfos[i].cmd); 184d9f0492fSopenharmony_ci } 185d9f0492fSopenharmony_ci } 186d9f0492fSopenharmony_ci free(g_rebootParamCmdInfos); 187d9f0492fSopenharmony_ci g_rebootParamCmdInfos = NULL; 188d9f0492fSopenharmony_ci}