From 3337e782e6f8462c6a2954617e4c59c01ec502be Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Wed, 28 Oct 2020 18:27:43 -0700 Subject: [PATCH] Move e2fsck into /first_stage_ramdisk. On devices without a dedicated recovery partition, it is possible that e2fsck exists in /system/bin, not /first_stage_ramdisk/system/bin, if it is using generic ramdisk. When force_normal_boot, /system/bin/e2fsck would not exist during first stage mount. In this case, move /first_stage_ramdisk/system/bin/e2fsck to /system/bin/e2fsck before switching root into /first_stage_ramdisk. Abort if the operation fails. On devices launching with R, e2fsck should already exist in the correct place, so skip moving if force_normal_boot and /first_stage_ramdisk/system/bin/e2fsck already exists. On devices launching before R, it is possible that /system/bin/e2fsck does not exist. Skip moving if force_normal_boot and /system/bin/e2fsck does not exist. Fixes: 171326057 Test: boot with GKI and move_recover_resources_to_vendor_boot, and check serial output Change-Id: I8008a4cad54c7c74a84cbcabe56723bf0e193025 --- init/first_stage_init.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp index 554f301cc..d2a952fc2 100644 --- a/init/first_stage_init.cpp +++ b/init/first_stage_init.cpp @@ -99,6 +99,34 @@ bool ForceNormalBoot(const std::string& cmdline) { return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos; } +// Move e2fsck before switching root, so that it is available at the same path +// after switching root. +void PrepareSwitchRoot() { + constexpr const char* src = "/system/bin/e2fsck"; + constexpr const char* dst = "/first_stage_ramdisk/system/bin/e2fsck"; + + if (access(dst, X_OK) == 0) { + LOG(INFO) << dst << " already exists and it can be executed"; + return; + } + + if (access(src, F_OK) != 0) { + PLOG(INFO) << "Not moving " << src << " because it cannot be accessed"; + return; + } + + auto dst_dir = android::base::Dirname(dst); + std::error_code ec; + if (!fs::create_directories(dst_dir, ec)) { + LOG(FATAL) << "Cannot create " << dst_dir << ": " << ec.message(); + } + if (rename(src, dst) != 0) { + PLOG(FATAL) << "Cannot move " << src << " to " << dst + << ". Either install e2fsck.ramdisk so that it is at the correct place (" << dst + << "), or make ramdisk writable"; + } +} + } // namespace std::string GetModuleLoadList(bool recovery, const std::string& dir_path) { @@ -298,6 +326,7 @@ int FirstStageMain(int argc, char** argv) { if (ForceNormalBoot(cmdline)) { mkdir("/first_stage_ramdisk", 0755); + PrepareSwitchRoot(); // SwitchRoot() must be called with a mount point as the target, so we bind mount the // target directory to itself here. if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {