RK3568 开发笔记整理之 FIT Image

RK3568 开发笔记整理之 FIT Image Asura 2024-03-18 14:27:20 2729

概述

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 文件:

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
Asura
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
Asura
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区