1d9f0492fSopenharmony_ci 2d9f0492fSopenharmony_ci/* 3d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 4d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 5d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 6d9f0492fSopenharmony_ci * You may obtain a copy of the License at 7d9f0492fSopenharmony_ci * 8d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 9d9f0492fSopenharmony_ci * 10d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 11d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 12d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 14d9f0492fSopenharmony_ci * limitations under the License. 15d9f0492fSopenharmony_ci */ 16d9f0492fSopenharmony_ci 17d9f0492fSopenharmony_ci#include "init_hook.h" 18d9f0492fSopenharmony_ci#include "init_service.h" 19d9f0492fSopenharmony_ci#include "init_utils.h" 20d9f0492fSopenharmony_ci#include "plugin_adapter.h" 21d9f0492fSopenharmony_ci#include "securec.h" 22d9f0492fSopenharmony_ci#include "init_module_engine.h" 23d9f0492fSopenharmony_ci#include "init_group_manager.h" 24d9f0492fSopenharmony_ci#include "init_param.h" 25d9f0492fSopenharmony_ci#include "hookmgr.h" 26d9f0492fSopenharmony_ci#include "bootstage.h" 27d9f0492fSopenharmony_ci 28d9f0492fSopenharmony_cistatic int ServiceExtDataCompareProc(ListNode *node, void *data) 29d9f0492fSopenharmony_ci{ 30d9f0492fSopenharmony_ci ServiceExtData *item = ListEntry(node, ServiceExtData, node); 31d9f0492fSopenharmony_ci if (item->dataId == *(uint32_t *)data) { 32d9f0492fSopenharmony_ci return 0; 33d9f0492fSopenharmony_ci } 34d9f0492fSopenharmony_ci return -1; 35d9f0492fSopenharmony_ci} 36d9f0492fSopenharmony_ci 37d9f0492fSopenharmony_cistatic ServiceExtData *GetServiceExtData_(Service *service, uint32_t id) 38d9f0492fSopenharmony_ci{ 39d9f0492fSopenharmony_ci ListNode *node = OH_ListFind(&service->extDataNode, (void *)&id, ServiceExtDataCompareProc); 40d9f0492fSopenharmony_ci return (ServiceExtData *)node; 41d9f0492fSopenharmony_ci} 42d9f0492fSopenharmony_ci 43d9f0492fSopenharmony_ciServiceExtData *AddServiceExtData(const char *serviceName, uint32_t id, void *data, uint32_t dataLen) 44d9f0492fSopenharmony_ci{ 45d9f0492fSopenharmony_ci Service *service = GetServiceByName(serviceName); 46d9f0492fSopenharmony_ci PLUGIN_CHECK(service != NULL, return NULL, "Can not find service for %s", serviceName); 47d9f0492fSopenharmony_ci ServiceExtData *extData = GetServiceExtData_(service, id); 48d9f0492fSopenharmony_ci if (extData != NULL) { 49d9f0492fSopenharmony_ci return NULL; 50d9f0492fSopenharmony_ci } 51d9f0492fSopenharmony_ci extData = calloc(1, sizeof(ServiceExtData) + dataLen); 52d9f0492fSopenharmony_ci PLUGIN_CHECK(extData != NULL, return NULL, "Can not alloc extData for %d", id); 53d9f0492fSopenharmony_ci OH_ListInit(&extData->node); 54d9f0492fSopenharmony_ci extData->dataId = id; 55d9f0492fSopenharmony_ci if (data != NULL) { 56d9f0492fSopenharmony_ci int ret = memcpy_s(extData->data, dataLen, data, dataLen); 57d9f0492fSopenharmony_ci if (ret == 0) { 58d9f0492fSopenharmony_ci OH_ListAddTail(&service->extDataNode, &extData->node); 59d9f0492fSopenharmony_ci return extData; 60d9f0492fSopenharmony_ci } 61d9f0492fSopenharmony_ci } else { 62d9f0492fSopenharmony_ci OH_ListAddTail(&service->extDataNode, &extData->node); 63d9f0492fSopenharmony_ci return extData; 64d9f0492fSopenharmony_ci } 65d9f0492fSopenharmony_ci free(extData); 66d9f0492fSopenharmony_ci return NULL; 67d9f0492fSopenharmony_ci} 68d9f0492fSopenharmony_ci 69d9f0492fSopenharmony_civoid DelServiceExtData(const char *serviceName, uint32_t id) 70d9f0492fSopenharmony_ci{ 71d9f0492fSopenharmony_ci Service *service = GetServiceByName(serviceName); 72d9f0492fSopenharmony_ci PLUGIN_CHECK(service != NULL, return, "Can not find service for %s", serviceName); 73d9f0492fSopenharmony_ci ServiceExtData *extData = GetServiceExtData_(service, id); 74d9f0492fSopenharmony_ci if (extData == NULL) { 75d9f0492fSopenharmony_ci return; 76d9f0492fSopenharmony_ci } 77d9f0492fSopenharmony_ci OH_ListRemove(&extData->node); 78d9f0492fSopenharmony_ci free(extData); 79d9f0492fSopenharmony_ci} 80d9f0492fSopenharmony_ci 81d9f0492fSopenharmony_ciServiceExtData *GetServiceExtData(const char *serviceName, uint32_t id) 82d9f0492fSopenharmony_ci{ 83d9f0492fSopenharmony_ci Service *service = GetServiceByName(serviceName); 84d9f0492fSopenharmony_ci PLUGIN_CHECK (service != NULL, return NULL, "Can not find service for %s", serviceName); 85d9f0492fSopenharmony_ci return GetServiceExtData_(service, id); 86d9f0492fSopenharmony_ci} 87d9f0492fSopenharmony_ci 88d9f0492fSopenharmony_cistatic int JobParseHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) 89d9f0492fSopenharmony_ci{ 90d9f0492fSopenharmony_ci JOB_PARSE_CTX *jobParseContext = (JOB_PARSE_CTX *)executionContext; 91d9f0492fSopenharmony_ci JobParseHook realHook = (JobParseHook)hookInfo->hookCookie; 92d9f0492fSopenharmony_ci realHook(jobParseContext); 93d9f0492fSopenharmony_ci return 0; 94d9f0492fSopenharmony_ci}; 95d9f0492fSopenharmony_ci 96d9f0492fSopenharmony_ciint InitAddJobParseHook(JobParseHook hook) 97d9f0492fSopenharmony_ci{ 98d9f0492fSopenharmony_ci HOOK_INFO info; 99d9f0492fSopenharmony_ci info.stage = INIT_JOB_PARSE; 100d9f0492fSopenharmony_ci info.prio = 0; 101d9f0492fSopenharmony_ci info.hook = JobParseHookWrapper; 102d9f0492fSopenharmony_ci info.hookCookie = (void *)hook; 103d9f0492fSopenharmony_ci 104d9f0492fSopenharmony_ci return HookMgrAddEx(GetBootStageHookMgr(), &info); 105d9f0492fSopenharmony_ci} 106d9f0492fSopenharmony_ci 107d9f0492fSopenharmony_cistatic void SetLogLevelFunc(const char *value) 108d9f0492fSopenharmony_ci{ 109d9f0492fSopenharmony_ci unsigned int level; 110d9f0492fSopenharmony_ci int ret = StringToUint(value, &level); 111d9f0492fSopenharmony_ci PLUGIN_CHECK(ret == 0, return, "Failed make %s to unsigned int", value); 112d9f0492fSopenharmony_ci PLUGIN_LOGI("Set log level is %d", level); 113d9f0492fSopenharmony_ci SetInitLogLevel(level); 114d9f0492fSopenharmony_ci} 115d9f0492fSopenharmony_ci 116d9f0492fSopenharmony_cistatic int CmdSetLogLevel(int id, const char *name, int argc, const char **argv) 117d9f0492fSopenharmony_ci{ 118d9f0492fSopenharmony_ci UNUSED(id); 119d9f0492fSopenharmony_ci UNUSED(name); 120d9f0492fSopenharmony_ci PLUGIN_CHECK(argc >= 1, return -1, "Invalid input args"); 121d9f0492fSopenharmony_ci const char *value = strrchr(argv[0], '.'); 122d9f0492fSopenharmony_ci PLUGIN_CHECK(value != NULL, return -1, "Failed get \'.\' from string %s", argv[0]); 123d9f0492fSopenharmony_ci SetLogLevelFunc(value + 1); 124d9f0492fSopenharmony_ci return 0; 125d9f0492fSopenharmony_ci} 126d9f0492fSopenharmony_ci 127d9f0492fSopenharmony_cistatic int InitCmd(int id, const char *name, int argc, const char **argv) 128d9f0492fSopenharmony_ci{ 129d9f0492fSopenharmony_ci UNUSED(id); 130d9f0492fSopenharmony_ci // process cmd by name 131d9f0492fSopenharmony_ci PLUGIN_LOGI("InitCmd %s argc %d", name, argc); 132d9f0492fSopenharmony_ci if (argc > 1 && strcmp(argv[0], "setloglevel") == 0) { 133d9f0492fSopenharmony_ci SetLogLevelFunc(argv[1]); 134d9f0492fSopenharmony_ci } 135d9f0492fSopenharmony_ci return 0; 136d9f0492fSopenharmony_ci} 137d9f0492fSopenharmony_ci 138d9f0492fSopenharmony_cistatic int ParamSetInitCmdHook(const HOOK_INFO *hookInfo, void *cookie) 139d9f0492fSopenharmony_ci{ 140d9f0492fSopenharmony_ci AddCmdExecutor("setloglevel", CmdSetLogLevel); 141d9f0492fSopenharmony_ci AddCmdExecutor("initcmd", InitCmd); 142d9f0492fSopenharmony_ci return 0; 143d9f0492fSopenharmony_ci} 144d9f0492fSopenharmony_ci 145d9f0492fSopenharmony_cistatic int DumpTrigger(const char *fmt, ...) 146d9f0492fSopenharmony_ci{ 147d9f0492fSopenharmony_ci va_list vargs; 148d9f0492fSopenharmony_ci va_start(vargs, fmt); 149d9f0492fSopenharmony_ci InitLog(INIT_INFO, INIT_LOG_DOMAIN, INIT_LOG_TAG, fmt, vargs); 150d9f0492fSopenharmony_ci va_end(vargs); 151d9f0492fSopenharmony_ci return 0; 152d9f0492fSopenharmony_ci} 153d9f0492fSopenharmony_ci 154d9f0492fSopenharmony_cistatic void DumpServiceHook(void) 155d9f0492fSopenharmony_ci{ 156d9f0492fSopenharmony_ci // check and dump all jobs 157d9f0492fSopenharmony_ci char dump[8] = {0}; // 8 len 158d9f0492fSopenharmony_ci uint32_t len = sizeof(dump); 159d9f0492fSopenharmony_ci (void)SystemReadParam("persist.init.debug.dump.trigger", dump, &len); 160d9f0492fSopenharmony_ci PLUGIN_LOGV("boot dump trigger %s", dump); 161d9f0492fSopenharmony_ci if (strcmp(dump, "1") == 0) { 162d9f0492fSopenharmony_ci SystemDumpTriggers(1, DumpTrigger); 163d9f0492fSopenharmony_ci } 164d9f0492fSopenharmony_ci return; 165d9f0492fSopenharmony_ci} 166d9f0492fSopenharmony_ci 167d9f0492fSopenharmony_cistatic void InitLogLevelFromPersist(void) 168d9f0492fSopenharmony_ci{ 169d9f0492fSopenharmony_ci char logLevel[2] = {0}; // 2 is set param "persist.init.debug.loglevel" value length. 170d9f0492fSopenharmony_ci uint32_t len = sizeof(logLevel); 171d9f0492fSopenharmony_ci int ret = SystemReadParam(INIT_DEBUG_LEVEL, logLevel, &len); 172d9f0492fSopenharmony_ci INIT_INFO_CHECK(ret == 0, return, "Can not get log level from param, keep the original loglevel."); 173d9f0492fSopenharmony_ci SetLogLevelFunc(logLevel); 174d9f0492fSopenharmony_ci return; 175d9f0492fSopenharmony_ci} 176d9f0492fSopenharmony_ci 177d9f0492fSopenharmony_cistatic int InitDebugHook(const HOOK_INFO *info, void *cookie) 178d9f0492fSopenharmony_ci{ 179d9f0492fSopenharmony_ci UNUSED(info); 180d9f0492fSopenharmony_ci UNUSED(cookie); 181d9f0492fSopenharmony_ci InitLogLevelFromPersist(); 182d9f0492fSopenharmony_ci DumpServiceHook(); 183d9f0492fSopenharmony_ci return 0; 184d9f0492fSopenharmony_ci} 185d9f0492fSopenharmony_ci 186d9f0492fSopenharmony_ci// clear extend memory 187d9f0492fSopenharmony_cistatic int BootCompleteCmd(const HOOK_INFO *hookInfo, void *executionContext) 188d9f0492fSopenharmony_ci{ 189d9f0492fSopenharmony_ci PLUGIN_LOGI("boot start complete"); 190d9f0492fSopenharmony_ci UNUSED(hookInfo); 191d9f0492fSopenharmony_ci UNUSED(executionContext); 192d9f0492fSopenharmony_ci 193d9f0492fSopenharmony_ci // clear hook 194d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_GLOBAL_INIT, NULL); 195d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_PRE_PARAM_SERVICE, NULL); 196d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_PARAM_LOAD_FILTER, NULL); 197d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, NULL); 198d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, NULL); 199d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_SERVICE_PARSE, NULL); 200d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, NULL); 201d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, NULL); 202d9f0492fSopenharmony_ci HookMgrDel(GetBootStageHookMgr(), INIT_JOB_PARSE, NULL); 203d9f0492fSopenharmony_ci // clear cmd 204d9f0492fSopenharmony_ci RemoveCmdExecutor("loadSelinuxPolicy", -1); 205d9f0492fSopenharmony_ci 206d9f0492fSopenharmony_ci PluginExecCmdByName("init_trace", "stop"); 207d9f0492fSopenharmony_ci // uninstall module of inittrace 208d9f0492fSopenharmony_ci InitModuleMgrUnInstall("inittrace"); 209d9f0492fSopenharmony_ci return 0; 210d9f0492fSopenharmony_ci} 211d9f0492fSopenharmony_ci 212d9f0492fSopenharmony_ciMODULE_CONSTRUCTOR(void) 213d9f0492fSopenharmony_ci{ 214d9f0492fSopenharmony_ci HookMgrAdd(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, 0, BootCompleteCmd); 215d9f0492fSopenharmony_ci InitAddGlobalInitHook(0, ParamSetInitCmdHook); 216d9f0492fSopenharmony_ci // Depends on parameter service 217d9f0492fSopenharmony_ci InitAddPostPersistParamLoadHook(0, InitDebugHook); 218d9f0492fSopenharmony_ci} 219