From 6d07b276091c8336e0336542d8b9cf6253393001 Mon Sep 17 00:00:00 2001 From: handyohos Date: Wed, 25 Oct 2023 22:44:54 +0800 Subject: [PATCH] Feat: /system/bin/init support first stage init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 把first stage init阶段完成的内容拆分到init_firststage.c中 2. ramdisk和system中的init都链接init_firststage.c,使得没有ramdisk的产品也可以分阶段启动。 Signed-off-by: handyohos Change-Id: Ib45286e1e8f451d5aa30091d052ada6e6ce72cdf #I8AX9X --- services/init/include/init.h | 1 + services/init/lite/init.c | 4 + services/init/main.c | 9 +- services/init/standard/BUILD.gn | 6 +- services/init/standard/init_firststage.c | 164 +++++++++++++++++++++++ services/init/standard/main_early.c | 140 +------------------ 6 files changed, 181 insertions(+), 143 deletions(-) create mode 100755 services/init/standard/init_firststage.c diff --git a/services/init/include/init.h b/services/init/include/init.h index dd2e82bb8..b856a2f78 100644 --- a/services/init/include/init.h +++ b/services/init/include/init.h @@ -42,6 +42,7 @@ 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 cf7e367cd..9071b66d6 100644 --- a/services/init/lite/init.c +++ b/services/init/lite/init.c @@ -46,6 +46,10 @@ void LogInit(void) return; } +void SystemPrepare(long long uptime) +{ +} + void ParseInitCfgByPriority(void) { ReadFileInDir(OTHER_CFG_PATH, ".cfg", ParseInitCfg, NULL); diff --git a/services/init/main.c b/services/init/main.c index fcfd347c0..f7d23198d 100644 --- a/services/init/main.c +++ b/services/init/main.c @@ -23,6 +23,7 @@ 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,6 +32,8 @@ 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()); @@ -40,11 +43,11 @@ int main(int argc, char * const argv[]) // Updater mode if (isSecondStage == 0) { - CreateFsAndDeviceNode(); + SystemPrepare(upTimeInMicroSecs); + } else { + LogInit(); } - LogInit(); - SystemInit(); SystemExecuteRcs(); SystemConfig(uptime); diff --git a/services/init/standard/BUILD.gn b/services/init/standard/BUILD.gn index 595b2b45b..c0a8310d5 100644 --- a/services/init/standard/BUILD.gn +++ b/services/init/standard/BUILD.gn @@ -36,6 +36,7 @@ ohos_executable("init_early") { "//base/startup/init/services/log/init_commlog.c", "bootstagehooker.c", "device.c", + "init_firststage.c", "init_mount.c", "main_early.c", "switch_root.c", @@ -70,10 +71,13 @@ ohos_executable("init") { "../standard/init_cmdexecutor.c", "../standard/init_cmds.c", "../standard/init_control_fd_service.c", + "../standard/init_firststage.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", ] @@ -97,7 +101,6 @@ 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", @@ -106,6 +109,7 @@ 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", ] diff --git a/services/init/standard/init_firststage.c b/services/init/standard/init_firststage.c new file mode 100755 index 000000000..04ffcb534 --- /dev/null +++ b/services/init/standard/init_firststage.c @@ -0,0 +1,164 @@ +/* + * 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(); + } +} + +void SystemPrepare(long long upTimeInMicroSecs) +{ + (void)signal(SIGPIPE, SIG_IGN); + + EnableInitLog(INIT_INFO); + EarlyLogInit(); + INIT_LOGI("Start init first stage."); + + CreateFsAndDeviceNode(); + + HookMgrExecute(GetBootStageHookMgr(), INIT_FIRST_STAGE, NULL, NULL); + + // Updater mode no need to mount and switch root + if (InUpdaterMode() != 0) { + return; + } + + MountRequiredPartitions(); + + StartSecondStageInit(upTimeInMicroSecs); +} diff --git a/services/init/standard/main_early.c b/services/init/standard/main_early.c index be80a0459..a9f3739c3 100755 --- a/services/init/standard/main_early.c +++ b/services/init/standard/main_early.c @@ -12,151 +12,13 @@ * 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); + SystemPrepare(upTimeInMicroSecs); return 0; } -- Gitee