fs_mgr_liblp模块-super分区解析
目录
- 概述
- 源码解析
- 1. utility模块-工具函数
- 2. reader模块
- 2.1 ReadMetadata-读super分区的metadata信息
- 2.2 ReadLogicalPartitionGeometry-读super分区头部信息
- 2.3 ReadPrimaryGeometry-读基本的Geometry信息
- 2.4 ParseGeometry-比对一下哈希值和struct大小,看Geometry的数据是否是正确的
- 2.5 ParseMetadata-从super分区中读取LpMetadata信息
- 2.6 ReadMetadataHeader-读LpMetadata header信息
- 2.7 AdjustMetadataForSlot-设置ab分区
- 2.8 GetBlockDevicePartitionName
- 2.9 NameFromFixedArray
- 3. PartitionOpener类-打开super分区
- 4. metadata数据结构
- 问题
- 补充
- 参考
概述
android/system/core/fs_mgr/liblp目录下的库,和super分区的数据结构的解析相关
源码解析
1. utility模块-工具函数
1.1 SlotNumberForSlotSuffix-a为0-b为1
uint32_t SlotNumberForSlotSuffix(const std::string& suffix) {
if (suffix.empty() || suffix == "a" || suffix == "_a") {
return 0;
} else if (suffix == "b" || suffix == "_b") {
return 1;
} else {
LERROR << __PRETTY_FUNCTION__ << "slot '" << suffix
<< "' does not have a recognized format.";
return 0;
}
}
1.2 GetControlFileOrOpen-打开设备
base::unique_fd GetControlFileOrOpen(std::string_view path, int flags) {
#if defined(__ANDROID__)
// 通过环境变量获取:
int fd = android_get_control_file(path.data());
if (fd >= 0) {
int newfd = TEMP_FAILURE_RETRY(dup(fd));
if (newfd >= 0) {
return base::unique_fd(newfd);
}
PERROR << "Cannot dup fd for already controlled file: " << path << ", reopening...";
}
#endif
// 一般通过open函数打开分区文件
return base::unique_fd(open(path.data(), flags));
}
1.3 SeekFile64-需要int64_t的offset来进行lseek
int64_t SeekFile64(int fd, int64_t offset, int whence) {
static_assert(sizeof(off_t) == sizeof(int64_t), "Need 64-bit lseek");
return lseek(fd, offset, whence);
}
1.4 GetPrimaryMetadataOffset-返回metadata的offset
int64_t GetPrimaryMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number) {
CHECK(slot_number < geometry.metadata_slot_count);
// 4096(reserve) + 4096*2(GEOMETRY两个) + 0
int64_t offset = LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2) +
geometry.metadata_max_size * slot_number;
return offset;
}
1.5 GetMetadataSuperBlockDevice-直接返回block_devices
const LpMetadataBlockDevice* GetMetadataSuperBlockDevice(const LpMetadata& metadata) {
if (metadata.block_devices.empty()) {
return nullptr;
}
return &metadata.block_devices[0];
}
1.6 SlotSuffixForSlotNumber-0为_a
std::string SlotSuffixForSlotNumber(uint32_t slot_number) {
CHECK(slot_number == 0 || slot_number == 1);
return (slot_number == 0) ? "_a" : "_b";
}
1.7 GetBlockDevicePartitionNames
std::vector<std::string> GetBlockDevicePartitionNames(const LpMetadata& metadata) {
std::vector<std::string> list;
for (const auto& block_device : metadata.block_devices) {
// super分区
list.emplace_back(GetBlockDevicePartitionName(block_device));
}
return list;
}
2. reader模块
2.1 ReadMetadata-读super分区的metadata信息
std::unique_ptr<LpMetadata> ReadMetadata(const std::string& super_partition, uint32_t slot_number) {
return ReadMetadata(PartitionOpener(), super_partition, slot_number);
}
std::unique_ptr<LpMetadata> ReadMetadata(const IPartitionOpener& opener,
const std::string& super_partition, uint32_t slot_number) {
// 打开super分区
android::base::unique_fd fd = opener.Open(super_partition, O_RDONLY);
if (fd < 0) {
PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
return nullptr;
}
LpMetadataGeometry geometry;
// 读LpMetadataGeometry数据
if (!ReadLogicalPartitionGeometry(fd, &geometry)) {
return nullptr;
}
// slot_number 为0
if (slot_number >= geometry.metadata_slot_count) {
LERROR << __PRETTY_FUNCTION__ << " invalid metadata slot number";
return nullptr;
}
std::vector<int64_t> offsets = {
GetPrimaryMetadataOffset(geometry, slot_number),
GetBackupMetadataOffset(geometry, slot_number),
};
std::unique_ptr<LpMetadata> metadata;
for (const auto& offset : offsets) {
if (SeekFile64(fd, offset, SEEK_SET) < 0) {
PERROR << __PRETTY_FUNCTION__ << " lseek failed, offset " << offset;
continue;
}
// 从super分区中读取LpMetadata信息
if ((metadata = ParseMetadata(geometry, fd)) != nullptr) {
break;
}
}
// 设置ab分区的信息
if (!metadata || !AdjustMetadataForSlot(metadata.get(), slot_number)) {
return nullptr;
}
return metadata;
}
2.2 ReadLogicalPartitionGeometry-读super分区头部信息
bool ReadLogicalPartitionGeometry(int fd, LpMetadataGeometry* geometry) {
if (ReadPrimaryGeometry(fd, geometry)) {
return true;
}
// primary的失败了,就读backup的备份的
return ReadBackupGeometry(fd, geometry);
}
2.3 ReadPrimaryGeometry-读基本的Geometry信息
bool ReadPrimaryGeometry(int fd, LpMetadataGeometry* geometry) {
std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
// offset为LP_PARTITION_RESERVED_BYTES 4096
if (SeekFile64(fd, GetPrimaryGeometryOffset(), SEEK_SET) < 0) {
PERROR << __PRETTY_FUNCTION__ << " lseek failed";
return false;
}
// 读数据结构,LP_METADATA_GEOMETRY_SIZE 4096
if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
PERROR << __PRETTY_FUNCTION__ << " read " << LP_METADATA_GEOMETRY_SIZE << " bytes failed";
return false;
}
// 分析LpMetadataGeometry信息
return ParseGeometry(buffer.get(), geometry);
}
2.4 ParseGeometry-比对一下哈希值和struct大小,看Geometry的数据是否是正确的
bool ParseGeometry(const void* buffer, LpMetadataGeometry* geometry) {
static_assert(sizeof(*geometry) <= LP_METADATA_GEOMETRY_SIZE);
memcpy(geometry, buffer, sizeof(*geometry));
// Check the magic signature.
if (geometry->magic != LP_METADATA_GEOMETRY_MAGIC) {
LERROR << "Logical partition metadata has invalid geometry magic signature.";
return false;
}
// Reject if the struct size is larger than what we compiled. This is so we
// can compute a checksum with the |struct_size| field rather than using
// sizeof.
if (geometry->struct_size > sizeof(LpMetadataGeometry)) {
LERROR << "Logical partition metadata has unrecognized fields.";
return false;
}
// Recompute and check the CRC32.
{
// 比对哈希值
LpMetadataGeometry temp = *geometry;
memset(&temp.checksum, 0, sizeof(temp.checksum));
SHA256(&temp, temp.struct_size, temp.checksum);
if (memcmp(temp.checksum, geometry->checksum, sizeof(temp.checksum)) != 0) {
LERROR << "Logical partition metadata has invalid geometry checksum.";
return false;
}
}
// Check that the struct size is equal (this will have to change if we ever
// change the struct size in a release).
if (geometry->struct_size != sizeof(LpMetadataGeometry)) {
LERROR << "Logical partition metadata has invalid struct size.";
return false;
}
if (geometry->metadata_slot_count == 0) {
LERROR << "Logical partition metadata has invalid slot count.";
return false;
}
if (geometry->metadata_max_size % LP_SECTOR_SIZE != 0) {
LERROR << "Metadata max size is not sector-aligned.";
return false;
}
return true;
}
2.5 ParseMetadata-从super分区中读取LpMetadata信息
static std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry,
Reader* reader) {
// First read and validate the header.
std::unique_ptr<LpMetadata> metadata = std::make_unique<LpMetadata>();
metadata->geometry = geometry;
// 读metadata的头部信息
if (!ReadMetadataHeader(reader, metadata.get())) {
return nullptr;
}
LpMetadataHeader& header = metadata->header;
// Sanity check the table size.
if (header.tables_size > geometry.metadata_max_size) {
LERROR << "Invalid partition metadata header table size.";
return nullptr;
}
// Read the metadata payload. Allocation is fallible since the table size
// could be large.
std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[header.tables_size]);
if (!buffer) {
LERROR << "Out of memory reading logical partition tables.";
return nullptr;
}
if (!reader->ReadFully(buffer.get(), header.tables_size)) {
PERROR << __PRETTY_FUNCTION__ << " read " << header.tables_size << "bytes failed";
return nullptr;
}
uint8_t checksum[32];
SHA256(buffer.get(), header.tables_size, checksum);
if (memcmp(checksum, header.tables_checksum, sizeof(checksum)) != 0) {
LERROR << "Logical partition metadata has invalid table checksum.";
return nullptr;
}
uint32_t valid_attributes = LP_PARTITION_ATTRIBUTE_MASK_V0;
if (metadata->header.minor_version >= LP_METADATA_VERSION_FOR_UPDATED_ATTR) {
valid_attributes |= LP_PARTITION_ATTRIBUTE_MASK_V1;
}
// ValidateTableSize ensured that |cursor| is valid for the number of
// entries in the table.
// 下面依次读:下面的信息,并检查边界
// std::vector<LpMetadataPartition> partitions;
// std::vector<LpMetadataExtent> extents;
// std::vector<LpMetadataPartitionGroup> groups;
// std::vector<LpMetadataBlockDevice> block_devices;
uint8_t* cursor = buffer.get() + header.partitions.offset;
for (size_t i = 0; i < header.partitions.num_entries; i++) {
LpMetadataPartition partition;
memcpy(&partition, cursor, sizeof(partition));
cursor += header.partitions.entry_size;
if (partition.attributes & ~valid_attributes) {
LERROR << "Logical partition has invalid attribute set.";
return nullptr;
}
if (partition.first_extent_index + partition.num_extents < partition.first_extent_index) {
LERROR << "Logical partition first_extent_index + num_extents overflowed.";
return nullptr;
}
if (partition.first_extent_index + partition.num_extents > header.extents.num_entries) {
LERROR << "Logical partition has invalid extent list.";
return nullptr;
}
if (partition.group_index >= header.groups.num_entries) {
LERROR << "Logical partition has invalid group index.";
return nullptr;
}
metadata->partitions.push_back(partition);
}
cursor = buffer.get() + header.extents.offset;
for (size_t i = 0; i < header.extents.num_entries; i++) {
LpMetadataExtent extent;
memcpy(&extent, cursor, sizeof(extent));
cursor += header.extents.entry_size;
if (extent.target_type == LP_TARGET_TYPE_LINEAR &&
extent.target_source >= header.block_devices.num_entries) {
LERROR << "Logical partition extent has invalid block device.";
return nullptr;
}
metadata->extents.push_back(extent);
}
cursor = buffer.get() + header.groups.offset;
for (size_t i = 0; i < header.groups.num_entries; i++) {
LpMetadataPartitionGroup group = {};
memcpy(&group, cursor, sizeof(group));
cursor += header.groups.entry_size;
metadata->groups.push_back(group);
}
cursor = buffer.get() + header.block_devices.offset;
for (size_t i = 0; i < header.block_devices.num_entries; i++) {
LpMetadataBlockDevice device = {};
memcpy(&device, cursor, sizeof(device));
cursor += header.block_devices.entry_size;
metadata->block_devices.push_back(device);
}
// LpMetadataBlockDevice不能为空
const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(*metadata.get());
if (!super_device) {
LERROR << "Metadata does not specify a super device.";
return nullptr;
}
// Check that the metadata area and logical partition areas don't overlap.
uint64_t metadata_region =
GetTotalMetadataSize(geometry.metadata_max_size, geometry.metadata_slot_count);
if (metadata_region > super_device->first_logical_sector * LP_SECTOR_SIZE) {
LERROR << "Logical partition metadata overlaps with logical partition contents.";
return nullptr;
}
return metadata;
}
2.6 ReadMetadataHeader-读LpMetadata header信息
static bool ReadMetadataHeader(Reader* reader, LpMetadata* metadata) {
// Note we zero the struct since older files will result in a partial read.
LpMetadataHeader& header = metadata->header;
memset(&header, 0, sizeof(header));
// 读头部信息
if (!reader->ReadFully(&header, sizeof(LpMetadataHeaderV1_0))) {
PERROR << __PRETTY_FUNCTION__ << " read failed";
return false;
}
// 下面都是检查信息是否的正确的
// Do basic sanity checks before computing the checksum.
if (header.magic != LP_METADATA_HEADER_MAGIC) {
LERROR << "Logical partition metadata has invalid magic value.";
return false;
}
if (header.major_version != LP_METADATA_MAJOR_VERSION ||
header.minor_version > LP_METADATA_MINOR_VERSION_MAX) {
LERROR << "Logical partition metadata has incompatible version.";
return false;
}
// Validate the header struct size against the reported version.
uint32_t expected_struct_size = sizeof(header);
if (header.minor_version < LP_METADATA_VERSION_FOR_EXPANDED_HEADER) {
expected_struct_size = sizeof(LpMetadataHeaderV1_0);
}
if (header.header_size != expected_struct_size) {
LERROR << "Invalid partition metadata header struct size.";
return false;
}
// Read in any remaining fields, the last step needed before checksumming.
if (size_t remaining_bytes = header.header_size - sizeof(LpMetadataHeaderV1_0)) {
uint8_t* offset = reinterpret_cast<uint8_t*>(&header) + sizeof(LpMetadataHeaderV1_0);
if (!reader->ReadFully(offset, remaining_bytes)) {
PERROR << __PRETTY_FUNCTION__ << " read failed";
return false;
}
}
// To compute the header's checksum, we have to temporarily set its checksum
// field to 0. Note that we must only compute up to |header_size|.
{
LpMetadataHeader temp = header;
memset(&temp.header_checksum, 0, sizeof(temp.header_checksum));
SHA256(&temp, temp.header_size, temp.header_checksum);
if (memcmp(temp.header_checksum, header.header_checksum, sizeof(temp.header_checksum)) !=
0) {
LERROR << "Logical partition metadata has invalid checksum.";
return false;
}
}
if (!ValidateTableBounds(header, header.partitions) ||
!ValidateTableBounds(header, header.extents) ||
!ValidateTableBounds(header, header.groups) ||
!ValidateTableBounds(header, header.block_devices)) {
LERROR << "Logical partition metadata has invalid table bounds.";
return false;
}
// Check that table entry sizes can accomodate their respective structs. If
// table sizes change, these checks will have to be adjusted.
if (header.partitions.entry_size != sizeof(LpMetadataPartition)) {
LERROR << "Logical partition metadata has invalid partition table entry size.";
return false;
}
if (header.extents.entry_size != sizeof(LpMetadataExtent)) {
LERROR << "Logical partition metadata has invalid extent table entry size.";
return false;
}
if (header.groups.entry_size != sizeof(LpMetadataPartitionGroup)) {
LERROR << "Logical partition metadata has invalid group table entry size.";
return false;
}
return true;
}
2.7 AdjustMetadataForSlot-设置ab分区
bool AdjustMetadataForSlot(LpMetadata* metadata, uint32_t slot_number) {
std::string slot_suffix = SlotSuffixForSlotNumber(slot_number);
for (auto& partition : metadata->partitions) {
// 设置了这个attributes,有vendor_a
if (!(partition.attributes & LP_PARTITION_ATTR_SLOT_SUFFIXED)) {
continue;
}// system_a
std::string partition_name = GetPartitionName(partition) + slot_suffix;
if (partition_name.size() > sizeof(partition.name)) {
LERROR << __PRETTY_FUNCTION__ << " partition name too long: " << partition_name;
return false;
}// 然后又写进去了
strncpy(partition.name, partition_name.c_str(), sizeof(partition.name));
partition.attributes &= ~LP_PARTITION_ATTR_SLOT_SUFFIXED;
}
for (auto& block_device : metadata->block_devices) {
// 没有设置这个flags,所以没有super_a
if (!(block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED)) {
continue;
}
std::string partition_name = GetBlockDevicePartitionName(block_device) + slot_suffix;
if (!UpdateBlockDevicePartitionName(&block_device, partition_name)) {
LERROR << __PRETTY_FUNCTION__ << " partition name too long: " << partition_name;
return false;
}
block_device.flags &= ~LP_BLOCK_DEVICE_SLOT_SUFFIXED;
}
for (auto& group : metadata->groups) {
// 没有设置这个flags,所以没有sb_a
if (!(group.flags & LP_GROUP_SLOT_SUFFIXED)) {
continue;
}
std::string group_name = GetPartitionGroupName(group) + slot_suffix;
if (!UpdatePartitionGroupName(&group, group_name)) {
LERROR << __PRETTY_FUNCTION__ << " group name too long: " << group_name;
return false;
}
group.flags &= ~LP_GROUP_SLOT_SUFFIXED;
}
return true;
}
2.8 GetBlockDevicePartitionName
std::string GetPartitionName(const LpMetadataPartition& partition) {
return NameFromFixedArray(partition.name, sizeof(partition.name));
}
std::string GetPartitionGroupName(const LpMetadataPartitionGroup& group) {
return NameFromFixedArray(group.name, sizeof(group.name));
}
std::string GetBlockDevicePartitionName(const LpMetadataBlockDevice& block_device) {
return NameFromFixedArray(block_device.partition_name, sizeof(block_device.partition_name));
}
2.9 NameFromFixedArray
static std::string NameFromFixedArray(const char* name, size_t buffer_size) {
// If the end of the buffer has a null character, it's safe to assume the
// buffer is null terminated. Otherwise, we cap the string to the input
// buffer size.
if (name[buffer_size - 1] == '\0') {
return std::string(name);
}
return std::string(name, buffer_size);
}
3. PartitionOpener类-打开super分区
3.1 Open-打开super分区-确认绝对路径-以及android环境变量文件
unique_fd PartitionOpener::Open(const std::string& partition_name, int flags) const {
// 获取绝对路径
std::string path = GetPartitionAbsolutePath(partition_name);
// 打开文件
return GetControlFileOrOpen(path.c_str(), flags | O_CLOEXEC);
}
3.2 GetPartitionAbsolutePath-获取块设备的真实路径
std::string GetPartitionAbsolutePath(const std::string& path) {
// 如果本来就是绝对路径,则直接返回
if (android::base::StartsWith(path, "/")) {
return path;
}
auto by_name = "/dev/block/by-name/" + path;
if (access(by_name.c_str(), F_OK) != 0) {
// If the by-name symlink doesn't exist, as a special case we allow
// certain devices to be used as partition names. This can happen if a
// Dynamic System Update is installed to an sdcard, which won't be in
// the boot device list.
//
// We whitelist because most devices in /dev/block are not valid for
// storing fiemaps.
// emmc设备
if (android::base::StartsWith(path, "mmcblk")) {
return "/dev/block/" + path;
}
// nand设备
if (android::base::StartsWith(path, "nand")) {
return "/dev/block/" + path;
}
}
return by_name;
}
3.3 GetDeviceString-获取块设备的真实路径
std::string PartitionOpener::GetDeviceString(const std::string& partition_name) const {
return GetPartitionAbsolutePath(partition_name);
}
4. metadata数据结构
4.2 逻辑分区的结构
/* Default name of the physical partition that holds logical partition entries.
* The layout of this partition will look like:
*
* +--------------------+
* | Disk Geometry |
* +--------------------+
* | Geometry Backup |
* +--------------------+
* | Metadata |
* +--------------------+
* | Backup Metadata |
* +--------------------+
* | Logical Partitions |
* +--------------------+
*/
执行lpdump命令:lpdump /dev/block/by-name/super
Metadata version: 10.0
Metadata size: 516 bytes
Metadata max size: 65536 bytes
Metadata slot count: 2
Header flags: none
Partition table:
------------------------
Name: system
Group: sb
Attributes: readonly
Extents:
0 .. 1672751 linear super 2048
------------------------
Name: vendor
Group: sb
Attributes: readonly
Extents:
0 .. 148471 linear super 1675264
------------------------
Name: product
Group: sb
Attributes: readonly
Extents:
0 .. 2881207 linear super 1824768
------------------------
Super partition layout:
------------------------
super: 2048 .. 1674800: system (1672752 sectors)
super: 1675264 .. 1823736: vendor (148472 sectors)
super: 1824768 .. 4705976: product (2881208 sectors)
------------------------
Block device table:
------------------------
Partition name: super
First sector: 2048
Size: 3758096384 bytes
Flags: none
------------------------
Group table:
------------------------
Name: default
Maximum size: 0 bytes
Flags: none
------------------------
Name: sb
Maximum size: 3749707776 bytes
Flags: none
------------------------
4.2 LpMetadataGeometry
typedef struct LpMetadataGeometry {
/* 0: Magic signature (LP_METADATA_GEOMETRY_MAGIC). */
uint32_t magic;
/* 4: Size of the LpMetadataGeometry struct. */
uint32_t struct_size;
/* 8: SHA256 checksum of this struct, with this field set to 0. */
uint8_t checksum[32];
/* 40: Maximum amount of space a single copy of the metadata can use. This
* must be a multiple of LP_SECTOR_SIZE.
*/
uint32_t metadata_max_size;
/* 44: Number of copies of the metadata to keep. For A/B devices, this
* will be 2. For an A/B/C device, it would be 3, et cetera. For Non-A/B
* it will be 1. A backup copy of each slot is kept, so if this is "2",
* there will be four copies total.
*/
uint32_t metadata_slot_count;
/* 48: Logical block size. This is the minimal alignment for partition and
* extent sizes, and it must be a multiple of LP_SECTOR_SIZE. Note that
* this must be equal across all LUNs that comprise the super partition,
* and thus this field is stored in the geometry, not per-device.
*/
uint32_t logical_block_size;
} __attribute__((packed)) LpMetadataGeometry;
// 告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐
4.3 LpMetadata
struct LpMetadata {
LpMetadataGeometry geometry;
LpMetadataHeader header;
std::vector<LpMetadataPartition> partitions;
std::vector<LpMetadataExtent> extents;
std::vector<LpMetadataPartitionGroup> groups;
std::vector<LpMetadataBlockDevice> block_devices;
};
4.4 LpMetadataHeaderV1_0
typedef struct LpMetadataHeaderV1_0 {
uint32_t magic;
uint16_t major_version;
uint16_t minor_version;
uint32_t header_size;
uint8_t header_checksum[32];
uint32_t tables_size;
uint8_t tables_checksum[32];
LpMetadataTableDescriptor partitions;
LpMetadataTableDescriptor extents;
LpMetadataTableDescriptor groups;
LpMetadataTableDescriptor block_devices;
} __attribute__((packed)) LpMetadataHeaderV1_0;
4.5 busybox hexdump -n 1100000 -C /dev/block/by-name/super
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
* LpMetadataGeometry
00001000 67 44 6c 61 34 00 00 00 4e 31 cf 64 27 54 42 f4 |gDla4...N1.d'TB.|
00001010 0e 25 c7 72 a1 8d 1f cc d8 b1 29 12 32 e5 93 f6 |.%.r......).2...|
00001020 5e 52 2f c7 ac 07 df 03 00 00 01 00 02 00 00 00 |^R/.............|
00001030 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00001040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
* LpMetadataGeometry备份
00002000 67 44 6c 61 34 00 00 00 4e 31 cf 64 27 54 42 f4 |gDla4...N1.d'TB.|
00002010 0e 25 c7 72 a1 8d 1f cc d8 b1 29 12 32 e5 93 f6 |.%.r......).2...|
00002020 5e 52 2f c7 ac 07 df 03 00 00 01 00 02 00 00 00 |^R/.............|
00002030 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00002040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
* LpMetadataHeaderV1_0
00003000 30 50 4c 41 0a 00 00 00 80 00 00 00 5a d9 e6 ae |0PLA........Z...|
00003010 18 4e 1e c7 74 6c 58 c4 db 4e 5a d8 c3 b5 7d 71 |.N..tlX..NZ...}q|
00003020 90 aa 05 33 ad 52 b0 b3 e6 b1 57 92 84 01 00 00 |...3.R....W.....|
00003030 f0 49 05 f2 4b 60 3f b7 c6 a2 5d cb da e6 22 20 |.I..K`?...]..." |
00003040 f3 0c 9e a8 3c 42 d4 f7 7b 2d 66 86 ac 94 14 6c |....<B..{-f....l|
00003050 00 00 00 00 03 00 00 00 34 00 00 00 9c 00 00 00 |........4.......|
00003060 03 00 00 00 18 00 00 00 e4 00 00 00 02 00 00 00 |................|
00003070 30 00 00 00 44 01 00 00 01 00 00 00 40 00 00 00 |0...D.......@...|
LpMetadataPartition
00003080 73 79 73 74 65 6d 00 00 00 00 00 00 00 00 00 00 |system..........|
00003090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000030a0 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 |................|
000030b0 01 00 00 00 76 65 6e 64 6f 72 00 00 00 00 00 00 |....vendor......|
000030c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000030d0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
000030e0 01 00 00 00 01 00 00 00 70 72 6f 64 75 63 74 00 |........product.|
000030f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00003100 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................|
00003110 02 00 00 00 01 00 00 00 01 00 00 00
LpMetadataExtent(1) 30 86 19 00 |............0...|
00003120 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 |................|
00003130 00 00 00 00
LpMetadataExtent(2) f8 43 02 00 00 00 00 00 00 00 00 00 |.....C..........|
00003140 00 90 19 00 00 00 00 00 00 00 00 00
LpMetadataExtent(3) b8 f6 2b 00 |..............+.|
00003150 00 00 00 00 00 00 00 00 00 d8 1b 00 00 00 00 00 |................|
00003160 00 00 00 00
LpMetadataPartitionGroup 64 65 66 61 75 6c 74 00 00 00 00 00 |....default.....|
00003170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00003190 00 00 00 00
LpMetadataPartitionGroup 73 62 00 00 00 00 00 00 00 00 00 00 |....sb..........|
000031a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000031b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 df |................|
000031c0 00 00 00 00
LpMetadataBlockDevice 00 08 00 00 00 00 00 00 00 00 10 00 |................|
000031d0 00 00 00 00 00 00 00 e0 00 00 00 00 73 75 70 65 |............supe|
000031e0 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |r...............|
000031f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00013000 30 50 4c 41 0a 00 00 00 80 00 00 00 5a d9 e6 ae |0PLA........Z...|
00013010 18 4e 1e c7 74 6c 58 c4 db 4e 5a d8 c3 b5 7d 71 |.N..tlX..NZ...}q|
00013020 90 aa 05 33 ad 52 b0 b3 e6 b1 57 92 84 01 00 00 |...3.R....W.....|
00013030 f0 49 05 f2 4b 60 3f b7 c6 a2 5d cb da e6 22 20 |.I..K`?...]..." |
00013040 f3 0c 9e a8 3c 42 d4 f7 7b 2d 66 86 ac 94 14 6c |....<B..{-f....l|
00013050 00 00 00 00 03 00 00 00 34 00 00 00 9c 00 00 00 |........4.......|
00013060 03 00 00 00 18 00 00 00 e4 00 00 00 02 00 00 00 |................|
00013070 30 00 00 00 44 01 00 00 01 00 00 00 40 00 00 00 |0...D.......@...|
00013080 73 79 73 74 65 6d 00 00 00 00 00 00 00 00 00 00 |system..........|
00013090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000130a0 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 |................|
000130b0 01 00 00 00 76 65 6e 64 6f 72 00 00 00 00 00 00 |....vendor......|
000130c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000130d0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
000130e0 01 00 00 00 01 00 00 00 70 72 6f 64 75 63 74 00 |........product.|
000130f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00013100 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................|
00013110 02 00 00 00 01 00 00 00 01 00 00 00 30 86 19 00 |............0...|
00013120 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 |................|
00013130 00 00 00 00 f8 43 02 00 00 00 00 00 00 00 00 00 |.....C..........|
00013140 00 90 19 00 00 00 00 00 00 00 00 00 b8 f6 2b 00 |..............+.|
00013150 00 00 00 00 00 00 00 00 00 d8 1b 00 00 00 00 00 |................|
00013160 00 00 00 00 64 65 66 61 75 6c 74 00 00 00 00 00 |....default.....|
00013170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00013190 00 00 00 00 73 62 00 00 00 00 00 00 00 00 00 00 |....sb..........|
000131a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000131b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 df |................|
000131c0 00 00 00 00 00 08 00 00 00 00 00 00 00 00 10 00 |................|
000131d0 00 00 00 00 00 00 00 e0 00 00 00 00 73 75 70 65 |............supe|
000131e0 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |r...............|
000131f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00023000 30 50 4c 41 0a 00 00 00 80 00 00 00 5a d9 e6 ae |0PLA........Z...|
00023010 18 4e 1e c7 74 6c 58 c4 db 4e 5a d8 c3 b5 7d 71 |.N..tlX..NZ...}q|
00023020 90 aa 05 33 ad 52 b0 b3 e6 b1 57 92 84 01 00 00 |...3.R....W.....|
00023030 f0 49 05 f2 4b 60 3f b7 c6 a2 5d cb da e6 22 20 |.I..K`?...]..." |
00023040 f3 0c 9e a8 3c 42 d4 f7 7b 2d 66 86 ac 94 14 6c |....<B..{-f....l|
00023050 00 00 00 00 03 00 00 00 34 00 00 00 9c 00 00 00 |........4.......|
00023060 03 00 00 00 18 00 00 00 e4 00 00 00 02 00 00 00 |................|
00023070 30 00 00 00 44 01 00 00 01 00 00 00 40 00 00 00 |0...D.......@...|
00023080 73 79 73 74 65 6d 00 00 00 00 00 00 00 00 00 00 |system..........|
00023090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000230a0 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 |................|
000230b0 01 00 00 00 76 65 6e 64 6f 72 00 00 00 00 00 00 |....vendor......|
000230c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000230d0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
000230e0 01 00 00 00 01 00 00 00 70 72 6f 64 75 63 74 00 |........product.|
000230f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00023100 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................|
00023110 02 00 00 00 01 00 00 00 01 00 00 00 30 86 19 00 |............0...|
00023120 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 |................|
00023130 00 00 00 00 f8 43 02 00 00 00 00 00 00 00 00 00 |.....C..........|
00023140 00 90 19 00 00 00 00 00 00 00 00 00 b8 f6 2b 00 |..............+.|
00023150 00 00 00 00 00 00 00 00 00 d8 1b 00 00 00 00 00 |................|
00023160 00 00 00 00 64 65 66 61 75 6c 74 00 00 00 00 00 |....default.....|
00023170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00023190 00 00 00 00 73 62 00 00 00 00 00 00 00 00 00 00 |....sb..........|
000231a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000231b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 df |................|
000231c0 00 00 00 00 00 08 00 00 00 00 00 00 00 00 10 00 |................|
000231d0 00 00 00 00 00 00 00 e0 00 00 00 00 73 75 70 65 |............supe|
000231e0 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |r...............|
000231f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00033000 30 50 4c 41 0a 00 00 00 80 00 00 00 5a d9 e6 ae |0PLA........Z...|
00033010 18 4e 1e c7 74 6c 58 c4 db 4e 5a d8 c3 b5 7d 71 |.N..tlX..NZ...}q|
00033020 90 aa 05 33 ad 52 b0 b3 e6 b1 57 92 84 01 00 00 |...3.R....W.....|
00033030 f0 49 05 f2 4b 60 3f b7 c6 a2 5d cb da e6 22 20 |.I..K`?...]..." |
00033040 f3 0c 9e a8 3c 42 d4 f7 7b 2d 66 86 ac 94 14 6c |....<B..{-f....l|
00033050 00 00 00 00 03 00 00 00 34 00 00 00 9c 00 00 00 |........4.......|
00033060 03 00 00 00 18 00 00 00 e4 00 00 00 02 00 00 00 |................|
00033070 30 00 00 00 44 01 00 00 01 00 00 00 40 00 00 00 |0...D.......@...|
00033080 73 79 73 74 65 6d 00 00 00 00 00 00 00 00 00 00 |system..........|
00033090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000330a0 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 |................|
000330b0 01 00 00 00 76 65 6e 64 6f 72 00 00 00 00 00 00 |....vendor......|
000330c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000330d0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
000330e0 01 00 00 00 01 00 00 00 70 72 6f 64 75 63 74 00 |........product.|
000330f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00033100 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................|
00033110 02 00 00 00 01 00 00 00 01 00 00 00 30 86 19 00 |............0...|
00033120 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 |................|
00033130 00 00 00 00 f8 43 02 00 00 00 00 00 00 00 00 00 |.....C..........|
00033140 00 90 19 00 00 00 00 00 00 00 00 00 b8 f6 2b 00 |..............+.|
00033150 00 00 00 00 00 00 00 00 00 d8 1b 00 00 00 00 00 |................|
00033160 00 00 00 00 64 65 66 61 75 6c 74 00 00 00 00 00 |....default.....|
00033170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00033190 00 00 00 00 73 62 00 00 00 00 00 00 00 00 00 00 |....sb..........|
000331a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000331b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 df |................|
000331c0 00 00 00 00 00 08 00 00 00 00 00 00 00 00 10 00 |................|
000331d0 00 00 00 00 00 00 00 e0 00 00 00 00 73 75 70 65 |............supe|
000331e0 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |r...............|
000331f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00100400 10 0a 00 00 ce 23 03 00 00 00 00 00 6f 02 00 00 |.....#......o...|
问题
1. nand设备OTA升级data分区读失败了
对于UDISK分区,GetPartitionAbsolutePath函数没有提供对nand设备的支持
解决办法:将UDISK改成userdata,或添加对nand设备的识别,如下所示
std::string GetPartitionAbsolutePath(const std::string& path) {
// 如果本来就是绝对路径,则直接返回
if (android::base::StartsWith(path, "/")) {
return path;
}
auto by_name = "/dev/block/by-name/" + path;
if (access(by_name.c_str(), F_OK) != 0) {
// If the by-name symlink doesn't exist, as a special case we allow
// certain devices to be used as partition names. This can happen if a
// Dynamic System Update is installed to an sdcard, which won't be in
// the boot device list.
//
// We whitelist because most devices in /dev/block are not valid for
// storing fiemaps.
// emmc设备
if (android::base::StartsWith(path, "mmcblk")) {
return "/dev/block/" + path;
}
// nand设备
if (android::base::StartsWith(path, "nand")) {
return "/dev/block/" + path;
}
}
return by_name;
}