U-Boot的FIT镜像格式比老方法好用多了~"

admin 2026-10-20 13:19:07 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

U-Boot 的 FIT 镜像格式比老方法好用多了~

内存泄漏

2026年6月26日 07:40
辽宁

在小说阅读器读本章

去阅读

以下文章来源于嵌入式情报局
,作者情报小哥

嵌入式情报局
.

集单片机与linux于一身的技术号~

目录

  • FIT 是什么、为什么需要它
  • 传统 uImage 的痛点
  • FIT 的文件结构:.its 和 .itb
  • 动手写一个 FIT 镜像
  • FIT 镜像的结构图解
  • 配置(configuration):一套组合拳
  • 完整性校验:Hash 守护数据安全
  • 压缩支持:给镜像瘦身
  • 签名验证:安全启动的基石
  • 总结

大家好,我是情报小哥~

前段时间,一个小伙伴在群里问:

小哥,我们项目要从老版本 U-Boot 切到新版本,发现原来的 uImage 启动方式要改成 FIT 格式了,这 FIT 到底是个啥玩意?为啥要搞这么复杂?

FIT 这几年在嵌入式 Linux 圈子里越来越常见,但很多人只是照着教程敲命令,并没有真正理解它做了什么.今天,我们就聊清楚了~

FIT 是什么

FIT,全称叫 Flattened Image Tree。

翻译过来就是\"扁平化镜像树\"。

传统的 uImage 就是这样:内核镜像打一个包,设备树是另一个文件,根文件系统又是一个文件,initramfs 还要单独管理。

更别提有些项目还有 FPGA 比特流、M4 协处理器固件、安全 OS 镜像……

FIT 做的事情很简单:它把所有这些二进制文件,按照一个统一的格式打包在一起,并且附上了描述信息、校验信息、加载地址等元数据。

每个成员都在自己该在的位置,并且身上贴好了标签。

传统 uImage 的痛点

先回顾一下老式的 uImage 是怎么用的。

用 mkimage 给内核镜像包个头:

mkimage -A arm -O linux -T kernel -C none -a 0x80008000 -e 0x80008000 \\
        -n \"Linux Kernel\" -d zImage uImage

然后启动的时候:

bootm 0x10000000

看起来很简单对吧?

但是问题来了:

第一,信息全挤在一个 64 字节的头部里。

镜像类型、加载地址、入口地址、压缩方式、名字……全部塞进去。

想加个校验?没地方了。

想放两个设备树?想都别想。

第二,多个组件要分开管理。

内核放一个分区,设备树放一个分区,根文件系统放一个分区。

生产烧录的时候,每个分区都得单独处理,烧错一个就起不来。

第三,没有完整性校验。

uImage 头部有个 CRC32,但那只校验头部,不校验数据部分。

内核镜像在存储介质上被意外篡改了一个 bit,bootm 发现不了,启动时直接崩溃给你看。

FIT 的文件结构:.its 和 .itb

FIT 有两个核心文件类型:

文件 后缀 性质 用途
Image Tree Source .its 文本文件 人类可读的镜像描述
Image Tree Blob .itb 二进制文件 烧录到设备上的镜像

工作流程是这样的:

.its 文件  ──mkimage──>  .itb 文件  ──bootm──>  启动内核

.its 文件用 Device Tree 语法来写(没错,就是和 .dts 一样的语法)。

.itb 文件就是编译后的 FIT 镜像,是一个大的二进制 blob。

动手写一个 FIT 镜像

先看一个最简的 .its 文件,它包含:一个内核镜像 + 一个设备树。

1. 准备原材料

假设我们已经有编译好的内核和设备树:

work/
├── zImage                    # Linux 内核
├── myboard.dtb               # 设备树
└── fit_demo.its              # 我们要写的 ITS 文件(还未创建)

2. 编写 .its 文件

/dts-v1/;

/ {
    description = \"FIT Demo - 内核 + 设备树\";
    #address-cells = <1>;

    images {
        kernel@1 {
            description = \"Linux Kernel\";
            data = /incbin/(\"./zImage\");
            type = \"kernel\";
            arch = \"arm\";
            os = \"linux\";
            compression = \"none\";
            load = <0x80008000>;
            entry = <0x80008000>;
            hash@1 {
                algo = \"sha256\";
            };
        };

        fdt@1 {
            description = \"MyBoard Device Tree\";
            data = /incbin/(\"./myboard.dtb\");
            type = \"flat_dt\";
            arch = \"arm\";
            compression = \"none\";
            hash@1 {
                algo = \"sha256\";
            };
        };
    };

    configurations {
        default = \"conf@1\";
        conf@1 {
            description = \"MyBoard Default Config\";
            kernel = \"kernel@1\";
            fdt = \"fdt@1\";
        };
    };
};

3. 编译生成 .itb

mkimage -f fit_demo.its fit_demo.itb

mkimage 会帮我们:

  • 读取 .its 文件
  • 把 zImage 和 myboard.dtb 嵌入进去
  • 计算每个镜像的 SHA256 哈希值,写入到镜像树中
  • 生成最终的 .itb 文件

4. 在 U-Boot 中使用

tftp 0x82000000 fit_demo.itb
bootm 0x82000000

U-Boot 会自动解析 FIT 结构,把内核和设备树加载到正确的地址,然后启动。

FIT 镜像的结构图解

下面我们看一张图,把 FIT 的内部结构看透:

从上图可以看到:

  • 最外层是一个 / 根节点(和 Device Tree 一样)
  • images 子节点下,每个镜像是一个独立节点,按名字索引
  • configurations 子节点下,每个配置指定 \"用哪个内核 + 用哪个设备树\"
  • 每个镜像节点内部可以挂 hash 子节点来做校验
  • 加载地址(load)、入口地址(entry)直接写在镜像属性里

这种树状结构的好处是:可扩展性极强。

想加一个 initramfs?在 images 下加个 ramdisk@1 节点就行。

想加两个设备树,通过不同配置切换?再加一个 fdt@2 节点,新建一个 conf@2 引用它。

配置(configuration)

单内核 + 单设备树是最简单的情况。

但在实际项目中,同一个硬件可能运行不同的内核配置,或者需要根据产品型号选择不同的设备树。

比如你有一个车载项目,硬件平台相同,但:

  • 标准版用 Linux 主线内核
  • RT 版用打过 PREEMPT\_RT 补丁的内核
  • 高端版多了个 FPGA,需要加载 FPGA 比特流

用 FIT 的配置机制,一个 .itb 全部搞定:

configurations {
    default = \"standard\";
    standard {
        description = \"标准版配置\";
        kernel = \"kernel_standard\";
        fdt = \"fdt_standard\";
    };
    rt {
        description = \"实时版配置\";
        kernel = \"kernel_rt\";
        fdt = \"fdt_rt\";
    };
    high_end {
        description = \"高端版配置(含FPGA)\";
        kernel = \"kernel_high_end\";
        fdt = \"fdt_high_end\";
        loadables = \"fpga_bitstream\";
    };
};

在 U-Boot 中可以通过环境变量选择配置:

setenv fit_conf high_end
bootm 0x82000000

或者直接指定:

bootm 0x82000000#high_end

完整性校验

还记得前面说传统 uImage 只校验头部吗?

FIT 的 hash 机制直接解决了这个痛点。

每个镜像节点下可以挂一个或多个 hash 子节点:

kernel@1 {
    ...
    hash@1 {
        algo = \"sha256\";
    };
};

mkimage 在打包时会自动计算镜像数据的哈希值,写入 FIT 结构中。

U-Boot 在启动前会重新计算一遍,和存储的值做比对。

如果对不上,直接报错拒绝启动:

## Loading kernel from FIT Image at 82000000 ...
   Using 'conf@1' configuration
   Verifying Hash Integrity ... sha256 error!
Bad hash value for 'kernel@1' hash node in 'kernel@1' image node

这个报错信息,排查过闪存位翻转问题的小伙伴一定不陌生。

可选的算法有:sha1、sha256、md5、crc32。

推荐用 sha256,安全性和性能的平衡点最好。

压缩支持

嵌入式设备的存储空间寸土寸金。

FIT 支持对镜像子节点做压缩:

kernel@1 {
    ...
    compression = \"gzip\";
};

支持的压缩算法:

  • none:不压缩
  • gzip:通用压缩
  • bzip2:压缩率更高,但解压慢
  • lzma:高压缩率
  • lzo:解压速度极快,适合内核

要注意:压缩后 U-Boot 需要在启动时解压,会消耗 CPU 时间和内存。

一般推荐内核用 lzo(启动快),根文件系统用 lzma(体积小)。

签名验证

Hash 校验保证了数据完整性,但无法防止镜像被恶意替换。

假如攻击者把你 Flash 上的 FIT 镜像整个替换掉,重新算一遍 hash 写入,U-Boot 验 hash 的时候是验不出来的。

这时候就需要 FIT 的签名机制:

kernel@1 {
    ...
    signature@1 {
        algo = \"sha256,rsa2048\";
        key-name-hint = \"dev_key\";
        sign-images = \"kernel\", \"fdt\";
    };
};

配置签名后,需要先生成密钥对,再用 mkimage 签名:

# 生成 RSA 密钥对
openssl genpkey -algorithm RSA -out dev_key.key -pkeyopt rsa_keygen_bits:2048

# 编译并签名 FIT 镜像
mkimage -f fit_demo.its -K u-boot.dtb -k . -r fit_signed.itb

参数说明:

  • -K u-boot.dtb:把公钥写入 U-Boot 的设备树,这样 U-Boot 启动时就能验签
  • -k .:密钥所在目录
  • -r:要求签名必须存在

签名后的 FIT 镜像,U-Boot 会先验签再验 hash,双重保障。

这也是各大芯片厂商(NXP、TI、ST)安全启动方案的底层基础。

最后完整版 .its

把上面提到的所有特性汇总,一个典型的完整 .its 文件长这样:

/dts-v1/;

/ {
    description = \"Production FIT Image for MyBoard\";
    #address-cells = <1>;

    images {
        kernel@1 {
            description = \"Linux Kernel 5.10\";
            data = /incbin/(\"./zImage\");
            type = \"kernel\";
            arch = \"arm\";
            os = \"linux\";
            compression = \"lzo\";
            load = <0x80008000>;
            entry = <0x80008000>;
            hash@1 {
                algo = \"sha256\";
            };
            signature@1 {
                algo = \"sha256,rsa2048\";
                key-name-hint = \"prod_key\";
            };
        };

        fdt@1 {
            description = \"MyBoard Rev B Device Tree\";
            data = /incbin/(\"./myboard-revb.dtb\");
            type = \"flat_dt\";
            arch = \"arm\";
            compression = \"none\";
            hash@1 {
                algo = \"sha256\";
            };
        };

        ramdisk@1 {
            description = \"Initial RAM Disk\";
            data = /incbin/(\"./initramfs.cpio.gz\");
            type = \"ramdisk\";
            arch = \"arm\";
            os = \"linux\";
            compression = \"gzip\";
            hash@1 {
                algo = \"sha256\";
            };
        };
    };

    configurations {
        default = \"production\";
        production {
            description = \"生产环境配置\";
            kernel = \"kernel@1\";
            fdt = \"fdt@1\";
            ramdisk = \"ramdisk@1\";
        };
    };
};

编译命令还是那一条:

mkimage -f fit_demo.its -K u-boot.dtb -k . -r fit_production.itb

如果你正在做新项目,或者从老 U-Boot 迁移,强烈推荐用 FIT。

毕竟,一个 .itb 文件代替过去三四个分散的二进制文件,不管是版本管理、生产烧录、还是现场升级,都清爽太多了。

完美!

星标公众号,第一时间看文章!

最     后

小哥搜集了一些嵌入式学习资料,公众号内回复【1024】即可找到下载链接!

推荐好文  点击蓝色字体即可跳转

☞ 专辑|Linux应用程序编程大全![](https://mmbiz.qpic.cn/mmbiz_gif/EhBibrVVlmvSUia2CdHcydLGJy7qHhLklSbyOhAibp1rUnETq6COIyxIt7ogtTkBI2ibGFJ2dfiaB33eZzBsia2n2cicw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp#imgIndex=5)

☞ 专辑|学点网络知识![](https://mmbiz.qpic.cn/mmbiz_gif/EhBibrVVlmvSUia2CdHcydLGJy7qHhLklSbyOhAibp1rUnETq6COIyxIt7ogtTkBI2ibGFJ2dfiaB33eZzBsia2n2cicw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp#imgIndex=6)

☞ 专辑|手撕C语言![](https://mmbiz.qpic.cn/mmbiz_gif/EhBibrVVlmvSUia2CdHcydLGJy7qHhLklSbyOhAibp1rUnETq6COIyxIt7ogtTkBI2ibGFJ2dfiaB33eZzBsia2n2cicw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp#imgIndex=7)

☞ 专辑|手撕C++语言![](https://mmbiz.qpic.cn/mmbiz_gif/EhBibrVVlmvSUia2CdHcydLGJy7qHhLklSbyOhAibp1rUnETq6COIyxIt7ogtTkBI2ibGFJ2dfiaB33eZzBsia2n2cicw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp#imgIndex=8)

☞ 专辑|经验分享![](https://mmbiz.qpic.cn/mmbiz_gif/EhBibrVVlmvSUia2CdHcydLGJy7qHhLklSbyOhAibp1rUnETq6COIyxIt7ogtTkBI2ibGFJ2dfiaB33eZzBsia2n2cicw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp#imgIndex=9)

☞ 专辑|从单片机到Linux![](https://mmbiz.qpic.cn/mmbiz_gif/EhBibrVVlmvSUia2CdHcydLGJy7qHhLklSbyOhAibp1rUnETq6COIyxIt7ogtTkBI2ibGFJ2dfiaB33eZzBsia2n2cicw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp#imgIndex=10)

☞ 专辑|电能控制技术![](https://mmbiz.qpic.cn/mmbiz_gif/EhBibrVVlmvSUia2CdHcydLGJy7qHhLklSbyOhAibp1rUnETq6COIyxIt7ogtTkBI2ibGFJ2dfiaB33eZzBsia2n2cicw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp#imgIndex=11)

☞ 专辑|嵌入式必备数学知识 ![](https://mmbiz.qpic.cn/mmbiz_gif/EhBibrVVlmvSUia2CdHcydLGJy7qHhLklSbyOhAibp1rUnETq6COIyxIt7ogtTkBI2ibGFJ2dfiaB33eZzBsia2n2cicw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp#imgIndex=12)

☞  MCU进阶专辑

☞  嵌入式C语言进阶专辑

☞  经验分享

U-Boot的FIT镜像格式比老方法好用多了~" 网络安全文章

U-Boot的FIT镜像格式比老方法好用多了~"

本文详细介绍了U-Boot的FIT镜像格式,对比传统uImage在扩展性、安全性和管理效率方面的优势。FIT通过.its描述文件将内核、设备树等多个组件打包为.itb二进制文件,支持多配置切换、哈希校验、压缩和数字签名功能。文档提供了完整的.its文件示例和操作步骤,展示了如何实现安全启动和灵活部署。
HTTP参数污染" 网络安全文章

HTTP参数污染"

本文详细介绍了HTTP参数污染(HPP)的测试流程与攻击手法,重点解析三种后端解析逻辑:首参验证末参执行、末参验证首参执行及参数转换为数组,并给出对应的Payload构造思路,强调参数转换为数组手法的危险性,同时提醒即使无参数也可尝试添加参数进行测试。
国际航空管理数据泄露事件" 网络安全文章

国际航空管理数据泄露事件"

2026年6月25日发生国际航空管理数据泄露事件,黑客通过未授权访问后端API获取全球航空基础设施数据库(16.7MB/24,518条记录),涵盖航空公司、机场、城市和国家四维结构化数据。关键发现包括81个军用机场信息泄露具有军事参考价值,双语(阿拉伯语/英语)特征暗示源系统为中东地区航空数据管理平台。事件暴露API安全缺陷,建议通过威胁情报系统(cti.libaisec.com)监控此类数据泄露风险。
Gartner发布2026年网络安全八大趋势" 网络安全文章

Gartner发布2026年网络安全八大趋势"

Gartner发布的2026年网络安全八大趋势以AI发展为主线,指出代理型AI需升级传统IAM体系并纳入程序化监管,量子计算要求提前部署后量子密码。企业需加强网络韧性建设应对复杂法规环境,CISO职责扩展至AI标准制定、数据治理等多领域。生成式AI要求企业转向安全行为文化建设,AI化SOC需重构人机协同工作模式。
评论:0   参与:  0