diff options
-rw-r--r-- | boot_control_android.cc | 7 | ||||
-rw-r--r-- | boot_control_android_unittest.cc | 15 | ||||
-rw-r--r-- | dynamic_partition_control_android.cc | 49 | ||||
-rw-r--r-- | dynamic_partition_control_android.h | 4 | ||||
-rw-r--r-- | dynamic_partition_control_interface.h | 6 | ||||
-rw-r--r-- | mock_dynamic_partition_control.h | 4 |
6 files changed, 61 insertions, 24 deletions
diff --git a/boot_control_android.cc b/boot_control_android.cc index 4568fe44..1d131391 100644 --- a/boot_control_android.cc +++ b/boot_control_android.cc @@ -119,7 +119,8 @@ DynamicPartitionDeviceStatus GetDynamicPartitionDevice( const string& partition_name_suffix, Slot slot, string* device) { - auto builder = dynamic_control->LoadMetadataBuilder(super_device, slot); + auto builder = dynamic_control->LoadMetadataBuilder( + super_device, slot, BootControlInterface::kInvalidSlot); if (builder == nullptr) { if (!dynamic_control->IsDynamicPartitionsEnabled()) { @@ -284,8 +285,8 @@ bool InitPartitionMetadataInternal( Slot target_slot, const string& target_suffix, const PartitionMetadata& partition_metadata) { - auto builder = - dynamic_control->LoadMetadataBuilder(super_device, source_slot); + auto builder = dynamic_control->LoadMetadataBuilder( + super_device, source_slot, target_slot); if (builder == nullptr) { // TODO(elsk): allow reconstructing metadata from partition_metadata // in recovery sideload. diff --git a/boot_control_android_unittest.cc b/boot_control_android_unittest.cc index e98d2f4b..6460ffec 100644 --- a/boot_control_android_unittest.cc +++ b/boot_control_android_unittest.cc @@ -298,10 +298,12 @@ class BootControlAndroidTest : public ::testing::Test { } void SetMetadata(uint32_t slot, const PartitionMetadata& metadata) { - EXPECT_CALL(dynamicControl(), LoadMetadataBuilder(GetSuperDevice(), slot)) + EXPECT_CALL(dynamicControl(), + LoadMetadataBuilder(GetSuperDevice(), slot, _)) .Times(AnyNumber()) - .WillRepeatedly(Invoke( - [metadata](auto, auto) { return NewFakeMetadata(metadata); })); + .WillRepeatedly(Invoke([metadata](auto, auto, auto) { + return NewFakeMetadata(metadata); + })); } // Expect that MapPartitionOnDeviceMapper is called on target() metadata slot @@ -394,7 +396,7 @@ class BootControlAndroidTest : public ::testing::Test { .Times(0); // Should not load metadata from target slot. EXPECT_CALL(dynamicControl(), - LoadMetadataBuilder(GetSuperDevice(), target())) + LoadMetadataBuilder(GetSuperDevice(), target(), _)) .Times(0); } @@ -512,8 +514,9 @@ TEST_P(BootControlAndroidTestP, DeleteAll) { // Test corrupt source metadata case. TEST_P(BootControlAndroidTestP, CorruptedSourceMetadata) { - EXPECT_CALL(dynamicControl(), LoadMetadataBuilder(GetSuperDevice(), source())) - .WillOnce(Invoke([](auto, auto) { return nullptr; })); + EXPECT_CALL(dynamicControl(), + LoadMetadataBuilder(GetSuperDevice(), source(), _)) + .WillOnce(Invoke([](auto, auto, auto) { return nullptr; })); EXPECT_FALSE(InitPartitionMetadata(target(), {{"system", 1_GiB}})) << "Should not be able to continue with corrupt source metadata"; } diff --git a/dynamic_partition_control_android.cc b/dynamic_partition_control_android.cc index 38c67594..93a0fae6 100644 --- a/dynamic_partition_control_android.cc +++ b/dynamic_partition_control_android.cc @@ -37,10 +37,13 @@ using android::dm::DmDeviceState; using android::fs_mgr::CreateLogicalPartition; using android::fs_mgr::DestroyLogicalPartition; using android::fs_mgr::MetadataBuilder; +using android::fs_mgr::PartitionOpener; namespace chromeos_update_engine { -constexpr char kUseDynamicPartitions[] = "ro.boot.logical_partitions"; +constexpr char kUseDynamicPartitions[] = "ro.boot.dynamic_partitions"; +constexpr char kRetrfoitDynamicPartitions[] = + "ro.boot.dynamic_partitions_retrofit"; constexpr uint64_t kMapTimeoutMillis = 1000; DynamicPartitionControlAndroid::~DynamicPartitionControlAndroid() { @@ -51,6 +54,10 @@ bool DynamicPartitionControlAndroid::IsDynamicPartitionsEnabled() { return GetBoolProperty(kUseDynamicPartitions, false); } +static bool IsDynamicPartitionsRetrofit() { + return GetBoolProperty(kRetrfoitDynamicPartitions, false); +} + bool DynamicPartitionControlAndroid::MapPartitionOnDeviceMapper( const std::string& super_device, const std::string& target_partition_name, @@ -122,8 +129,20 @@ bool DynamicPartitionControlAndroid::GetDmDevicePathByName( std::unique_ptr<MetadataBuilder> DynamicPartitionControlAndroid::LoadMetadataBuilder( - const std::string& super_device, uint32_t source_slot) { - auto builder = MetadataBuilder::New(super_device, source_slot); + const std::string& super_device, + uint32_t source_slot, + uint32_t target_slot) { + std::unique_ptr<MetadataBuilder> builder; + + if (target_slot != BootControlInterface::kInvalidSlot && + IsDynamicPartitionsRetrofit()) { + builder = MetadataBuilder::NewForUpdate( + PartitionOpener(), super_device, source_slot, target_slot); + } else { + builder = + MetadataBuilder::New(PartitionOpener(), super_device, source_slot); + } + if (builder == nullptr) { LOG(WARNING) << "No metadata slot " << BootControlInterface::SlotName(source_slot) << " in " @@ -148,16 +167,24 @@ bool DynamicPartitionControlAndroid::StoreMetadata( return false; } - if (!UpdatePartitionTable(super_device, *metadata, target_slot)) { - LOG(ERROR) << "Cannot write metadata to slot " - << BootControlInterface::SlotName(target_slot) << " in " - << super_device; - return false; + if (IsDynamicPartitionsRetrofit()) { + if (!FlashPartitionTable(super_device, *metadata)) { + LOG(ERROR) << "Cannot write metadata to " << super_device; + return false; + } + LOG(INFO) << "Written metadata to " << super_device; + } else { + if (!UpdatePartitionTable(super_device, *metadata, target_slot)) { + LOG(ERROR) << "Cannot write metadata to slot " + << BootControlInterface::SlotName(target_slot) << " in " + << super_device; + return false; + } + LOG(INFO) << "Copied metadata to slot " + << BootControlInterface::SlotName(target_slot) << " in " + << super_device; } - LOG(INFO) << "Copied metadata to slot " - << BootControlInterface::SlotName(target_slot) << " in " - << super_device; return true; } diff --git a/dynamic_partition_control_android.h b/dynamic_partition_control_android.h index 91c9f877..52d4f5bd 100644 --- a/dynamic_partition_control_android.h +++ b/dynamic_partition_control_android.h @@ -43,7 +43,9 @@ class DynamicPartitionControlAndroid : public DynamicPartitionControlInterface { bool GetDmDevicePathByName(const std::string& name, std::string* path) override; std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder( - const std::string& super_device, uint32_t source_slot) override; + const std::string& super_device, + uint32_t source_slot, + uint32_t target_slot) override; bool StoreMetadata(const std::string& super_device, android::fs_mgr::MetadataBuilder* builder, uint32_t target_slot) override; diff --git a/dynamic_partition_control_interface.h b/dynamic_partition_control_interface.h index 95b01a1b..b92d88ab 100644 --- a/dynamic_partition_control_interface.h +++ b/dynamic_partition_control_interface.h @@ -74,8 +74,12 @@ class DynamicPartitionControlInterface { std::string* path) = 0; // Retrieve metadata from |super_device| at slot |source_slot|. + // On retrofit devices, if |target_slot| != kInvalidSlot, the returned + // metadata automatically includes block devices at |target_slot|. virtual std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder( - const std::string& super_device, uint32_t source_slot) = 0; + const std::string& super_device, + uint32_t source_slot, + uint32_t target_slot) = 0; // Write metadata |builder| to |super_device| at slot |target_slot|. virtual bool StoreMetadata(const std::string& super_device, diff --git a/mock_dynamic_partition_control.h b/mock_dynamic_partition_control.h index 6b233b35..7b375813 100644 --- a/mock_dynamic_partition_control.h +++ b/mock_dynamic_partition_control.h @@ -38,9 +38,9 @@ class MockDynamicPartitionControl : public DynamicPartitionControlInterface { MOCK_METHOD1(DeviceExists, bool(const std::string&)); MOCK_METHOD1(GetState, ::android::dm::DmDeviceState(const std::string&)); MOCK_METHOD2(GetDmDevicePathByName, bool(const std::string&, std::string*)); - MOCK_METHOD2(LoadMetadataBuilder, + MOCK_METHOD3(LoadMetadataBuilder, std::unique_ptr<::android::fs_mgr::MetadataBuilder>( - const std::string&, uint32_t)); + const std::string&, uint32_t, uint32_t)); MOCK_METHOD3(StoreMetadata, bool(const std::string&, android::fs_mgr::MetadataBuilder*, |