RK3568 开发笔记整理之 FIT Image
概述
RK 平台的 U-Boot 固件有两种格式,RK 格式和 FIT 格式,RK 格式固件和 FIT 格式固件分别由闭源SPL 和开源 SPL 负责引导。不过对于我们的 RK3568,我们使用 FIT 格式。
- RK 格式
Rockchip自定义的固件格式,U-Boot和trust分别打包为uboot.img和trust.img。如下:uboot.img 和32位 trust.img 镜像文件的magic为“LOADER”
64位 trust.img 镜像文件的magic为“BL3X’
- FIT 格式
U-Boot mainline支持的一种灵活性极高的固件格式。U-Boot、trust以及mcu等固件一起打包为uboot.img。
uboot.img的镜像文件的magic 为”d0 0d fe ed”,用命令 fdtdump uboot.img 可以查看固件头。
trust 镜像就是 ARM Trusted Firmware + OP-TEE OS 镜像,对于 RK 平台来说就是 BL31、BL32。
FIT 镜像是 U-Boot 支持的一种新固件类型的引导镜像格式,支持任意多个 image 打包和校验。FIT 镜像的制作需要使用 mkimage 工具,该工具在 u-boot 源码目录下的 tools 目录中,不过由于 U-Boot 官方原本的 FIT 功能无法满足实际产品需要,所以 RK 平台对 FIT 功能进行了适配和优化,所以自然对 mkimage 工具的源代码进行了修改、优化;所以对于 RK 平台硬件,如果使用 FIT 格式镜像,必须使用 RK U-boot 源码编译生辰的 mkimage 工具,不可使用 U-boot 原版的 mkimage 工具。
FIT 固件会使用 its(image source file)文件描述 image 信息,最后通过 mkimage 工具生成 itb(flattened image tree blob)镜像。its 文件使用 DTS(设备树)的语法规则,非常灵活,可以直接使用 libfdt 库和相关工具。描述文件为 u-boot.its,最终生成的 FIT 固件为 uboot.itb,这个 itb 文件其实就是我们的 uboot.img。
当我们编译 u-boot 源码之后,会在 u-boot 源码目录下生成一个 fit 目录,该目录下包含 u-boot.its 文件以及编译得到的 uboot.itb 文件。
如下以u-boot.its和u-boot.itb作为范例进行介绍。
/images
:静态定义了所有的资源,相当于一个 dtsi文件;/configurations
:每个 config 节点都描述了一套可启动的配置,相当于一个板级dts文件。defau1t
=:指明默认启用的config;
/dts-v1/;
/ {
description = "FIT Image with ATF/OP-TEE/U-Boot";
#address-cells = <1>;
images {
uboot {
description = "U-Boot(64-bit)";
data = /incbin/("./u-boot-nodtb.bin");
type = "standalone";
arch = "arm64";
os = "U-Boot";
compression = "none";
load = <0x00a00000>;
hash {
algo = "sha256";
};
};
atf-1 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0x00040000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0x00040000>;
hash {
algo = "sha256";
};
};
atf-2 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0xfdcc9000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0xfdcc9000>;
hash {
algo = "sha256";
};
};
atf-3 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0xfdcd0000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0xfdcd0000>;
hash {
algo = "sha256";
};
};
optee {
description = "OP-TEE";
data = /incbin/("./tee.bin");
type = "firmware";
arch = "arm64";
os = "op-tee";
compression = "none";
load = <0x8400000>;
hash {
algo = "sha256";
};
};
fdt {
description = "U-Boot dtb";
data = /incbin/("./u-boot.dtb");
type = "flat_dt";
arch = "arm64";
compression = "none";
hash {
algo = "sha256";
};
};
};
//configurations 节点下可以定义任意多个不同的 conf 节点,但实际产品方案上我们只需要一个 conf
即可。
configurations {
default = "conf";
conf {
description = "rk3568-evb";
rollback-index = <0x0>;
firmware = "atf-1";
loadables = "uboot", "atf-2", "atf-3", "optee";
fdt = "fdt";
signature {
algo = "sha256,rsa2048";
key-name-hint = "dev";
sign-images = "fdt", "firmware", "loadables";
};
};
};
};
首先需要说明的是,its 文件的语法和设备树文件 dts 是一样的,这点不用怀疑。只是说 its 文件中的这些属性具体是什么等等这些,我们需要了解下,关于 its 文件在 u-boot 源码目录下的 doc 目录中提供了相应的帮助文档:
doc/uImage.FIT/
/images 节点描述定义了所有镜像资源,对这些镜像资源进行描述,相当于一个 dtsi 文件,该节点下定义的镜像并不一定会加入到最终生成的 itb 镜像中。
/configurations:该节点下可 conf 节点,每个 conf 节点都描述了一套可用于启动的配置,相当于一个板级的 dts 文件。
关于这些属性的介绍可以参考 doc/uImage.FIT/source_file_format.txt 文档。
根节点的布局:
/images 节点的布局:
type 属性:镜像的类型,支持的类型有:
data 属性:二进制数据(镜像文件)的路径;
compression 属性:镜像数据的压缩类型,支持的压缩是“gzip”和“bzip2”。如果不使用压缩,则压缩属性应设置为“none”。
以上三个是必填属性:type、data、compression。
接下来这些为<有条件的强制性属性>:
os 属性:OS name,type 等于”kernel”和”ramdisk”时必须填写,包括:
arch 属性:架构名字,type 等于”standalone”, “kernel”,”firmware”, “ramdisk” and “fdt”时必须填写,支持:
entry 属性:入口点地址。
load 属性:加载地址,其实加载地址就是入口地址,这俩的含义是一样的我觉得,RK 平台使用 its 文件中并没有使用 entry 属性,而是用了 load 属性。
“/images”节点下有一个可选的子节点,hash 节点,hash 节点用于做 hash 值校验,他通常有两个属性algo、value,
algo 属性:hash 校验算法的名称,supported are “crc32”, “md5” and “sha1”。
value 属性:实际校验和或哈希值,对应长度为 4、16 或 20 个字节,编译过程中构建该属性。
- ‘/configurations’节点的布局
“/configurations”节点下有一个 default 属性,表示当前那个配置(某个 config 节点)生效。来看看 config 节点的布局:
需要说明的是,还有一些属性会在 its 编译过程中自动创建出来,因为这些属性与加载地址、镜像大小等有关系,譬如 data-offset、data-size、data-position 等这些,以及一些满足 RK 平台需要的属性(RK 修改的,这些属性不是原本 mkimage 工具所支持的)。
itb 文件
使用 mkimage 工具和 its 文件可以生成 itb 文件:
fdtdump 命令可以查看 itb 文件内容,可以看到fdtdump fit/uboot.itb
这里面有些属性就是编译之后才会有的,编译的时候创建的属性,譬如 data-size、data-offset、data-position等等,这些属性后面再说。
itb 本质是 fdt_blob(its 设备树镜像) + images 的文件集合,有如下两种打包方式,RK 平台方案采用结构 2 方式。
使用 mkimage 工具时,默认使用的是第一种结构生成 itb,可通过-E 选项,指定为第二种结构来生成itb。
对于结构 2,u-boot 以及 FIT 文档中也称为“External data”,外部数据,也就是说镜像没有嵌入到 fdt_blob,而是在外部。这个时候通常会使用 data-offset 或者 data-position 属性来找到该镜像的位置,data-size 表示镜像数据的大小。
那么 data-offset 和 data-position,一个表示相对位置,一个表示绝对位置。不过 data-position 的优先级会更高。默认情况下使用的是 data-offset 属性,不过我们可以使用-p 选项指定为使用绝对位置 data-position,使用-p 选项时,后面可以携带一个参数,这个参数指定了一个起始位置,所有的“External data”镜像将从这个位置开始放置。
data-offset:相对位置,这个是镜像相对于 fdt_blob 末尾的位置偏移量,所以相对整个 itb 文件的位置偏移量需要加上 fdt_blob 的大小。
data-position:绝对位置,镜像在 itb 文件中的绝对位置(其实就是相对于 itb 文件头部的位置)。
u-boot 在解析 itb(uboot.img 镜像的时候,不过 uboot.img 通过由 SPL 加载解析),会找到镜像对应的节点,也就是”/images”节点下定义的某个镜像的节点,再找到它的这些属性,根据这些属性找到它的位置。
在解析 fdt_blob 之前,SPL 会将 fdt_blob 拷贝到内存中,这个在 SPL 启动流程中分析过,然后在解析,找到位置之后再从存储设备中读取。
如果结构 1 这种内嵌的情况,通过会通过 data 属性来找到,找到了 data 属性就找到镜像的位置,因为结构 2 是内嵌的情况,镜像已经嵌入到了 fdt_blob 中,所以拷贝 fdt_blob 的时候就已经将这些镜像都拷贝到内存中了。但如果没有 data 属性,则还会通过 data-size、data-offset、或 data-position 这些属性定位,具体看SPL 代码分析过程。
再次说明,itb 文件就是我们编译的到的 uboot.img 文件。
itb 制作过程
编译完 u-boot 源码之后,会生成很多的.bin 文件:
可以看到有 bl31_0xxxxx.bin、bl31.elf、tee.bin 等这些镜像文件。
首先这个 bl31.elf 文件就是 rbbin/bin/rk35/目录下的 rk3568_bl31_v1.27.elf 文件,直接拷贝过来的,tee.bin文件就是rbbin/bin/rk35/目录下 rk3568_bl32_v1.05.bin 文件,也是直接拷贝过来的。
而 bl31_0x00040000.bin、bl31_0xfdcc9000.bin、bl31_0xfdcd0000.bin 这几个文件其实只是由 bl31.elf 分解而成的,在制作 itb 文件的时候,会对 bl31.elf 文件进行分解,而实际上制作 itb 文件时,也是使用了这 3个分解后的文件和 tee.bin 文件,在 its 文件中有写到,如下:
atf1: data = /incbin/(“./bl31_0x00040000.bin”);
atf2: data = /incbin/(“./bl31_0xfdcc9000.bin”);
atf3: data = /incbin/(“./bl31_0xfdcd0000.bin”);
optee: data = /incbin/(“./tee.bin”);
这三个文件通过 arch/arm/mach-rockchip/decode_bl31.py 脚本生成。
后面的数字表示它对应的加载地址,也就可以知道,这个 bl31 分成了 3 个部分,这 3 个部分对应的加载地址是不同的,SPL 会引导bl31_0x00040000.bin 启动,后续的就由它去处理了,最终会启动 u-boot 镜像。
我们说过,uboot.img 其实就包括了 u-boot 镜像(BL33)、ARM Trusted Firmware(BL31)、OP-TEEOS(BL32),我们来看看 itb 文件的制作过程:
分析 make.sh 脚本文件:
make.sh 脚本中会调用 pack_images 函数进行打包:
接着调用 pack_fit_image 函数:
然后调用 ${SCRIPT_FIT} ${ARG_LIST_FIT} —chip ${RKCHIP_LABEL}${SCRIPT_FIT}就是./scripts/fit.sh 脚本文件:
依次调用 fit_gen_uboot_itb、fit_gen_uboot_img、fit_gen_loader 这三个函数,在 fit_gen_uboot_itb 函数会其生成 itb 文件,如下所示:
./make.sh itb ${ARG_INI_TRUST} 用于产生 u-boot.its 文件。
${MKIMAGE} -f ${ITS_UBOOT} -E -p ${OFFS_DATA} ${ITB_UBOOT} -v ${ARG_VER_UBOOT} 用于生成 uboot.itb 文件。
然后在 fit_gen_uboot_img 函数中生成 uboot.img 镜像文件,其实就是对 uboot.itb 文件的拷贝,可能有多份 itb 文件:
- 分享
- 举报
-
浏览量:872次2024-03-12 16:42:47
-
浏览量:1698次2024-03-13 15:15:04
-
浏览量:2347次2024-03-18 15:00:34
-
浏览量:1162次2024-02-18 17:07:58
-
浏览量:4944次2022-09-30 16:40:59
-
浏览量:5848次2021-12-10 15:40:21
-
浏览量:9436次2022-10-12 09:28:15
-
浏览量:18180次2022-09-30 16:51:48
-
浏览量:1045次2023-12-08 16:48:29
-
浏览量:2645次2022-09-30 16:48:25
-
浏览量:4081次2022-10-11 10:48:08
-
浏览量:6598次2022-10-08 14:00:42
-
浏览量:5070次2022-09-26 11:51:17
-
浏览量:6600次2022-10-09 10:20:09
-
浏览量:7933次2022-10-13 19:26:04
-
浏览量:2537次2022-09-30 16:46:03
-
浏览量:6002次2022-10-08 13:56:28
-
浏览量:10296次2022-10-09 15:56:41
-
浏览量:2761次2022-10-28 09:28:29
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
Asura
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明