From 128d724d3b5e516bc1613ff42fb0f6772d89d8f4 Mon Sep 17 00:00:00 2001 From: aleasto Date: Sun, 17 Jan 2021 20:31:22 +0100 Subject: [PATCH] recovery: Support writing to Virtual A/B partitions Change-Id: Ice74e460242a58140fe31240b9fc464848b3aeea --- install/install.cpp | 11 +++++ recovery_utils/include/recovery_utils/roots.h | 2 + recovery_utils/roots.cpp | 47 +++++++++++++------ 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/install/install.cpp b/install/install.cpp index 59a40b8e..aa4040b2 100644 --- a/install/install.cpp +++ b/install/install.cpp @@ -46,6 +46,7 @@ #include #include +#include "install/snapshot_utils.h" #include "install/spl_check.h" #include "install/wipe_data.h" #include "install/wipe_device.h" @@ -408,6 +409,7 @@ static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, bool device_supports_ab = android::base::GetBoolProperty("ro.build.ab_update", false); bool ab_device_supports_nonab = true; bool device_only_supports_ab = device_supports_ab && !ab_device_supports_nonab; + bool device_supports_virtual_ab = android::base::GetBoolProperty("ro.virtual_ab.enabled", false); /*const auto current_spl = android::base::GetProperty("ro.build.version.security_patch", ""); if (ViolatesSPLDowngrade(zip, current_spl)) { @@ -430,6 +432,15 @@ static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, } } + if (!package_is_ab && !logical_partitions_mapped()) { + CreateSnapshotPartitions(); + map_logical_partitions(); + } else if (package_is_ab && device_supports_virtual_ab && logical_partitions_mapped()) { + LOG(ERROR) << "Logical partitions are mapped. " + << "Please reboot recovery before installing an OTA update."; + return INSTALL_ERROR; + } + ReadSourceTargetBuild(metadata, log_buffer); // The updater in child process writes to the pipe to communicate with recovery. diff --git a/recovery_utils/include/recovery_utils/roots.h b/recovery_utils/include/recovery_utils/roots.h index 2e08eea0..aa7b0eeb 100644 --- a/recovery_utils/include/recovery_utils/roots.h +++ b/recovery_utils/include/recovery_utils/roots.h @@ -62,4 +62,6 @@ int setup_install_mounts(); // Returns true if there is /cache in the volumes. bool HasCache(); +void map_logical_partitions(); + bool logical_partitions_mapped(); diff --git a/recovery_utils/roots.cpp b/recovery_utils/roots.cpp index c107aeb6..9f627980 100644 --- a/recovery_utils/roots.cpp +++ b/recovery_utils/roots.cpp @@ -46,6 +46,8 @@ using android::fs_mgr::Fstab; using android::fs_mgr::FstabEntry; using android::fs_mgr::ReadDefaultFstab; +using android::dm::DeviceMapper; +using android::dm::DmDeviceState; static void write_fstab_entry(const FstabEntry& entry, FILE* file) { if (entry.fs_type != "emmc" && !entry.fs_mgr_flags.vold_managed && !entry.blk_device.empty() && @@ -372,8 +374,6 @@ int format_volume(const std::string& volume) { return format_volume(volume, "", ""); } -static bool logical_partitions_auto_mapped = false; - int setup_install_mounts() { if (fstab.empty()) { LOG(ERROR) << "can't set up install mounts: no fstab loaded"; @@ -397,16 +397,6 @@ int setup_install_mounts() { } } } - // Map logical partitions - if (android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) && - !logical_partitions_mapped()) { - std::string super_name = fs_mgr_get_super_partition_name(); - if (!android::fs_mgr::CreateLogicalPartitions("/dev/block/by-name/" + super_name)) { - LOG(ERROR) << "Failed to map logical partitions"; - } else { - logical_partitions_auto_mapped = true; - } - } return 0; } @@ -416,6 +406,35 @@ bool HasCache() { return has_cache; } -bool logical_partitions_mapped() { - return android::fs_mgr::LogicalPartitionsMapped() || logical_partitions_auto_mapped; +static bool logical_partitions_auto_mapped = false; + +void map_logical_partitions() { + if (android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) && + !logical_partitions_mapped()) { + std::string super_name = fs_mgr_get_super_partition_name(); + if (!android::fs_mgr::CreateLogicalPartitions("/dev/block/by-name/" + super_name)) { + LOG(ERROR) << "Failed to map logical partitions"; + } else { + logical_partitions_auto_mapped = true; + } + } +} + +bool dm_find_system() { + auto rec = GetEntryForPath(&fstab, android::fs_mgr::GetSystemRoot()); + if (!rec->fs_mgr_flags.logical) { + return false; + } + // If the fstab entry for system it's a path instead of a name, then it was already mapped + if (rec->blk_device[0] != '/') { + if (DeviceMapper::Instance().GetState(rec->blk_device) == DmDeviceState::INVALID) { + return false; + } + } + return true; +} + +bool logical_partitions_mapped() { + return android::fs_mgr::LogicalPartitionsMapped() || logical_partitions_auto_mapped || + dm_find_system(); }