summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot_control_android.cc7
-rw-r--r--boot_control_android_unittest.cc15
-rw-r--r--dynamic_partition_control_android.cc49
-rw-r--r--dynamic_partition_control_android.h4
-rw-r--r--dynamic_partition_control_interface.h6
-rw-r--r--mock_dynamic_partition_control.h4
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*,