前言
这篇文章主要讨论,在Anykernel中放入一个Image.xx-dtb
和放入Image.xx
+dtb
两个文件的区别
我曾经在这里提到过,msm-4.19平台上
- 并不能继续使用类似
Image.gz-dtb
的镜像放入Anykernel zip进行刷入,这样刷入了系统并不会认(就和dtb没修改一样)
- 内核的默认config不再开启生成Image.xx-dtb的
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE
- 裸Image刷入是可以开机的(比如Anykernel中单单放入一个
Image.gz
而没有任何dtb文件)
- 想要正常替换dtb,需要将对应的dtb重命名为“dtb”并放入Anykernel的根目录(比如将
kona-v2.1.dtb
重命名为dtb
并放入Anykernel根目录)
但是,后来有人提醒我说一加7系列上也有这种情况?于是我把它划掉了,并认为是一加的某些魔改
最近瞧了瞧这个东西,并确定了造成这个变化的根本原因在于Android Boot Image规范的变化
揭秘
看不懂的文档
在谷歌的文档中,有这样一段话
Including the DTB image in the boot image
Devices running Android 10 can include the DTB image in the boot image. This removes the need for Android to support scripts that append the DTB image to image.gz in the kernel, and enables the use of Vendor Test Suite (VTS) test to verify (and standardize) DTB placement.
也就是说,搭载安卓10的设备可以把dtb镜像放在boot镜像里,并且因此可以不再支持把dtb连接在Image.gz镜像后面的这种格式
问题是,这段话说了个鬼?dtb不原来就在boot镜像里?它到底改变了什么?
我们可以继续找线索
Boot Image Header 的更新
谷歌有提到
Android 9 introduced a version field in the boot image header, enabling updates to the header while maintaining backward compatibility. The bootloader must check the header version field and parse the header accordingly. Devices launching with:
Android 11 can use boot header version 3. For devices supporting Generic Kernel Image (GKI) architecture, this version must be used for the primary boot image.
Android 10 must use boot header version 2.
Android 9 must use boot header version 1.
Android 8 and lower are considered as using a boot image header version 0.
也就是说,安卓10引入了一个新的boot header v2,所有安卓10出厂的设备都必须支持,msm-4.19平台正是出厂安卓10,也许改变就在这里
Header v2 变了啥?
相比于header v1
struct boot_img_hdr
{
uint8_t magic[BOOT_MAGIC_SIZE];
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 */
uint32_t page_size; /* flash page size we assume */
uint32_t header_version;
uint32_t os_version;
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
uint8_t cmdline[BOOT_ARGS_SIZE];
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
uint32_t recovery_[dtbo|acpio]_size; /* size of recovery image */
uint64_t recovery_[dtbo|acpio]_offset; /* offset in boot image */
uint32_t header_size; /* size of boot image header in bytes */
+ uint32_t dtb_size; /* size of dtb image */
+ uint64_t dtb_addr; /* physical load address */
};
可以看到,header中多出了两行,分别存储dtb尺寸和加载地址的信息
但是Header仅仅只是boot镜像的头部位置,还得看看boot image整体发生了什么变化
Boot Image 结构
我们可以在aosp源码中找到相关信息
这是v1的
/* 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
这是v2的
/* 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
可以看到,v2的镜像相比于v1多出了一个存储dtb的位置,与header中的更改吻合
那么问题来了,在v1镜像中,dtb放在哪里?
答案是kernel里。没错,dtb和kernel共享一块区域,其中dtb连接在kernel后面——也就是Image.xx-dtb文件
总结
msm-4.19平台确实与之前有些许不同,而造成这个不同的原因在于谷歌修改了出厂安卓10的Boot镜像格式要求
制作Anykernel zip时需要注意的内容如前言所说
至于前言里一加7系列也可以用上这种boot镜像格式的原因,大概是因为bootloader支持?于是即使没有出厂安卓10,官方也开启了这个特性?
Boot Header v2应使用独立的dtb文件,低版本Boot Header应使用Image.xx-dtb的连接文件