android13 boot类镜像解析
android 包含的boot类镜像有哪些:
boot.img
recovery.img
vendor_boot.img
init_boot.img
vendor_kernel_boot.img
等
boot类镜像的结构:
system/tools/mkbootimg/include/bootimg/bootimg.h:
#pragma once
#include <stdint.h>
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
#define VENDOR_BOOT_MAGIC "VNDRBOOT"
#define VENDOR_BOOT_MAGIC_SIZE 8
#define VENDOR_BOOT_ARGS_SIZE 2048
#define VENDOR_BOOT_NAME_SIZE 16
#define VENDOR_RAMDISK_TYPE_NONE 0
#define VENDOR_RAMDISK_TYPE_PLATFORM 1
#define VENDOR_RAMDISK_TYPE_RECOVERY 2
#define VENDOR_RAMDISK_TYPE_DLKM 3
#define VENDOR_RAMDISK_NAME_SIZE 32
#define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16
/* When a boot header is of version 0, the structure of boot image is as
* follows:
*
* +-----------------+
* | boot header | 1 page
* +-----------------+
* | kernel | n pages
* +-----------------+
* | ramdisk | m pages
* +-----------------+
* | second stage | o pages
* +-----------------+
*
* n = (kernel_size + page_size - 1) / page_size
* m = (ramdisk_size + page_size - 1) / page_size
* o = (second_size + page_size - 1) / page_size
*
* 0. all entities are page_size aligned in flash =>所有flash中的条目都是pase_size对齐
* 1. kernel and ramdisk are required (size != 0) => kernel和ramdisk被需要(并且大小!=0)
* 2. second is optional (second_size == 0 -> no second) => second 是可选的(second_size == 0 -> 没有 second)
* 3. load each element (kernel, ramdisk, second) at the specified physical address (kernel_addr, etc)
* => 在指定的物理地址(kernel_addr 等)加载每个元素(kernel、ramdisk、second)
* 4. prepare tags at tag_addr. kernel_args[] is appended to the kernel commandline in the tags.
* => 在 tag_addr 准备标签。 kernel_args[] 附加到标签中的内核命令行。
* 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
* 6. if second_size != 0: jump to second_addr
* else: jump to kernel_addr
*/
struct boot_img_hdr_v0 {
// Must be BOOT_MAGIC.
uint8_t magic[BOOT_MAGIC_SIZE]; // "ANDROID!"占8字节
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t tags_addr; /* physical addr for kernel tags (if required) */
uint32_t page_size; /* flash page size we assume */
// Version of the boot image header. => boot镜像头的版本,偏移量为40(0x28)个字节
uint32_t header_version;
// Operating system version and security patch level.
// For version "A.B.C" and patch level "Y-M-D":
// (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M)
// os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0]
uint32_t os_version;
#if __cplusplus
void SetOsVersion(unsigned major, unsigned minor, unsigned patch) {
os_version &= ((1 << 11) - 1);
os_version |= (((major & 0x7f) << 25) | ((minor & 0x7f) << 18) | ((patch & 0x7f) << 11));
}
void SetOsPatchLevel(unsigned year, unsigned month) {
os_version &= ~((1 << 11) - 1);
os_version |= (((year - 2000) & 0x7f) << 4) | ((month & 0xf) << 0);
}
#endif
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */ // 16字节的产品名大小,
uint8_t cmdline[BOOT_ARGS_SIZE]; /* asciiz kernel commandline */ // 512字节的kernel命令行
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
// Supplemental command line data; kept here to maintain
// binary compatibility with older versions of mkbootimg.
// Asciiz.
uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; // 1024字节的额外命令行,主要与旧版本的mkbootimg兼容
} __attribute__((packed));
/*
* It is expected that callers would explicitly specify which version of the
* boot image header they need to use.
* 预期调用者将明确指定他们需要使用哪个版本的引导映像标头。
*/
typedef struct boot_img_hdr_v0 boot_img_hdr; //1632(0x660)个字节
/* When a boot header is of version 1, the structure of boot image is as
* follows:
*
* +---------------------+
* | boot header | 1 page
* +---------------------+
* | kernel | n pages
* +---------------------+
* | ramdisk | m pages
* +---------------------+
* | second stage | o pages
* +---------------------+
* | recovery dtbo/acpio | p pages
* +---------------------+
*
* n = (kernel_size + page_size - 1) / page_size
* m = (ramdisk_size + page_size - 1) / page_size
* o = (second_size + page_size - 1) / page_size
* p = (recovery_dtbo_size + page_size - 1) / page_size
*
* 0. all entities are page_size aligned in flash
* 1. kernel and ramdisk are required (size != 0)
* 2. recovery_dtbo/recovery_acpio is required for recovery.img in non-A/B
* devices(recovery_dtbo_size != 0)
* 非 A/B 设备中的 recovery.img 需要 recovery_dtbo/recovery_acpio (recovery_dtbo_size != 0)
* 3. second is optional (second_size == 0 -> no second)
* 4. load each element (kernel, ramdisk, second) at
* the specified physical address (kernel_addr, etc)
* 5. If booting to recovery mode in a non-A/B device, extract recovery
* dtbo/acpio and apply the correct set of overlays on the base device tree
* depending on the hardware/product revision.
* 如果在非 A/B 设备中启动到recovery模式,请提取recovery dtbo/acpio 并根据硬件/产品版本
* 在基本设备树上应用正确的overlays集。
* 6. set up registers for kernel entry as required by your architecture
* 根据您的体系结构的要求为内核入口设置寄存器
* 7. if second_size != 0: jump to second_addr
* else: jump to kernel_addr
*/
struct boot_img_hdr_v1 : public boot_img_hdr_v0 {
uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO/ACPIO image */
uint64_t recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */
uint32_t header_size;
} __attribute__((packed)); //1648(0x670)个字节
/* When the boot image header has a version of 2, the structure of the boot
* image is as follows:
*
* +---------------------+
* | boot header | 1 page
* +---------------------+
* | kernel | n pages
* +---------------------+
* | ramdisk | m pages
* +---------------------+
* | second stage | o pages
* +---------------------+
* | recovery dtbo/acpio | p pages
* +---------------------+
* | dtb | q pages
* +---------------------+
* n = (kernel_size + page_size - 1) / page_size
* m = (ramdisk_size + page_size - 1) / page_size
* o = (second_size + page_size - 1) / page_size
* p = (recovery_dtbo_size + page_size - 1) / page_size
* q = (dtb_size + page_size - 1) / page_size
*
* 0. all entities are page_size aligned in flash
* 1. kernel, ramdisk and DTB are required (size != 0)
* 2. recovery_dtbo/recovery_acpio is required for recovery.img in non-A/B
* devices(recovery_dtbo_size != 0)
* 3. second is optional (second_size == 0 -> no second)
* 4. load each element (kernel, ramdisk, second, dtb) at
* the specified physical address (kernel_addr, etc)
* 5. If booting to recovery mode in a non-A/B device, extract recovery
* dtbo/acpio and apply the correct set of overlays on the base device tree
* depending on the hardware/product revision.
* 6. set up registers for kernel entry as required by your architecture
* 7. if second_size != 0: jump to second_addr
* else: jump to kernel_addr
*/
struct boot_img_hdr_v2 : public boot_img_hdr_v1 {
uint32_t dtb_size; /* size in bytes for DTB image */
uint64_t dtb_addr; /* physical load address for DTB image */
} __attribute__((packed)); //1660(0x67C)个字节
上面的版本0,1,2差异不大
==============================================
下面的版本3,4重构了,差异较大
/* When the boot image header has a version of 3, the structure of the boot
* image is as follows:
*
* +---------------------+
* | boot header | 4096 bytes
* +---------------------+
* | kernel | m pages
* +---------------------+
* | ramdisk | n pages
* +---------------------+
*
* m = (kernel_size + 4096 - 1) / 4096
* n = (ramdisk_size + 4096 - 1) / 4096
*
* Note that in version 3 of the boot image header, page size is fixed at 4096 bytes.
* 请注意,在版本 3 的引导映像标头中,页面大小固定为 4096 字节。
* The structure of the vendor boot image (introduced with version 3 and
* required to be present when a v3 boot image is used) is as follows:
* vendor_boot.img的结构(在版本 3 中引入,并且在使用 v3 引导映像时需要存在)如下所示:
* +---------------------+
* | vendor boot header | o pages
* +---------------------+
* | vendor ramdisk | p pages
* +---------------------+
* | dtb | q pages
* +---------------------+
* o = (2112 + page_size - 1) / page_size
* p = (vendor_ramdisk_size + page_size - 1) / page_size
* q = (dtb_size + page_size - 1) / page_size
*
* 0. all entities in the boot image are 4096-byte aligned in flash, all
* entities in the vendor boot image are page_size (determined by the vendor
* and specified in the vendor boot image header) aligned in flash
* 引导映像中的所有条目在闪存flash中都是 4096 字节对齐的,
* 供应商引导映像中的所有实体都是 page_size(由供应商确定并在供应商引导映像标头中指定)在闪存flash中对齐
* 1. kernel, ramdisk, vendor ramdisk, and DTB are required (size != 0)
* // 需要kernel、ramdisk、vendor ramdisk 和 DTB(大小!= 0)
* 2. load the kernel and DTB at the specified physical address (kernel_addr,
* dtb_addr) // 在指定的物理地址(kernel_addr,dtb_addr)加载内核和DTB
* 3. load the vendor ramdisk at ramdisk_addr //在 ramdisk_addr 加载供应商 ramdisk
* 4. load the generic ramdisk immediately following the vendor ramdisk in
* memory //在内存中的供应商 ramdisk 之后立即加载通用 ramdisk
* 5. set up registers for kernel entry as required by your architecture
* // 根据您的体系结构的要求为内核入口设置寄存器
* 6. if the platform has a second stage bootloader jump to it (must be
* contained outside boot and vendor boot partitions), otherwise
* jump to kernel_addr
* 如果平台有第二阶段引导加载程序跳转到它(必须包含在引导和供应商引导分区之外),
* 否则跳转到 kernel_addr
*/
struct boot_img_hdr_v3 {
// Must be BOOT_MAGIC.
uint8_t magic[BOOT_MAGIC_SIZE];
uint32_t kernel_size; /* size in bytes */
uint32_t ramdisk_size; /* size in bytes */
// Operating system version and security patch level.
// For version "A.B.C" and patch level "Y-M-D":
// (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M)
// os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0]
uint32_t os_version;
#if __cplusplus
void SetOsVersion(unsigned major, unsigned minor, unsigned patch) {
os_version &= ((1 << 11) - 1);
os_version |= (((major & 0x7f) << 25) | ((minor & 0x7f) << 18) | ((patch & 0x7f) << 11));
}
void SetOsPatchLevel(unsigned year, unsigned month) {
os_version &= ~((1 << 11) - 1);
os_version |= (((year - 2000) & 0x7f) << 4) | ((month & 0xf) << 0);
}
#endif
uint32_t header_size;
uint32_t reserved[4]; //预留4字节为了解析下面的header_version版本号时与上面0,1,2版本兼容
// Version of the boot image header.
uint32_t header_version;
// Asciiz kernel commandline.
uint8_t cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
} __attribute__((packed));
struct vendor_boot_img_hdr_v3 {
// Must be VENDOR_BOOT_MAGIC.
uint8_t magic[VENDOR_BOOT_MAGIC_SIZE]; //"VNDRBOOT"占8字节
// Version of the vendor boot image header.
uint32_t header_version;
uint32_t page_size; /* flash page size we assume */ 我们假设的flash页大小
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t vendor_ramdisk_size; /* size in bytes */
uint8_t cmdline[VENDOR_BOOT_ARGS_SIZE]; /* asciiz kernel commandline */
uint32_t tags_addr; /* physical addr for kernel tags (if required) */
uint8_t name[VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */
uint32_t header_size;
uint32_t dtb_size; /* size in bytes for DTB image */
uint64_t dtb_addr; /* physical load address for DTB image */
} __attribute__((packed));
/* When the boot image header has a version of 4, the structure of the boot
* image is as follows:
* 当引导映像头文件的版本为 4 时,引导映像的结构如下:
* +---------------------+
* | boot header | 4096 bytes
* +---------------------+
* | kernel | m pages
* +---------------------+
* | ramdisk | n pages
* +---------------------+
* | boot signature | g pages
* +---------------------+
*
* m = (kernel_size + 4096 - 1) / 4096
* n = (ramdisk_size + 4096 - 1) / 4096
* g = (signature_size + 4096 - 1) / 4096
*
* Note that in version 4 of the boot image header, page size is fixed at 4096
* bytes.
* 请注意,在版本 4 的引导映像标头中,页面大小固定为 4096 字节。
* The structure of the vendor boot image version 4, which is required to be
* present when a version 4 boot image is used, is as follows:
* 供应商引导映像版本 4 的结构,在使用版本 4 引导映像时需要存在,如下所示:
* +------------------------+
* | vendor boot header | o pages
* +------------------------+
* | vendor ramdisk section | p pages
* +------------------------+
* | dtb | q pages
* +------------------------+
* | vendor ramdisk table | r pages
* +------------------------+
* | bootconfig | s pages
* +------------------------+
*
* o = (2128 + page_size - 1) / page_size
* p = (vendor_ramdisk_size + page_size - 1) / page_size
* q = (dtb_size + page_size - 1) / page_size
* r = (vendor_ramdisk_table_size + page_size - 1) / page_size
* s = (vendor_bootconfig_size + page_size - 1) / page_size
*
* Note that in version 4 of the vendor boot image, multiple vendor ramdisks can
* be included in the vendor boot image. The bootloader can select a subset of
* ramdisks to load at runtime. To help the bootloader select the ramdisks, each
* ramdisk is tagged with a type tag and a set of hardware identifiers
* describing the board, soc or platform that this ramdisk is intended for.
*请注意,在供应商启动映像的版本 4 中,多个供应商 ramdisk 可以包含在供应商启动映像中。
*bootloader可以选择 ramdisks 的子集在运行时加载。 为了帮助bootloader选择 ramdisk,
*每个 ramdisk 都标有类型标签和一组硬件标识符,用于描述该 ramdisk 适用的board、soc 或platform。
*
* The vendor ramdisk section is consist of multiple ramdisk images concatenated
* one after another, and vendor_ramdisk_size is the size of the section, which
* is the total size of all the ramdisks included in the vendor boot image.
* ===vendor ramdisk section由多个ramdisk image依次拼接而成,vendor_ramdisk_size为该section的大小,
* 即vendor boot image中包含的所有ramdisk的总大小。
*
* The vendor ramdisk table holds the size, offset, type, name and hardware
* identifiers of each ramdisk. The type field denotes the type of its content.
* The vendor ramdisk names are unique. The hardware identifiers are specified
* in the board_id field in each table entry. The board_id field is consist of a
* vector of unsigned integer words, and the encoding scheme is defined by the
* hardware vendor.
* 供应商 ramdisk 表包含每个 ramdisk 的大小、偏移量、类型、名称和硬件标识符。
* 类型字段表示其内容的类型。供应商 ramdisk 名称是唯一的。
* 硬件标识符在每个表条目的 board_id 字段中指定。
* board_id 字段由无符号整数字向量组成,编码方案由硬件供应商定义。
*
* For the different type of ramdisks, there are: 对于不同类型的ramdisk,有:
* - VENDOR_RAMDISK_TYPE_NONE indicates the value is unspecified.
* - VENDOR_RAMDISK_TYPE_NONE 表示该值未指定。
* - VENDOR_RAMDISK_TYPE_PLATFORM ramdisks contain platform specific bits, so
* the bootloader should always load these into memory.
* - VENDOR_RAMDISK_TYPE_PLATFORM ramdisks 包含特定于平台的位,因此引导加载程序应始终将这些位加载到内存中。
* - VENDOR_RAMDISK_TYPE_RECOVERY ramdisks contain recovery resources, so
* the bootloader should load these when booting into recovery.
* - VENDOR_RAMDISK_TYPE_RECOVERY ramdisks 包含recovery资源,因此引导加载程序应在引导进入recovery时加载这些资源。
* - VENDOR_RAMDISK_TYPE_DLKM ramdisks contain dynamic loadable kernel
* modules.
* - VENDOR_RAMDISK_TYPE_DLKM ramdisks 包含动态可加载内核模块。
*
* Version 4 of the vendor boot image also adds a bootconfig section to the end
* of the image. This section contains Boot Configuration parameters known at
* build time. The bootloader is responsible for placing this section directly
* after the generic ramdisk, followed by the bootconfig trailer, before
* entering the kernel.
* 供应商引导映像的版本 4 还在映像末尾添加了一个 bootconfig 部分。
* 此部分包含构建时已知的引导配置参数。 在进入内核之前,引导加载程序负责将此部分直接放在通用 ramdisk 之后,然后是 bootconfig trailer。
*
* 0. all entities in the boot image are 4096-byte aligned in flash, all
* entities in the vendor boot image are page_size (determined by the vendor
* and specified in the vendor boot image header) aligned in flash
* 1. kernel, ramdisk, and DTB are required (size != 0)
* 2. load the kernel and DTB at the specified physical address (kernel_addr,
* dtb_addr)
* 3. load the vendor ramdisks at ramdisk_addr
* 4. load the generic ramdisk immediately following the vendor ramdisk in
* memory
* 5. load the bootconfig immediately following the generic ramdisk. Add
* additional bootconfig parameters followed by the bootconfig trailer.
* 在通用 ramdisk 之后立即加载 bootconfig。 添加其他 bootconfig 参数,后跟 bootconfig 尾部。
* 6. set up registers for kernel entry as required by your architecture
* 7. if the platform has a second stage bootloader jump to it (must be
* contained outside boot and vendor boot partitions), otherwise
* jump to kernel_addr
*/
struct boot_img_hdr_v4 : public boot_img_hdr_v3 {
uint32_t signature_size; /* size in bytes */
} __attribute__((packed));
struct vendor_boot_img_hdr_v4 : public vendor_boot_img_hdr_v3 {
uint32_t vendor_ramdisk_table_size; /* size in bytes for the vendor ramdisk table */
uint32_t vendor_ramdisk_table_entry_num; /* number of entries in the vendor ramdisk table */
uint32_t vendor_ramdisk_table_entry_size; /* size in bytes for a vendor ramdisk table entry */
uint32_t bootconfig_size; /* size in bytes for the bootconfig section */
} __attribute__((packed));
struct vendor_ramdisk_table_entry_v4 { //VENDOR_RAMDISK_TABLE_ENTRY_V4_SIZE = 108字节
uint32_t ramdisk_size; /* size in bytes for the ramdisk image */
uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */
uint32_t ramdisk_type; /* type of the ramdisk */
uint8_t ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */
// Hardware identifiers describing the board, soc or platform which this
// ramdisk is intended to be loaded on.=>硬件标识符描述了该 ramdisk 打算加载到的板、soc 或平台。
uint32_t board_id[VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE];
} __attribute__((packed));
boot镜像的制作:
system/tools/mkbootimg/mkbootimg.py
$ dd if=/dev/urandom of=./tmp/kernel bs=4096 count=1 # 创建一个4096字节的文件,内容随机
1+0 records in
1+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000140272 s, 29.2 MB/s
$ dd if=/dev/urandom of=./tmp/ramdisk bs=4096 count=1 # 创建一个4096字节的文件,内容随机
1+0 records in
1+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000145439 s, 28.2 MB/s
$ mkbootimg --header_version 4 \ #版本4的header的页大小为4096字节
--kernel ./tmp/kernel \
--ramdisk ./tmp/ramdisk \
--cmdline 'printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init kfence.sample_interval=500 loop.max_part=7 bootconfig' \
--os_version 11.0.0 \
--os_patch_level 2021-01 \
--gki_signing_algorithm SHA256_RSA2048 \ #以下三行是boot_signature的相关参数
--gki_signing_key ./data/testkey_rsa2048.pem \ #签名工具路径
--gki_signing_signature_args '--prop foo:bar --prop gki:nice' \
--output ./tmp/boot.img \
--gki_signing_avbtool_path avbtool #avbtool的签名工具路径
$ unpack_bootimg --boot_img ./tmp/boot.img --out ./tmp/out #解压boot.img
boot magic: ANDROID!
kernel_size: 4096
ramdisk size: 4096
os version: 11.0.0
os patch level: 2021-01
boot image header version: 4
command line args: printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init kfence.sample_interval=500 loop.max_part=7 bootconfig
boot.img signature size: 4096
$ avbtool info_image --image ./tmp/out/boot_signature #查看boot_signature的信息
Minimum libavb version: 1.0
Header Block: 256 bytes
Authentication Block: 320 bytes
Auxiliary Block: 832 bytes
Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d
Algorithm: SHA256_RSA2048
Rollback Index: 0
Flags: 0
Rollback Index Location: 0
Release String: 'avbtool 1.2.0'
Descriptors:
Hash descriptor:
Image Size: 12288 bytes
Hash Algorithm: sha256
Partition Name: boot
Salt: d00df00d
Digest: cf3755630856f23ab70e501900050feef30b633b3e82a9085a578617e344f9c7
Flags: 0
Prop: foo -> 'bar'
Prop: gki -> 'nice'
$ mkbootimg --header_version 4 \ # signature为空时构建
--kernel ./tmp/kernel \
--ramdisk ./tmp/ramdisk \
--cmdline 'printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init kfence.sample_interval=500 loop.max_part=7 bootconfig' \
--os_version 11.0.0 \
--os_patch_level 2021-01 \
--output ./tmp/boot.img
$ unpack_bootimg --boot_img ./tmp/boot.img --out ./tmp/out
boot magic: ANDROID!
kernel_size: 4096
ramdisk size: 4096
os version: 11.0.0
os patch level: 2021-01
boot image header version: 4
command line args: printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init kfence.sample_interval=500 loop.max_part=7 bootconfig
boot.img signature size: 0
$ ls -l tmp/out #解压只有没有boot_signature文件
total 8
-rw-r----- 1 wxy wxy 4096 Feb 18 18:55 kernel
-rw-r----- 1 wxy wxy 4096 Feb 18 18:55 ramdisk
vendor_boot镜像:
$ dd if=/dev/urandom of=./tmp/dtb bs=4096 count=1
1+0 records in
1+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.00010651 s, 38.5 MB/s
$ dd if=/dev/urandom of=./tmp/ramdisk1 bs=4096 count=1
1+0 records in
1+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000115653 s, 35.4 MB/s
$ dd if=/dev/urandom of=./tmp/ramdisk2 bs=8192 count=1
1+0 records in
1+0 records out
8192 bytes (8.2 kB, 8.0 KiB) copied, 0.000138211 s, 59.3 MB/s
$ dd if=/dev/urandom of=./tmp/bootconfig bs=4096 count=1
1+0 records in
1+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000110595 s, 37.0 MB/s
$ ls -l tmp/*
-rw-r----- 1 wxy wxy 4096 Feb 18 20:26 tmp/bootconfig
-rw-r----- 1 wxy wxy 4096 Feb 18 20:24 tmp/dtb
-rw-r----- 1 wxy wxy 4096 Feb 18 20:25 tmp/ramdisk1
-rw-r----- 1 wxy wxy 8192 Feb 18 20:25 tmp/ramdisk2
$ mkbootimg --header_version 4 \
> --vendor_boot ./tmp/vendor_boot.img \
> --dtb ./tmp/dtb \
> --vendor_ramdisk ./tmp/ramdisk1 \
> --ramdisk_type 'PLATFORM' \
> --ramdisk_name 'RAMDISK1' \
> --vendor_ramdisk_fragment ./tmp/ramdisk1 \
> --ramdisk_type 'DLKM' \
> --ramdisk_name 'RAMDISK2' \
> --board_id0 '0xC0FFEE' \
> --board_id15 '0x15151515' \
> --vendor_ramdisk_fragment ./tmp/ramdisk2 \
> --vendor_cmdline 'printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init kfence.sample_interval=500 loop.max_part=7 bootconfig' \
> --vendor_bootconfig ./tmp/bootconfig
或者
$ mkbootimg --header_version 4 --vendor_boot ./tmp/vendor_boot.img --dtb ./tmp/dtb --vendor_ramdisk ./tmp/ramdisk1 --ramdisk_type 'PLATFORM' --ramdisk_name 'RAMDISK1' --vendor_ramdisk_fragment ./tmp/ramdisk1 --ramdisk_type 'DLKM' --ramdisk_name 'RAMDISK2' --board_id0 '0xC0FFEE' --board_id15 '0x15151515' --vendor_ramdisk_fragment ./tmp/ramdisk2 --vendor_cmdline 'printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init kfence.sample_interval=500 loop.max_part=7 bootconfig' --vendor_bootconfig ./tmp/bootconfig
$ ls -l tmp/*
-rw-r----- 1 wxy wxy 4096 Feb 18 20:26 tmp/bootconfig
-rw-r----- 1 wxy wxy 4096 Feb 18 20:24 tmp/dtb
-rw-r----- 1 wxy wxy 4096 Feb 18 20:25 tmp/ramdisk1
-rw-r----- 1 wxy wxy 8192 Feb 18 20:25 tmp/ramdisk2
-rw-r----- 1 wxy wxy 30720 Feb 18 20:32 tmp/vendor_boot.img #生成的vendor_boot.img镜像
$ unpack_bootimg --boot_img ./tmp/vendor_boot.img --out ./tmp/out
boot magic: VNDRBOOT
vendor boot image header version: 4
page size: 0x00000800
kernel load address: 0x10008000
ramdisk load address: 0x11000000
vendor ramdisk total size: 16384
vendor command line args: printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init kfence.sample_interval=500 loop.max_part=7 bootconfig
kernel tags load address: 0x10000100
product name:
vendor boot image header size: 2128
dtb size: 4096
dtb address: 0x0000000011f00000
vendor ramdisk table size: 324
vendor ramdisk table: [
vendor_ramdisk00: { #--vendor_ramdisk ./tmp/ramdisk1对应的默认的第一组
size: 4096
offset: 0
type: 0x1 #第一组默认为VENDOR_RAMDISK_TYPE_PLATFORM
name: #第一组默认为''
board_id: [ #第一组默认为None,即全零
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
]
}
vendor_ramdisk01: { #--ramdisk_type 'PLATFORM' --ramdisk_name 'RAMDISK1' --vendor_ramdisk_fragment ./tmp/ramdisk1 指定的第二组
size: 4096
offset: 4096
type: 0x1
name: RAMDISK1
board_id: [
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
]
}
vendor_ramdisk02: { #--ramdisk_type 'DLKM' --ramdisk_name 'RAMDISK2' --board_id0 '0xC0FFEE' --board_id15 '0x15151515' --vendor_ramdisk_fragment ./tmp/ramdisk2 指定的第三组
size: 8192
offset: 8192
type: 0x3
name: RAMDISK2
board_id: [
0x00c0ffee, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x15151515,
]
}
]
vendor bootconfig size: 4096
$ ls -l ./tmp/out/ #解压之后的东西
total 44
-rw-r----- 1 wxy wxy 4096 Feb 18 20:35 bootconfig
-rw-r----- 1 wxy wxy 4096 Feb 18 20:35 dtb
-rw-r----- 1 wxy wxy 16384 Feb 18 20:35 vendor_ramdisk
-rw-r----- 1 wxy wxy 4096 Feb 18 20:35 vendor_ramdisk00
-rw-r----- 1 wxy wxy 4096 Feb 18 20:35 vendor_ramdisk01
-rw-r----- 1 wxy wxy 8192 Feb 18 20:35 vendor_ramdisk02
drwxr-x--- 2 wxy wxy 4096 Feb 18 20:35 vendor-ramdisk-by-name
$ tree ./tmp/out/
./tmp/out/
├── bootconfig
├── dtb
├── vendor_ramdisk
├── vendor_ramdisk00
├── vendor_ramdisk01
├── vendor_ramdisk02
└── vendor-ramdisk-by-name
├── ramdisk_ -> ../vendor_ramdisk00
├── ramdisk_RAMDISK1 -> ../vendor_ramdisk01
└── ramdisk_RAMDISK2 -> ../vendor_ramdisk02
1 directory, 9 files
$ unpack_bootimg --boot_img ./tmp/vendor_boot.img \
> --out ./tmp/out \
> --format=mkbootimg
--header_version 4 --pagesize 0x00000800 --base 0x00000000 --kernel_offset 0x10008000 --ramdisk_offset 0x11000000 --tags_offset 0x10000100 --dtb_offset 0x0000000011f00000 --vendor_cmdline 'printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init kfence.sample_interval=500 loop.max_part=7 bootconfig' --board '' --dtb ./tmp/out/dtb --vendor_bootconfig ./tmp/out/bootconfig --ramdisk_type 1 --ramdisk_name '' --vendor_ramdisk_fragment ./tmp/out/vendor_ramdisk00 --ramdisk_type 1 --ramdisk_name RAMDISK1 --vendor_ramdisk_fragment ./tmp/out/vendor_ramdisk01 --ramdisk_type 3 --ramdisk_name RAMDISK2 --board_id0 0x00c0ffee --board_id15 0x15151515 --vendor_ramdisk_fragment ./tmp/out/vendor_ramdisk02
wxy@siashcsitd04211:~/jieya/system-tools-mkbootimg/tests$ ls -l ./tmp/out/*
-rw-r----- 1 wxy wxy 4096 Feb 18 21:42 ./tmp/out/bootconfig
-rw-r----- 1 wxy wxy 4096 Feb 18 21:42 ./tmp/out/dtb
-rw-r----- 1 wxy wxy 16384 Feb 18 21:42 ./tmp/out/vendor_ramdisk
-rw-r----- 1 wxy wxy 4096 Feb 18 21:42 ./tmp/out/vendor_ramdisk00
-rw-r----- 1 wxy wxy 4096 Feb 18 21:42 ./tmp/out/vendor_ramdisk01
-rw-r----- 1 wxy wxy 8192 Feb 18 21:42 ./tmp/out/vendor_ramdisk02
./tmp/out/vendor-ramdisk-by-name:
total 0
lrwxrwxrwx 1 wxy wxy 19 Feb 18 21:42 ramdisk_ -> ../vendor_ramdisk00
lrwxrwxrwx 1 wxy wxy 19 Feb 18 21:42 ramdisk_RAMDISK1 -> ../vendor_ramdisk01
lrwxrwxrwx 1 wxy wxy 19 Feb 18 21:42 ramdisk_RAMDISK2 -> ../vendor_ramdisk02
boot镜像重新打包:
system/tools/mkbootimg/repack_bootimg.py
boot镜像解压:
system/tools/mkbootimg/unpack_bootimg.py