在新的内核中,可以发现在RK平台上出现了打包成fit格式的内核镜像。在盛博的项目中,我们内核提供了标准的安卓打包方式,但是客户SDK通过fit打包,导致我们支持overlayfs的ramdisk.img无法正常打包。其主要原因是fit打包的内核没有把ramdisk打包进来。再者,内核boot更换了打包方式,居然无需修改uboot启动方式即可正常启动,于是抱着一定的兴趣追了一下代码,再参考了一下官方文档,了解了fit镜像的制作,引导过程。这里分享出来
在说fit image之前,有必要简单带过一下传统的uboot image引导。通常我们知道uboot 的引导过程是需要知道三个条件的
kernel addr fdt addr ramdisk addr(非必须)
然后再根据booti/bootm启动内核。
所以一般调试linux系统的第一步,就是想方设法将内核,设备树,initrd加载到内存地址上,然后通过bootm A B C 的方式直接加载内存地址,或者通过booti 加载uimage的方式。
这些动作通常要么是uboot内指定写死,要么是手动uboot写好,然后通过saveenv的命令保存来确保下次正常启动。
但是发现了没有,这种方式它不灵活,如果我更换内核,设备树,initrd的话,只能通过同名的文件替换来实现。加载步骤是不能变化的。
如果有一个新的启动方式,它能在嵌入式设备中灵活的选择任意的内核,设备树,initrd是不是更好。
结合上面的需求,uboot开发了新的image格式方式加载(uImage.FIT is the new format used for uImage payloads developed by U-boot.)。
CONFIG_FIT=y CONFIG_CMD_BOOT_FIT=y
上面打开uboot支持fit启动,下一个打开boot_fit命令,实际上如果boot_fit命令不打开也可以手动bootm启动。
对应在bootcmd中,需要添加boot_fit命令,可以安排启动顺序如下:
bootcmd=boot_android ${devtype} ${devnum};boot_fit;bootrkp;run distro_bootcmd;
这样机器默认先找安卓打包方式的内核,再找fit方式的内核。也就解释了为什么内核更换打包方式无需做修改就能直接启动了
its文件即描述多个镜像启动的配置文件,其语法本质就是设备树fdt,所以直接按照设备树语法编写即可
RK平台默认的its文件如下
/* * Copyright (C) 2021 Rockchip Electronics Co., Ltd * * SPDX-License-Identifier: GPL-2.0 */ /dts-v1/; / { description = "FIT image with Linux kernel, FDT blob and resource"; images { fdt { data = /incbin/("fdt"); type = "flat_dt"; arch = ""; compression = "none"; load = <0xffffff00>; hash { algo = "sha256"; }; }; kernel { data = /incbin/("kernel"); type = "kernel"; arch = ""; os = "linux"; compression = ""; entry = <0xffffff01>; load = <0xffffff01>; hash { algo = "sha256"; }; }; resource { data = /incbin/("resource"); type = "multi"; arch = ""; compression = "none"; hash { algo = "sha256"; }; }; ramdisk { description = "Compressed Initramfs"; data = /incbin/("ramdisk"); type = "ramdisk"; arch = "arm64"; os = "linux"; compression = "none"; load = <0x00000000>; entry = <0x00000000>; hash { algo = "sha256"; }; }; }; configurations { default = "conf"; conf { rollback-index = <0x00>; fdt = "fdt"; kernel = "kernel"; multi = "resource"; ramdisk = "ramdisk"; signature { algo = "sha256,rsa2048"; padding = "pss"; key-name-hint = "dev"; sign-images = "fdt", "kernel", "multi"; }; }; }; };
可以留意到的是,这个文件就两个node,一个是images,一个是configurations
其实通过英文就能大概猜到了。images描述了镜像(多个),configurations描述了配置(多个),那么就意味着可以针对多个镜像来搭配出多个配置,每种配置均可通过uboot的boot_fit启动。
下面支持ramdisk打包的its修改方法。这里load和entry填写0是因为uboot会根据实际地址ramdisk_addr_r来复写。所以没有关系
kernel# git diff HEAD boot.its diff --git a/boot.its b/boot.its index 755005c..885bfd1 100644 --- a/boot.its +++ b/boot.its @@ -45,6 +45,21 @@ algo = "sha256"; }; }; + + ramdisk { + description = "Compressed Initramfs"; + data = /incbin/("ramdisk"); + type = "ramdisk"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x00000000>; + entry = <0x00000000>; + + hash { + algo = "sha256"; + }; + }; }; configurations { @@ -55,6 +70,7 @@ fdt = "fdt"; kernel = "kernel"; multi = "resource"; + ramdisk = "ramdisk"; signature { algo = "sha256,rsa2048";
mkimage -E -p 0x800 -f out/boot.its boot.img
通过如上命令即可将its打包到boot镜像内,这样在uboot的boot_fit命令就可以直接找到boot.img内的boot.itb文件
./mkimage -l boot.img FIT description: FIT image with Linux kernel, FDT blob and resource Created: Thu Nov 2 18:41:56 2023 Image 0 (fdt) Description: unavailable Created: Thu Nov 2 18:41:56 2023 Type: Flat Device Tree Compression: uncompressed Data Size: 151491 Bytes = 147.94 KiB = 0.14 MiB Architecture: AArch64 Load Address: 0xffffff00 Hash algo: sha256 Hash value: cedd1011209678d3b1acbe79ecb93c869f716df3e43049722c5c83b4382bab41 Image 1 (kernel) Description: unavailable Created: Thu Nov 2 18:41:56 2023 Type: Kernel Image Compression: lz4 compressed Data Size: 18758725 Bytes = 18319.07 KiB = 17.89 MiB Architecture: AArch64 OS: Linux Load Address: 0xffffff01 Entry Point: 0xffffff01 Hash algo: sha256 Hash value: e363a997ae83daeb70c130c30b32c1b00655a515d2a5b96ea251884c00655d9c Image 2 (resource) Description: unavailable Created: Thu Nov 2 18:41:56 2023 Type: Multi-File Image Compression: uncompressed Data Size: 793600 Bytes = 775.00 KiB = 0.76 MiB Hash algo: sha256 Hash value: bfb3aaf4cf63f736406e5e3cf54a0924056cf1e16d35eceb1f7ce041777f12b6 Image 3 (ramdisk) Description: Compressed Initramfs Created: Thu Nov 2 18:41:56 2023 Type: RAMDisk Image Compression: uncompressed Data Size: 5188818 Bytes = 5067.21 KiB = 4.95 MiB Architecture: AArch64 OS: Linux Load Address: 0x00000000 Entry Point: 0x00000000 Hash algo: sha256 Hash value: 4cfac4cf0b7fdee76a2b3ef847cedaacdd1ab28b290faff9164fbbef051b6d57 Default Configuration: 'conf' Configuration 0 (conf) Description: unavailable Kernel: kernel Init Ramdisk: ramdisk FDT: fdt
这里可以看到,boot.img内正常包含所以需要its启动的文件和itb文件
如果its想要验证,可在uboot中直接引导,如下方式, 前置条件是需要提前将boot.its描述的文件加载到内存。否则找不到文件的
tftp 0X10000000 boot.its bootm 0X10000000
这里展示fit格式的镜像启动日志,如下
=> boot_fit ## Booting FIT Image at 0xea3eff40 with size 0x01209600 ## Loading kernel from FIT Image at ea3eff40 ... Using 'conf' configuration optee api revision: 2.0 TEEC: Waring: Could not find security partition ## Verified-boot: 0 Trying 'kernel' kernel subimage Description: unavailable Type: Kernel Image Compression: lz4 compressed Data Start: 0xea415740 Data Size: 18758725 Bytes = 17.9 MiB Architecture: AArch64 OS: Linux Load Address: 0x00400000 Entry Point: 0x00400000 Hash algo: sha256 Hash value: e363a997ae83daeb70c130c30b32c1b00655a515d2a5b96ea251884c00655d9c Verifying Hash Integrity ... sha256+ OK ## Loading fdt from FIT Image at ea3eff40 ... Using 'conf' configuration Trying 'fdt' fdt subimage Description: unavailable Type: Flat Device Tree Compression: uncompressed Data Start: 0xea3f0740 Data Size: 151448 Bytes = 147.9 KiB Architecture: AArch64 Load Address: 0x08300000 Hash algo: sha256 Hash value: c49109c3ca4ebe1d68c2da345e1737e92adc5ff0bfc05ab2c20a2184a927b600 Verifying Hash Integrity ... sha256+ OK Loading fdt from 0x08300000 to 0x08300000 Booting using the fdt blob at 0x08300000 Uncompressing LZ4 Kernel Image from 0xea415740 to 0x00400000 ... with 029cea00 bytes OK kernel loaded at 0x00400000, end = 0x02dcea00 Using Device Tree in place at 0000000008300000, end 0000000008327f97 WARNING: could not set reg FDT_ERR_BADOFFSET. ## reserved-memory: drm-logo@00000000: addr=edf00000 size=136000 ramoops@110000: addr=110000 size=f0000 Adding bank: 0x00200000 - 0x08400000 (size: 0x08200000) Adding bank: 0x09400000 - 0xf0000000 (size: 0xe6c00000) Adding bank: 0x1f0000000 - 0x200000000 (size: 0x10000000) Total: 382304.976/382374.272 ms Starting kernel ...
这里默认加载了名字为conf的配置,也就加载了conf配置中指定的文件,至此fit image正常启动。
为何启动fit image如此轻松,主要原因是fit image已经合入主线,linux和uboot都默认支持fit。下面是参考文档