diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp index b6d6da1b9..9fe92df56 100644 --- a/fs_mgr/liblp/builder.cpp +++ b/fs_mgr/liblp/builder.cpp @@ -623,6 +623,9 @@ std::unique_ptr MetadataBuilder::Export() { LERROR << "Partition group name is too long: " << group->name(); return nullptr; } + if (auto_slot_suffixing_ && group->name() != "default") { + out.flags |= LP_GROUP_SLOT_SUFFIXED; + } strncpy(out.name, group->name().c_str(), sizeof(out.name)); out.maximum_size = group->maximum_size(); diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h index c2e25fbfb..9c5ec5c93 100644 --- a/fs_mgr/liblp/include/liblp/metadata_format.h +++ b/fs_mgr/liblp/include/liblp/metadata_format.h @@ -38,7 +38,7 @@ extern "C" { #define LP_METADATA_HEADER_MAGIC 0x414C5030 /* Current metadata version. */ -#define LP_METADATA_MAJOR_VERSION 9 +#define LP_METADATA_MAJOR_VERSION 10 #define LP_METADATA_MINOR_VERSION 0 /* Attributes for the LpMetadataPartition::attributes field. @@ -267,10 +267,19 @@ typedef struct LpMetadataPartitionGroup { /* 0: Name of this group. Any unused characters must be 0. */ char name[36]; - /* 36: Maximum size in bytes. If 0, the group has no maximum size. */ + /* 36: Flags (see LP_GROUP_*). */ + uint32_t flags; + + /* 40: Maximum size in bytes. If 0, the group has no maximum size. */ uint64_t maximum_size; } LpMetadataPartitionGroup; +/* This flag is only intended to be used with super_empty.img and super.img on + * retrofit devices. If set, the group needs a slot suffix to be interpreted + * correctly. The suffix is automatically applied by ReadMetadata(). + */ +#define LP_GROUP_SLOT_SUFFIXED (1 << 0) + /* This struct defines an entry in the block_devices table. There must be at * least one device, and the first device must represent the partition holding * the super metadata. diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp index 9acf23e8e..b539d776a 100644 --- a/fs_mgr/liblp/io_test.cpp +++ b/fs_mgr/liblp/io_test.cpp @@ -622,6 +622,7 @@ TEST(liblp, AutoSlotSuffixing) { unique_ptr builder = CreateDefaultBuilder(); ASSERT_NE(builder, nullptr); ASSERT_TRUE(AddDefaultPartitions(builder.get())); + ASSERT_TRUE(builder->AddGroup("example", 0)); builder->SetAutoSlotSuffixing(); auto fd = CreateFakeDisk(); @@ -641,6 +642,11 @@ TEST(liblp, AutoSlotSuffixing) { EXPECT_EQ(GetPartitionName(metadata->partitions[0]), "system_b"); ASSERT_EQ(metadata->block_devices.size(), static_cast(1)); EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "super_b"); + ASSERT_EQ(metadata->groups.size(), static_cast(2)); + EXPECT_EQ(GetPartitionGroupName(metadata->groups[0]), "default"); + EXPECT_EQ(GetPartitionGroupName(metadata->groups[1]), "example_b"); + EXPECT_EQ(metadata->groups[0].flags, 0); + EXPECT_EQ(metadata->groups[1].flags, 0); metadata = ReadMetadata(opener, "super_a", 0); ASSERT_NE(metadata, nullptr); @@ -648,6 +654,11 @@ TEST(liblp, AutoSlotSuffixing) { EXPECT_EQ(GetPartitionName(metadata->partitions[0]), "system_a"); ASSERT_EQ(metadata->block_devices.size(), static_cast(1)); EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "super_a"); + ASSERT_EQ(metadata->groups.size(), static_cast(2)); + EXPECT_EQ(GetPartitionGroupName(metadata->groups[0]), "default"); + EXPECT_EQ(GetPartitionGroupName(metadata->groups[1]), "example_a"); + EXPECT_EQ(metadata->groups[0].flags, 0); + EXPECT_EQ(metadata->groups[1].flags, 0); } TEST(liblp, UpdateRetrofit) { diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp index b36ba0eb5..305e6c79d 100644 --- a/fs_mgr/liblp/reader.cpp +++ b/fs_mgr/liblp/reader.cpp @@ -375,6 +375,18 @@ bool AdjustMetadataForSlot(LpMetadata* metadata, uint32_t slot_number) { } block_device.flags &= ~LP_BLOCK_DEVICE_SLOT_SUFFIXED; } + for (auto& group : metadata->groups) { + if (!(group.flags & LP_GROUP_SLOT_SUFFIXED)) { + continue; + } + std::string group_name = GetPartitionGroupName(group) + slot_suffix; + if (group_name.size() > sizeof(group.name)) { + LERROR << __PRETTY_FUNCTION__ << " group name too long: " << group_name; + return false; + } + strncpy(group.name, group_name.c_str(), sizeof(group.name)); + group.flags &= ~LP_GROUP_SLOT_SUFFIXED; + } return true; }