在進(jìn)一步分析升級(jí)流程之前,我們先來看下AB升級(jí)情況下的OTA包的結(jié)構(gòu)。
OTA包的結(jié)構(gòu)
├── care_map.pb
├── META-INF
│ └── com
│ └── android
│ ├── metadata
│ └── otacert // release key的公鑰,用來對(duì)ota包做簽名驗(yàn)證
├── payload.bin
└── payload_properties.txt
payload_properties.txt
包含了payload的一些元信息,如文件的hash值,大小等。
FILE_HASH=clGjz1kJ/Toxcax0Ap8d2cCVupI1xoBBXgqOzNK+IeQ=
FILE_SIZE=1345770359
METADATA_HASH=EG0gbI1eQ5PCQhcOovjiP8zK1H14T6CL8znOwAnQRnE=
METADATA_SIZE=98416
metadata
包含了待升級(jí)固件的信息,如版本號(hào),編譯的時(shí)間等
ota-property-files=payload_metadata.bin:1808:98683,payload.bin:1808:1345770359,payload_properties.txt:1345772225:155,care_map.pb:677:1084,metadata:69:561
ota-required-cache=0
ota-streaming-property-files=payload.bin:1808:1345770359,payload_properties.txt:1345772225:155,care_map.pb:677:1084,metadata:69:561
ota-type=AB
post-build=xxx
post-build-incremental=1640652245
post-sdk-level=30
post-security-patch-level=2021-10-05
post-timestamp=1640652162
pre-device=xxx
payload.bin
包含待升級(jí)的鏡像信息
payload.bin的結(jié)構(gòu)
payload隨著AB分區(qū)和update engine引入,其中payload的數(shù)據(jù)定義在
update_metadata.proto中,這個(gè)是protobuf格式的源文件。protobuf是Google推出的跨語(yǔ)言的序列化工具,可以將對(duì)象轉(zhuǎn)換成字節(jié)流保存,并可以通過Java,C++,C#,Python等方式讀寫。
delta_update_file
delta_update_file這個(gè)結(jié)構(gòu)體是payload.bin的數(shù)據(jù)結(jié)構(gòu),解結(jié)構(gòu)體表述如下:
system/update_engine/update_metadata.proto
struct delta_update_file {
char magic[4] = "CrAU";
uint64 file_format_version; // payload major version
uint64 manifest_size; // Size of protobuf DeltaArchiveManifest
// Only present if format_version >= 2:
uint32 metadata_signature_size;
// The DeltaArchiveManifest protobuf serialized, not compressed.
char manifest[manifest_size];
// The signature of the metadata (from the beginning of the payload up to
// this location, not including the signature itself). This is a serialized
// Signatures message.
char metadata_signature_message[metadata_signature_size];
// Data blobs for files, no specific format. The specific offset
// and length of each data blob is recorded in the DeltaArchiveManifest.
struct {
char data[];
} blobs[];
// The signature of the entire payload, everything up to this location,
// except that metadata_signature_message is skipped to simplify signing
// process. These two are not signed:
uint64 payload_signatures_message_size;
// This is a serialized Signatures message.
char payload_signatures_message[payload_signatures_message_size];
};
將結(jié)構(gòu)體轉(zhuǎn)化為圖片分解后如下:

這個(gè)圖片能比較清晰的看到delta_update_file主要分為四個(gè)部分
-
Header
主要是文件格式以及后面的protobuf的長(zhǎng)度,簽名長(zhǎng)度進(jìn)行描述 -
protofuf
DeltaArchiveManifest這個(gè)結(jié)構(gòu)代表的數(shù)據(jù),是payload.bin轉(zhuǎn)給你的核心數(shù)據(jù),存儲(chǔ)了分區(qū)的信息。 -
blob[]
對(duì)應(yīng)于InstallOperation的數(shù)據(jù),至于這個(gè)數(shù)據(jù)有多長(zhǎng),如何操作等信息都存放在DeltaArchiveManifest中 -
signature
存儲(chǔ)包括元數(shù)據(jù)的簽名和payload的簽名
Manifest的數(shù)據(jù)結(jié)構(gòu)
message DeltaArchiveManifest {
// Only present in major version = 1. List of install operations for the
// kernel and rootfs partitions. For major version = 2 see the |partitions|
// field.
repeated InstallOperation install_operations = 1;
repeated InstallOperation kernel_install_operations = 2;
// (At time of writing) usually 4096
optional uint32 block_size = 3 [default = 4096];
// If signatures are present, the offset into the blobs, generally
// tacked onto the end of the file, and the length. We use an offset
// rather than a bool to allow for more flexibility in future file formats.
// If either is absent, it means signatures aren't supported in this
// file.
optional uint64 signatures_offset = 4;
optional uint64 signatures_size = 5;
// Only present in major version = 1. Partition metadata used to validate the
// update. For major version = 2 see the |partitions| field.
optional PartitionInfo old_kernel_info = 6;
optional PartitionInfo new_kernel_info = 7;
optional PartitionInfo old_rootfs_info = 8;
optional PartitionInfo new_rootfs_info = 9;
// old_image_info will only be present for delta images.
optional ImageInfo old_image_info = 10;
optional ImageInfo new_image_info = 11;
// The minor version, also referred as "delta version", of the payload.
// Minor version 0 is full payload, everything else is delta payload.
optional uint32 minor_version = 12 [default = 0];
// Only present in major version >= 2. List of partitions that will be
// updated, in the order they will be updated. This field replaces the
// |install_operations|, |kernel_install_operations| and the
// |{old,new}_{kernel,rootfs}_info| fields used in major version = 1. This
// array can have more than two partitions if needed, and they are identified
// by the partition name.
repeated PartitionUpdate partitions = 13;
// The maximum timestamp of the OS allowed to apply this payload.
// Can be used to prevent downgrading the OS.
optional int64 max_timestamp = 14;
// Metadata related to all dynamic partitions.
optional DynamicPartitionMetadata dynamic_partition_metadata = 15;
}

這里requried指定的成員一定存在;optional指定的成員屬于可選項(xiàng),有可能不存在;而repeated指示的成員我們可以看成是一個(gè)數(shù)組
payload.bin解壓縮
payload.bin可以理解為壓縮文件,可以通過https://github.com/vm03/payload_dumper中的腳本進(jìn)行解壓縮。
使用環(huán)境說明
1.需要使用Python3的環(huán)境執(zhí)行
2.pip3 install bsdiff4
環(huán)境配置完之后,使用payload_dumper.py腳本執(zhí)行
python3 payload_dumper.py -h
usage: payload_dumper.py [-h] [--out OUT] [--diff] [--old OLD]
[--images IMAGES]
payloadfile
OTA payload dumper
positional arguments:
payloadfile payload file name
optional arguments:
-h, --help show this help message and exit
--out OUT output directory (defaul: output)
--diff extract differential OTA, you need put original images to
old dir
--old OLD directory with original images for differential OTA
(defaul: old)
--images IMAGES images to extract (default: empty)
執(zhí)行完之后
python3 payload_dumper.py '/work/update/payload.bin'
Processing boot partition................Done
Processing system partition................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................Done
Processing vendor partition...........................................................................................................................................................Done
Processing preloader partition.Done
Processing md1img partition............Done
Processing md1dsp partition....Done
Processing spmfw partition.Done
Processing scp partition.Done
Processing sspm partition.Done
Processing gz partition.Done
Processing lk partition.Done
Processing dtbo partition.Done
Processing tee partition.Done
Processing vbmeta partition.Done
Processing vbmeta_system partition.Done
Processing vbmeta_vendor partition.Done
Processing product partition................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................Done
如果不指定參數(shù),則默認(rèn)在腳本當(dāng)前目錄下生產(chǎn)解壓縮的文件
├── output
│ ├── boot.img
│ ├── dtbo.img
│ ├── gz.img
│ ├── lk.img
│ ├── md1dsp.img
│ ├── md1img.img
│ ├── preloader.img
│ ├── product.img
│ ├── scp.img
│ ├── spmfw.img
│ ├── sspm.img
│ ├── system.img
│ ├── tee.img
│ ├── vbmeta.img
│ ├── vbmeta_system.img
│ ├── vbmeta_vendor.img
│ └── vendor.img
├── payload_dumper.py
參考鏈接
[1] https://www.cxyzjd.com/article/u011391629/100122248#OTA_Package_Format_107
[2] https://blog.csdn.net/guyongqiangx/article/details/82805813
[3] https://github.com/vm03/payload_dumper