From aafafa29376d1df6c0e5c26fda41812f0788b95d Mon Sep 17 00:00:00 2001 From: cheng_jinsong Date: Mon, 17 Oct 2022 17:55:33 +0800 Subject: [PATCH] add channe for begetctl cmd Signed-off-by: cheng_jinsong --- interfaces/innerkits/include/beget_ext.h | 2 + .../init_module_engine/include/bootstage.h | 1 + services/begetctl/begetctl_cmd.c | 99 +++++++++++++++++++ services/init/init_common_cmds.c | 18 +++- services/modules/bootevent/bootevent.c | 2 + services/modules/init_hook/init_hook.c | 67 ++++++++++--- services/modules/init_hook/param_hook.c | 30 ++++++ .../param/watcher/proxy/watcher_manager.cpp | 9 +- 8 files changed, 207 insertions(+), 21 deletions(-) create mode 100644 services/begetctl/begetctl_cmd.c diff --git a/interfaces/innerkits/include/beget_ext.h b/interfaces/innerkits/include/beget_ext.h index 1b0f0d92..248126f6 100644 --- a/interfaces/innerkits/include/beget_ext.h +++ b/interfaces/innerkits/include/beget_ext.h @@ -25,6 +25,8 @@ extern "C" { #endif #endif +#define INIT_DEBUG_LEVEL "persist.init.debug.loglevel" + #ifndef INIT_LOG_PATH #define INIT_LOG_PATH "/data/init_agent/" #endif diff --git a/interfaces/innerkits/init_module_engine/include/bootstage.h b/interfaces/innerkits/init_module_engine/include/bootstage.h index 56ae3f5f..57a21824 100755 --- a/interfaces/innerkits/init_module_engine/include/bootstage.h +++ b/interfaces/innerkits/init_module_engine/include/bootstage.h @@ -41,6 +41,7 @@ enum INIT_BOOTSTAGE { INIT_SERVICE_SET_PERMS = 59, INIT_SERVICE_FORK_AFTER = 60, INIT_JOB_PARSE = 70, + INIT_BOOT_COMPLETE = 100, }; HOOK_MGR *GetBootStageHookMgr(); diff --git a/services/begetctl/begetctl_cmd.c b/services/begetctl/begetctl_cmd.c new file mode 100644 index 00000000..da77387b --- /dev/null +++ b/services/begetctl/begetctl_cmd.c @@ -0,0 +1,99 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include +#include +#include + +#include "begetctl.h" +#include "init_utils.h" +#include "init_param.h" +#include "securec.h" +#include "shell_utils.h" +#include "parameter.h" + +#define BEGETCTRL_INIT_CMD "ohos.servicectrl.cmd" + +/** + * @brief 通用的命令通道,注册函数完成参数校验,调用HandleCmd进行处理 + * init进程使用 initCmd 按命令字进行处理 + */ +static int HandleCmd(BShellHandle shell, const char *cmdName, int argc, char **argv) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_LOGI("initCmd %s argc %d", cmdName, argc); + // format args + if (argc == 0) { + return SystemSetParameter(BEGETCTRL_INIT_CMD, cmdName); + } + char value[PARAM_VALUE_LEN_MAX] = { 0 }; + int ret = sprintf_s(value, sizeof(value) - 1, "%s ", cmdName); + BSH_CHECK(ret > 0, return BSH_INVALID_PARAM, "Failed to format cmdName"); + for (int i = 0; i < argc; i++) { + ret = strcat_s(value, sizeof(value), argv[i]); + BSH_CHECK(ret == 0, return BSH_INVALID_PARAM, "Failed to format name"); + ret = strcat_s(value, sizeof(value), " "); + BSH_CHECK(ret == 0, return BSH_INVALID_PARAM, "Failed to format name"); + } + return SystemSetParameter(BEGETCTRL_INIT_CMD, value); +} + +static int SetInitLogLevelFromParam(BShellHandle shell, int argc, char **argv) +{ + if (argc != 2) { // 2 is set log level parameter number + char *helpArgs[] = {"set", NULL}; + BShellCmdHelp(shell, 1, helpArgs); + return 0; + } + const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; + errno = 0; + unsigned int level = strtoul(argv[1], 0, 10); // 10 is decimal + if (errno != 0) { + printf("Failed to transform %s to unsigned int. \n", argv[1]); + return -1; + } + if ((level >= INIT_DEBUG) && (level <= INIT_FATAL)) { + int ret = HandleCmd(shell, "setloglevel", argc - 1, &argv[1]); + if (ret != 0) { + printf("Failed to set log level %s. \n", LOG_LEVEL_STR[level]); + } else { + printf("Success to set log level %s. \n", LOG_LEVEL_STR[level]); + } + } else { + printf("%s is invalid. \n", argv[1]); + } + return 0; +} + +static int32_t GetInitLogLevelFromParam(BShellHandle shell, int argc, char **argv) +{ + const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; + int level = GetIntParameter(INIT_DEBUG_LEVEL, (int)INIT_ERROR); + if ((level >= INIT_DEBUG) && (level <= INIT_FATAL)) { + printf("Init log level: %s \n", LOG_LEVEL_STR[level]); + } + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + {"set", SetInitLogLevelFromParam, + "set init log level 0:debug, 1:info, 2:warning, 3:err, 4:fatal", "set log level", "set log level"}, + {"get", GetInitLogLevelFromParam, "get init log level", "get log level", "get log level"}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} \ No newline at end of file diff --git a/services/init/init_common_cmds.c b/services/init/init_common_cmds.c index 529b06f6..20df0eed 100644 --- a/services/init/init_common_cmds.c +++ b/services/init/init_common_cmds.c @@ -38,6 +38,8 @@ #include "init_utils.h" #include "securec.h" +#define BASE_MS_UNIT 1000 + #ifndef OHOS_LITE #include "hookmgr.h" #include "bootstage.h" @@ -716,9 +718,9 @@ long long InitDiffTime(INIT_TIMING_STAT *stat) { long long diff = (long long)((stat->endTime.tv_sec - stat->startTime.tv_sec) * 1000000); // 1000000 1000ms if (stat->endTime.tv_nsec > stat->startTime.tv_nsec) { - diff += (stat->endTime.tv_nsec - stat->startTime.tv_nsec) / 1000; // 1000 ms + diff += (stat->endTime.tv_nsec - stat->startTime.tv_nsec) / BASE_MS_UNIT; } else { - diff -= (stat->startTime.tv_nsec - stat->endTime.tv_nsec) / 1000; // 1000 ms + diff -= (stat->startTime.tv_nsec - stat->endTime.tv_nsec) / BASE_MS_UNIT; } return diff; } @@ -741,7 +743,11 @@ void DoCmdByName(const char *name, const char *cmdContent) #ifndef OHOS_LITE InitCmdHookExecute(name, cmdContent, &cmdTimer); #endif - INIT_LOGV("Execute command \"%s %s\" took %lld ms", name, cmdContent, diff / 1000); // 1000 is convert us to ms + if (diff > 200000) { // 200000 > 200ms + INIT_LOGI("Execute command \"%s %s\" took %lld ms", name, cmdContent, diff / BASE_MS_UNIT); + } else { + INIT_LOGV("Execute command \"%s %s\" took %lld ms", name, cmdContent, diff / BASE_MS_UNIT); + } } void DoCmdByIndex(int index, const char *cmdContent) @@ -776,5 +782,9 @@ void DoCmdByIndex(int index, const char *cmdContent) #ifndef OHOS_LITE InitCmdHookExecute(cmdName, cmdContent, &cmdTimer); #endif - INIT_LOGV("Execute command \"%s %s\" took %lld ms", cmdName, cmdContent, diff / 1000); // 1000 is convert us to ms + if (diff > 200000) { // 200000 > 200ms + INIT_LOGI("Execute command \"%s %s\" took %lld ms", cmdName, cmdContent, diff / BASE_MS_UNIT); + } else { + INIT_LOGV("Execute command \"%s %s\" took %lld ms", cmdName, cmdContent, diff / BASE_MS_UNIT); + } } diff --git a/services/modules/bootevent/bootevent.c b/services/modules/bootevent/bootevent.c index 5c2cdeda..3ca380d8 100755 --- a/services/modules/bootevent/bootevent.c +++ b/services/modules/bootevent/bootevent.c @@ -180,6 +180,8 @@ static void BootEventParaFireByName(const char *paramName) const char *clearBootEventArgv[] = {"bootevent"}; // clear servie extra data PluginExecCmd("clear", ARRAY_LENGTH(clearBootEventArgv), clearBootEventArgv); + + HookMgrExecute(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, NULL, NULL); return; } diff --git a/services/modules/init_hook/init_hook.c b/services/modules/init_hook/init_hook.c index 3c252b00..28c041fa 100755 --- a/services/modules/init_hook/init_hook.c +++ b/services/modules/init_hook/init_hook.c @@ -124,20 +124,37 @@ static int CmdClear(int id, const char *name, int argc, const char **argv) return 0; } +static void SetLogLevel_(const char *value) +{ + unsigned int level; + int ret = StringToUint(value, &level); + PLUGIN_CHECK(ret == 0, return, "Failed make %s to unsigned int", value); + PLUGIN_LOGI("Set log level is %d", level); + SetInitLogLevel(level); +} + static int CmdSetLogLevel(int id, const char *name, int argc, const char **argv) { UNUSED(id); - if ((name == NULL) || (argv == NULL) || (argc < 1)) { - PLUGIN_LOGE("Failed get log level from parameter."); - return -1; - } - char *value = strrchr(argv[0], '.'); + UNUSED(name); + PLUGIN_CHECK(argc >= 1, return -1, "Invalid input args"); + const char *value = strrchr(argv[0], '.'); PLUGIN_CHECK(value != NULL, return -1, "Failed get \'.\' from string %s", argv[0]); - unsigned int level; - int ret = StringToUint(value + 1, &level); - PLUGIN_CHECK(ret == 0, return -1, "Failed make string to unsigned int"); - PLUGIN_LOGI("level is %d", level); - SetInitLogLevel(level); + SetLogLevel_(value + 1); + return 0; +} + +static int initCmd(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + // process cmd by name + PLUGIN_LOGI("initCmd %s argc %d", name, argc); + for (int i = 0; i < argc; i++) { + PLUGIN_LOGI("initCmd %s", argv[i]); + } + if (argc > 1 && strcmp(argv[0], "setloglevel") == 0) { + SetLogLevel_(argv[1]); + } return 0; } @@ -145,6 +162,7 @@ static int ParamSetInitCmdHook(const HOOK_INFO *hookInfo, void *cookie) { AddCmdExecutor("clear", CmdClear); AddCmdExecutor("setloglevel", CmdSetLogLevel); + AddCmdExecutor("initcmd", initCmd); return 0; } @@ -174,12 +192,9 @@ static void InitLogLevelFromPersist(void) { char logLevel[2] = {0}; // 2 is set param "persist.init.debug.loglevel" value length. uint32_t len = sizeof(logLevel); - int ret = SystemReadParam("persist.init.debug.loglevel", logLevel, &len); + int ret = SystemReadParam(INIT_DEBUG_LEVEL, logLevel, &len); INIT_INFO_CHECK(ret == 0, return, "Can not get log level from param, keep the original loglevel."); - errno = 0; - unsigned int level = (unsigned int)strtoul(logLevel, 0, 10); // 10 is decimal - INIT_INFO_CHECK(errno == 0, return, "Failed strtoul %s, err=%d", logLevel, errno); - SetInitLogLevel(level); + SetLogLevel_(logLevel); return; } @@ -192,8 +207,30 @@ static int InitDebugHook(const HOOK_INFO *info, void *cookie) return 0; } +// clear extend memory +static int BootCompleteCmd(const HOOK_INFO *hookInfo, void *executionContext) +{ + PLUGIN_LOGI("boot start complete"); + UNUSED(hookInfo); + UNUSED(executionContext); + + // clear hook + HookMgrDel(GetBootStageHookMgr(), INIT_GLOBAL_INIT, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_PRE_PARAM_SERVICE, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_SERVICE_PARSE, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_JOB_PARSE, NULL); + // clear cmd + RemoveCmdExecutor("loadSelinuxPolicy", -1); + return 0; +} + MODULE_CONSTRUCTOR(void) { + HookMgrAdd(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, 0, BootCompleteCmd); InitAddGlobalInitHook(0, ParamSetInitCmdHook); // Depends on parameter service InitAddPostPersistParamLoadHook(0, InitDebugHook); diff --git a/services/modules/init_hook/param_hook.c b/services/modules/init_hook/param_hook.c index e1b8152c..9f412860 100755 --- a/services/modules/init_hook/param_hook.c +++ b/services/modules/init_hook/param_hook.c @@ -19,6 +19,35 @@ #include "plugin_adapter.h" #include "securec.h" +/** +系统参数转化规则 + 1,ohos.ctl.start.{start|stop} = servicename + 转化后系统参数,用来进行dac/mac校验 + ohos.servicectrl.{servicename} + 对应的处理命令 + start + 2,ohos.startup.powerctrl = reboot,[bootcharge | shutdown | flashd | updater] + 转化后系统参数,用来进行dac/mac校验 + ohos.servicectrl.reboot.[bootcharge | shutdown | flashd | updater] + 对应的处理命令 + reboot.[bootcharge | shutdown | flashd | updater] + 3,ohos.servicectrl.{cmdName} = {arg} + 转化后系统参数,用来进行dac/mac校验 + ohos.servicectrl.{cmd} + 对应的处理命令 + cmd + 4,普通系统参数,根据定义的ParamCmdInfo进行处理 + {xxxx.xxxx.xxxx, xxxx.xxxx.xxxx, cmdname} + 例如: + xxxx.xxxx.xxxx = {args} + 转化后系统参数,用来进行dac/mac校验 + xxxx.xxxx.xxxx.{args} + 对应的处理命令 + cmdname + 命令输入参数(跳过replace部分的剩余值) + xxxx.xxxx.xxxx.{args} + strlen(name) +*/ + const ParamCmdInfo *GetServiceStartCtrl(size_t *size) { static const ParamCmdInfo ctrlParam[] = { @@ -38,6 +67,7 @@ const ParamCmdInfo *GetServiceCtl(size_t *size) {"ohos.servicectrl.bootchart", "bootchart", "bootchart" }, {"ohos.servicectrl.timer_start", "timer_start", "timer_start " }, {"ohos.servicectrl.timer_stop", "timer_stop", "timer_stop" }, + {"ohos.servicectrl.cmd", "cmd", "initcmd"}, }; *size = ARRAY_LENGTH(installParam); return installParam; diff --git a/services/param/watcher/proxy/watcher_manager.cpp b/services/param/watcher/proxy/watcher_manager.cpp index 1cebf09d..f322bd65 100644 --- a/services/param/watcher/proxy/watcher_manager.cpp +++ b/services/param/watcher/proxy/watcher_manager.cpp @@ -21,6 +21,7 @@ #include #include "init_param.h" +#include "parameter.h" #include "system_ability_definition.h" #include "string_ex.h" #include "watcher_utils.h" @@ -37,7 +38,8 @@ WatcherManager::~WatcherManager() uint32_t WatcherManager::AddRemoteWatcher(uint32_t id, const sptr &watcher) { - WATCHER_CHECK(watcher != nullptr && deathRecipient_ != nullptr, return 0, "Invalid remove watcher"); + WATCHER_CHECK(watcher != nullptr, return 0, "Invalid remote watcher"); + WATCHER_CHECK(deathRecipient_ != nullptr, return 0, "Invalid deathRecipient_"); sptr object = watcher->AsObject(); if ((object != nullptr) && (object->IsProxyObject())) { WATCHER_CHECK(object->AddDeathRecipient(deathRecipient_), return 0, "Failed to add death recipient %u", id); @@ -303,15 +305,18 @@ int WatcherManager::GetServerFd(bool retry) void WatcherManager::OnStart() { + int level = GetIntParameter(INIT_DEBUG_LEVEL, (int)INIT_ERROR); + SetInitLogLevel((InitLogLevel)level); + WATCHER_LOGI("Watcher manager OnStart"); bool res = Publish(this); if (!res) { WATCHER_LOGE("WatcherManager Publish failed"); } - SystemSetParameter("bootevent.param_watcher.started", "true"); if (deathRecipient_ == nullptr) { deathRecipient_ = new DeathRecipient(this); } + SystemSetParameter("bootevent.param_watcher.started", "true"); return; } -- GitLab