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
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 554f301..d2a952f 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -99,6 +99,34 @@
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 @@
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) {