diff --git a/interfaces/innerkits/fs_manager/fstab_mount.c b/interfaces/innerkits/fs_manager/fstab_mount.c index 526c75039..ef426bff9 100755 --- a/interfaces/innerkits/fs_manager/fstab_mount.c +++ b/interfaces/innerkits/fs_manager/fstab_mount.c @@ -295,16 +295,6 @@ static int Mount(const char *source, const char *target, const char *fsType, return rc; } -static int GetSlotInfoFromParameter(const char *slotInfoName) -{ - char name[PARAM_NAME_LEN_MAX] = {0}; - BEGET_ERROR_CHECK(sprintf_s(name, sizeof(name), "ohos.boot.%s", slotInfoName) > 0, - return -1, "Failed to format slot parameter name"); - char value[PARAM_VALUE_LEN_MAX] = {0}; - uint32_t valueLen = PARAM_VALUE_LEN_MAX; - return SystemGetParameter(name, value, &valueLen) == 0 ? atoi(value) : -1; -} - static int GetSlotInfoFromCmdLine(const char *slotInfoName) { char value[MAX_BUFFER_LEN] = {0}; @@ -334,21 +324,13 @@ static int GetSlotInfoFromBootctrl(off_t offset, off_t size) int GetBootSlots(void) { - int bootSlots = GetSlotInfoFromParameter("bootslots"); - BEGET_CHECK_RETURN_VALUE(bootSlots <= 0, bootSlots); - BEGET_LOGI("No valid slot value found from parameter, try to get it from cmdline"); return GetSlotInfoFromCmdLine("bootslots"); } int GetCurrentSlot(void) { - // get current slot from parameter - int currentSlot = GetSlotInfoFromParameter("currentslot"); - BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot); - BEGET_LOGI("No valid slot value found from parameter, try to get it from cmdline"); - // get current slot from cmdline - currentSlot = GetSlotInfoFromCmdLine("currentslot"); + int currentSlot = GetSlotInfoFromCmdLine("currentslot"); BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot); BEGET_LOGI("No valid slot value found from cmdline, try to get it from bootctrl"); @@ -468,6 +450,7 @@ int MountAllWithFstab(const Fstab *fstab, bool required) } } #endif + for (item = fstab->head; item != NULL; item = item->next) { rc = CheckRequiredAndMount(item, required); if (required && (rc < 0)) { // Init fail to mount in the first stage and exit directly. diff --git a/services/BUILD.gn b/services/BUILD.gn index 7f2b0271b..98631fdeb 100755 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -32,6 +32,7 @@ group("startup_init") { deps = [ "etc:etc_files", "init/standard:init", + "init/standard:init_early", "//third_party/e2fsprogs:e2fsprogs", ] diff --git a/services/init/include/device.h b/services/init/include/device.h index fb6d92d75..9729572a3 100644 --- a/services/init/include/device.h +++ b/services/init/include/device.h @@ -27,8 +27,7 @@ extern "C" { #define DEV_RANDOM_MINOR 8 #define DEV_URANDOM_MINOR 9 -void MountBasicFs(void); -void CreateDeviceNode(void); +void CreateFsAndDeviceNode(void); #ifdef __cplusplus #if __cplusplus diff --git a/services/init/include/init.h b/services/init/include/init.h index b856a2f78..dd2e82bb8 100644 --- a/services/init/include/init.h +++ b/services/init/include/init.h @@ -42,7 +42,6 @@ extern "C" { void SystemInit(void); void LogInit(void); -void SystemPrepare(long long uptime); void SystemConfig(const char *uptime); void SystemRun(void); void SystemExecuteRcs(void); diff --git a/services/init/lite/init.c b/services/init/lite/init.c index 26b37a849..cf7e367cd 100644 --- a/services/init/lite/init.c +++ b/services/init/lite/init.c @@ -46,16 +46,16 @@ void LogInit(void) return; } -void SystemPrepare(long long uptime) -{ -} - void ParseInitCfgByPriority(void) { ReadFileInDir(OTHER_CFG_PATH, ".cfg", ParseInitCfg, NULL); ReadFileInDir("/vendor/etc/init", ".cfg", ParseInitCfg, NULL); } +void CreateFsAndDeviceNode(void) +{ +} + void SystemConfig(const char *uptime) { InitServiceSpace(); diff --git a/services/init/main.c b/services/init/main.c index a59447075..fcfd347c0 100644 --- a/services/init/main.c +++ b/services/init/main.c @@ -16,13 +16,13 @@ #include "init.h" #include "init_log.h" #include "init_utils.h" +#include "device.h" static const pid_t INIT_PROCESS_PID = 1; int main(int argc, char * const argv[]) { const char *uptime = NULL; - long long upTimeInMicroSecs = 0; int isSecondStage = 0; (void)signal(SIGPIPE, SIG_IGN); // Number of command line parameters is 2 @@ -31,19 +31,20 @@ int main(int argc, char * const argv[]) if (argc > 2) { uptime = argv[2]; } - } else { - upTimeInMicroSecs = GetUptimeInMicroSeconds(NULL); } if (getpid() != INIT_PROCESS_PID) { INIT_LOGE("Process id error %d!", getpid()); return 0; } EnableInitLog(INIT_INFO); + + // Updater mode if (isSecondStage == 0) { - SystemPrepare(upTimeInMicroSecs); - } else { - LogInit(); + CreateFsAndDeviceNode(); } + + LogInit(); + SystemInit(); SystemExecuteRcs(); SystemConfig(uptime); diff --git a/services/init/standard/BUILD.gn b/services/init/standard/BUILD.gn index cd22c3f77..57239145b 100644 --- a/services/init/standard/BUILD.gn +++ b/services/init/standard/BUILD.gn @@ -30,6 +30,37 @@ FSCRYPT_PATH = import("//build/ohos.gni") import("//build/ohos/native_stub/native_stub.gni") +ohos_executable("init_early") { + sources = [ + "//base/startup/init/interfaces/innerkits/hookmgr/hookmgr.c", + "//base/startup/init/services/log/init_commlog.c", + "bootstagehooker.c", + "device.c", + "init_mount.c", + "main_early.c", + "switch_root.c", + ] + include_dirs = [ + "//third_party/cJSON", + "//base/startup/init/services/include", + "//base/startup/init/services/init/include", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", + ] + configs = [ "//build/config/gcc:symbol_visibility_hidden" ] + deps = [ + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/services/log:init_log", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + "//third_party/bounds_checking_function:libsec_static", + ] + if (startup_init_extra_static_modules != "") { + deps += [ startup_init_extra_static_modules ] + } + install_images = [ "ramdisk" ] + install_enable = true + part_name = "init" +} + ohos_executable("init") { sources = [ "../adapter/init_adapter.c", @@ -40,11 +71,10 @@ ohos_executable("init") { "../standard/init_cmds.c", "../standard/init_control_fd_service.c", "../standard/init_jobs.c", - "../standard/init_mount.c", "../standard/init_reboot.c", "../standard/init_service.c", "../standard/init_signal_handler.c", - "../standard/switch_root.c", + "bootstagehooker.c", ] modulemgr_sources = [ @@ -66,6 +96,7 @@ ohos_executable("init") { "//base/startup/init/interfaces/innerkits/control_fd:libcontrolfd", "//base/startup/init/interfaces/innerkits/fd_holder:fdholder", "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/services/log:init_log", "//base/startup/init/services/loopevent:loopevent", "//base/startup/init/services/param/linux:param_init", "//base/startup/init/services/sandbox:sandbox", @@ -74,7 +105,6 @@ ohos_executable("init") { deps += [ "//base/startup/init/services/param/base:param_base" ] deps += [ - "//base/startup/init/ueventd:libueventd_ramdisk_static", "//third_party/bounds_checking_function:libsec_static", "//third_party/cJSON:cjson_static", ] @@ -152,7 +182,6 @@ ohos_executable("init") { install_images = [ "system", "updater", - "ramdisk", ] install_enable = true part_name = "init" diff --git a/services/init/standard/bootstagehooker.c b/services/init/standard/bootstagehooker.c new file mode 100755 index 000000000..c241aaef7 --- /dev/null +++ b/services/init/standard/bootstagehooker.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 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 "bootstage.h" + +#define INIT_BOOTSTAGE_HOOK_NAME "bootstage" +static HOOK_MGR *bootStageHookMgr = NULL; + +HOOK_MGR *GetBootStageHookMgr() +{ + if (bootStageHookMgr != NULL) { + return bootStageHookMgr; + } + + /* + * Create bootstage hook manager for booting only. + * When boot completed, this manager will be destroyed. + */ + bootStageHookMgr = HookMgrCreate(INIT_BOOTSTAGE_HOOK_NAME); + return bootStageHookMgr; +} diff --git a/services/init/standard/device.c b/services/init/standard/device.c index d73bdff7b..bd2c8ff90 100644 --- a/services/init/standard/device.c +++ b/services/init/standard/device.c @@ -26,7 +26,7 @@ #define DEFAULT_RW_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) #define DEFAULT_NO_AUTHORITY_MODE (S_IWUSR | S_IRUSR) -void MountBasicFs(void) +static void MountBasicFs(void) { if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755") != 0) { INIT_LOGE("Mount tmpfs failed. %s", strerror(errno)); @@ -66,7 +66,7 @@ void MountBasicFs(void) } } -void CreateDeviceNode(void) +static void CreateDeviceNode(void) { if (mknod("/dev/null", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_NULL_MINOR)) != 0) { INIT_LOGE("Create /dev/null device node failed. %s", strerror(errno)); @@ -80,3 +80,23 @@ void CreateDeviceNode(void) } } +static void EnableDevKmsg(void) +{ + /* printk_devkmsg default value is ratelimit, We need to set "on" and remove the restrictions */ + int fd = open("/proc/sys/kernel/printk_devkmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd < 0) { + return; + } + char *kmsgStatus = "on"; + write(fd, kmsgStatus, strlen(kmsgStatus) + 1); + close(fd); + fd = -1; + return; +} + +void CreateFsAndDeviceNode(void) +{ + MountBasicFs(); + CreateDeviceNode(); + EnableDevKmsg(); +} diff --git a/services/init/standard/init.c b/services/init/standard/init.c index 6b1af4012..125f5df46 100755 --- a/services/init/standard/init.c +++ b/services/init/standard/init.c @@ -29,7 +29,6 @@ #include "config_policy_utils.h" #include "device.h" #include "fd_holder_service.h" -#include "fs_manager/fs_manager.h" #include "key_control.h" #include "init_control_fd_service.h" #include "init_log.h" @@ -40,9 +39,6 @@ #include "init_service_manager.h" #include "init_utils.h" #include "securec.h" -#include "switch_root.h" -#include "ueventd.h" -#include "ueventd_socket.h" #include "fd_holder_internal.h" #include "bootstage.h" @@ -108,19 +104,6 @@ void SystemInit(void) InitControlFd(); } -static void EnableDevKmsg(void) -{ - /* printk_devkmsg default value is ratelimit, We need to set "on" and remove the restrictions */ - int fd = open("/proc/sys/kernel/printk_devkmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - if (fd < 0) { - return; - } - char *kmsgStatus = "on"; - write(fd, kmsgStatus, strlen(kmsgStatus) + 1); - close(fd); - return; -} - void LogInit(void) { int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR, @@ -130,135 +113,6 @@ void LogInit(void) } } -static char **GetRequiredDevices(Fstab fstab, int *requiredNum) -{ - int num = 0; - FstabItem *item = fstab.head; - while (item != NULL) { - if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) { - num++; - } - item = item->next; - } - if (num == 0) { - return NULL; - } - char **devices = (char **)calloc(num, sizeof(char *)); - INIT_ERROR_CHECK(devices != NULL, return NULL, "Failed calloc err=%d", errno); - - int i = 0; - item = fstab.head; - while (item != NULL) { - if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) { - devices[i] = strdup(item->deviceName); - INIT_ERROR_CHECK(devices[i] != NULL, FreeStringVector(devices, num); return NULL, - "Failed strdup err=%d", errno); - i++; - } - item = item->next; - } - *requiredNum = num; - return devices; -} - -static int StartUeventd(char **requiredDevices, int num) -{ - INIT_ERROR_CHECK(requiredDevices != NULL && num > 0, return -1, "Failed parameters"); - int ueventSockFd = UeventdSocketInit(); - if (ueventSockFd < 0) { - INIT_LOGE("Failed to create uevent socket"); - return -1; - } - RetriggerUevent(ueventSockFd, requiredDevices, num); - close(ueventSockFd); - return 0; -} - -static void StartInitSecondStage(long long uptime) -{ - int requiredNum = 0; - Fstab *fstab = LoadRequiredFstab(); - char **devices = (fstab != NULL) ? GetRequiredDevices(*fstab, &requiredNum) : NULL; - if (devices != NULL && requiredNum > 0) { - int ret = StartUeventd(devices, requiredNum); - if (ret == 0) { - ret = MountRequriedPartitions(fstab); - } - FreeStringVector(devices, requiredNum); - devices = NULL; - ReleaseFstab(fstab); - fstab = NULL; - if (ret < 0) { - // If mount required partitions failure. - // There is no necessary to continue. - // Just abort - INIT_LOGE("Mount required partitions failed; please check fstab file"); - // Execute sh for debugging -#ifndef STARTUP_INIT_TEST - execv("/bin/sh", NULL); - abort(); -#endif - } - } - - if (fstab != NULL) { - ReleaseFstab(fstab); - fstab = NULL; - } - // It will panic if close stdio before execv("/bin/sh", NULL) - CloseStdio(); - - INIT_LOGI("Start init second stage."); - SwitchRoot("/usr"); - char buf[64]; - snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%lld", uptime); - // Execute init second stage - char * const args[] = { - "/bin/init", - "--second-stage", - buf, - NULL, - }; - if (execv("/bin/init", args) != 0) { - INIT_LOGE("Failed to exec \"/bin/init\", err = %d", errno); - exit(-1); - } -} - -void SystemPrepare(long long uptime) -{ - MountBasicFs(); - CreateDeviceNode(); - LogInit(); - // Make sure init log always output to /dev/kmsg. - EnableDevKmsg(); - INIT_LOGI("Start init first stage."); - HookMgrExecute(GetBootStageHookMgr(), INIT_FIRST_STAGE, NULL, NULL); - // Only ohos normal system support - // two stages of init. - // If we are in updater mode, only one stage of init. - if (InUpdaterMode() == 0) { - StartInitSecondStage(uptime); - } -} - -#define INIT_BOOTSTAGE_HOOK_NAME "bootstage" -static HOOK_MGR *bootStageHookMgr = NULL; - -HOOK_MGR *GetBootStageHookMgr() -{ - if (bootStageHookMgr != NULL) { - return bootStageHookMgr; - } - - /* - * Create bootstage hook manager for booting only. - * When boot completed, this manager will be destroyed. - */ - bootStageHookMgr = HookMgrCreate(INIT_BOOTSTAGE_HOOK_NAME); - return bootStageHookMgr; -} - INIT_TIMING_STAT g_bootJob = {{0}, {0}}; static void RecordInitBootEvent(const char *initBootEvent) diff --git a/services/init/standard/init_mount.c b/services/init/standard/init_mount.c index fbe74bcb1..77087f82b 100644 --- a/services/init/standard/init_mount.c +++ b/services/init/standard/init_mount.c @@ -18,7 +18,6 @@ #include #include #include "fs_manager/fs_manager.h" -#include "init_cmds.h" #include "init_log.h" #include "init_utils.h" #include "securec.h" diff --git a/services/init/standard/main_early.c b/services/init/standard/main_early.c new file mode 100755 index 000000000..be80a0459 --- /dev/null +++ b/services/init/standard/main_early.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023 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 +#include +#include +#include +#include +#include +#include "securec.h" +#include "device.h" +#include "init.h" +#include "init_log.h" +#include "init_utils.h" +#include "init_mount.h" +#include "fs_manager/fs_manager.h" +#include "switch_root.h" +#include "ueventd.h" +#include "ueventd_socket.h" +#include "bootstage.h" + +static char **GetRequiredDevices(Fstab fstab, int *requiredNum) +{ + int num = 0; + FstabItem *item = fstab.head; + while (item != NULL) { + if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) { + num++; + } + item = item->next; + } + if (num == 0) { + return NULL; + } + char **devices = (char **)calloc(num, sizeof(char *)); + INIT_ERROR_CHECK(devices != NULL, return NULL, "Failed calloc err=%d", errno); + + int i = 0; + item = fstab.head; + while (item != NULL) { + if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) { + devices[i] = strdup(item->deviceName); + INIT_ERROR_CHECK(devices[i] != NULL, FreeStringVector(devices, num); return NULL, + "Failed strdup err=%d", errno); + i++; + } + item = item->next; + } + *requiredNum = num; + return devices; +} + +static int StartUeventd(char **requiredDevices, int num) +{ + INIT_ERROR_CHECK(requiredDevices != NULL && num > 0, return -1, "Failed parameters"); + int ueventSockFd = UeventdSocketInit(); + if (ueventSockFd < 0) { + INIT_LOGE("Failed to create uevent socket"); + return -1; + } + RetriggerUevent(ueventSockFd, requiredDevices, num); + close(ueventSockFd); + return 0; +} + +static void MountRequiredPartitions(void) +{ + int requiredNum = 0; + Fstab *fstab = LoadRequiredFstab(); + char **devices = (fstab != NULL) ? GetRequiredDevices(*fstab, &requiredNum) : NULL; + if (devices != NULL && requiredNum > 0) { + int ret = StartUeventd(devices, requiredNum); + if (ret == 0) { + ret = MountRequriedPartitions(fstab); + } + FreeStringVector(devices, requiredNum); + devices = NULL; + ReleaseFstab(fstab); + fstab = NULL; + if (ret < 0) { + // If mount required partitions failure. + // There is no necessary to continue. + // Just abort + INIT_LOGE("Mount required partitions failed; please check fstab file"); + // Execute sh for debugging +#ifndef STARTUP_INIT_TEST + execv("/bin/sh", NULL); + abort(); +#endif + } + } + + if (fstab != NULL) { + ReleaseFstab(fstab); + fstab = NULL; + } +} + +static void StartSecondStageInit(long long uptime) +{ + INIT_LOGI("Start init second stage."); + // It will panic if close stdio before execv("/bin/sh", NULL) + CloseStdio(); + + SwitchRoot("/usr"); + char buf[64]; + snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%lld", uptime); + // Execute init second stage + char * const args[] = { + "/bin/init", + "--second-stage", + buf, + NULL, + }; + if (execv("/bin/init", args) != 0) { + INIT_LOGE("Failed to exec \"/bin/init\", err = %d", errno); + exit(-1); + } +} + +static void EarlyLogInit(void) +{ + int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR, + makedev(MEM_MAJOR, DEV_KMSG_MINOR)); + if (ret == 0) { + OpenLogDevice(); + } +} + +int main(int argc, char * const argv[]) +{ + long long upTimeInMicroSecs = GetUptimeInMicroSeconds(NULL); + + (void)signal(SIGPIPE, SIG_IGN); + + EnableInitLog(INIT_INFO); + EarlyLogInit(); + INIT_LOGI("Start init first stage."); + + CreateFsAndDeviceNode(); + + HookMgrExecute(GetBootStageHookMgr(), INIT_FIRST_STAGE, NULL, NULL); + + MountRequiredPartitions(); + + StartSecondStageInit(upTimeInMicroSecs); + return 0; +} diff --git a/test/unittest/init/init_unittest.cpp b/test/unittest/init/init_unittest.cpp index a327d2ec0..b4511dc33 100644 --- a/test/unittest/init/init_unittest.cpp +++ b/test/unittest/init/init_unittest.cpp @@ -72,13 +72,11 @@ HWTEST_F(InitUnitTest, TestSystemPrepare, TestSize.Level1) { SetStubResult(STUB_MOUNT, -1); SetStubResult(STUB_MKNODE, -1); - MountBasicFs(); - CreateDeviceNode(); + CreateFsAndDeviceNode(); SetStubResult(STUB_MOUNT, 0); SetStubResult(STUB_MKNODE, 0); - MountBasicFs(); - CreateDeviceNode(); + CreateFsAndDeviceNode(); } HWTEST_F(InitUnitTest, TestSystemExecRcs, TestSize.Level1) diff --git a/test/unittest/param/param_stub.cpp b/test/unittest/param/param_stub.cpp index 3340e1d3a..effb9adb6 100644 --- a/test/unittest/param/param_stub.cpp +++ b/test/unittest/param/param_stub.cpp @@ -596,7 +596,6 @@ static __attribute__((constructor(101))) void ParamTestStubInit(void) #ifndef OHOS_LITE TestBeforeInit(); #endif - SystemPrepare(0); #ifndef __LITEOS_A__ SystemInit(); #endif