From bbb1d1a69839328441472660e042a4d3fdacda14 Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Thu, 6 Sep 2018 18:18:34 -0700 Subject: [PATCH] init: allow using the recovery image for 1st stage init For A/B devices, the recovery image is typically provided as a ramdisk paired with boot.img. Instead of repartitioning these devices to have a separate recovery partition and have the new 1st stage ramdisk paired with the boot.img, this allows setting androidboot.force_normal_boot=1 on the kernel command line to have init in recovery boot directly to a normal boot. This requires /system_recovery_mount to be added in the DT fstab for the system partition. Bug: 114062208 Test: hikey boots Change-Id: I1e331b5cca91152d20ca92549779ab41aa9cd431 --- init/first_stage_mount.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index fa3392e06..79cfbcb4e 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -120,8 +120,14 @@ static inline bool IsDtVbmetaCompatible() { return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta"); } -static bool inline IsRecoveryMode() { - return access("/system/bin/recovery", F_OK) == 0; +static bool IsRecoveryMode() { + static bool force_normal_boot = []() { + std::string cmdline; + android::base::ReadFileToString("/proc/cmdline", &cmdline); + return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos; + }(); + + return !force_normal_boot && access("/system/bin/recovery", F_OK) == 0; } static inline bool IsDmLinearEnabled() { @@ -362,14 +368,16 @@ bool FirstStageMount::MountPartitions() { // this case, we mount system first then pivot to it. From that point on, // we are effectively identical to a system-as-root device. auto system_partition = - std::find_if(mount_fstab_recs_.begin(), mount_fstab_recs_.end(), - [](const auto& rec) { return rec->mount_point == "/system"s; }); + std::find_if(mount_fstab_recs_.begin(), mount_fstab_recs_.end(), [](const auto& rec) { + return rec->mount_point == "/system"s || + rec->mount_point == "/system_recovery_mount"s; + }); if (system_partition != mount_fstab_recs_.end()) { if (!MountPartition(*system_partition)) { return false; } - SwitchRoot("/system"); + SwitchRoot((*system_partition)->mount_point); mount_fstab_recs_.erase(system_partition); }