fs_mgr_liblp模块-super分区解析

概述

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;
}

补充

参考

posted @ 2021-06-10 19:32  pyjetson  阅读(1285)  评论(0编辑  收藏  举报