1 分钟阅读 次阅读

1 背景与核心痛点

  • “Unify Kernel” (统一内核) 的愿景:ARM 架构引入设备树 (FDT) 的核心目的,就是希望编译出一个统一的 Kernel Image。在启动时,由 Bootloader 根据当前具体的硬件板型,动态加载对应的 .dtb 文件,从而实现“一套镜像,适配多款硬件”。
  • Legacy uImage 的局限性
  • 操作繁琐:传统的启动方式(如使用 booti)需要手动将 Kernel、DTB、Ramdisk 等文件分别搬运到内存的不同物理地址。
  • 管理混乱:启动命令参数过于冗长。虽然早期的 Legacy uImage 利用 mkimage 加上了头部信息(包含加载地址、压缩格式和 CRC 校验等),但面对如今需要同时打包并灵活切换多个 DTB 的复杂需求时,传统的镜像格式显得力不从心。

2 FIT Image 的引入与设计思路

为了完美配合设备树实现统一分发,U-Boot 推出了全新的镜像格式 FIT (Flattened Image Tree)

  • 核心特性:允许将内核(Kernel)、多个设备树(DTB)、根文件系统(Ramdisk)等多个启动组件全部打包进一个单一的二进制文件中,并在启动时快速指定组合。
  • 实现原理:FIT 镜像的设计高度借鉴了设备树。
  • 它使用 .its (Image Tree Source) 作为打包的描述脚本,语法与 .dts 完全相同。
  • 通过 mkimage 工具(底层依赖 dtc 编译器)将 .its 蓝图和分散的二进制文件编译打包,最终生成 .itb 镜像文件。

3 ITS (Image Source File) 核心语法解析

.its 文件中包含两个至关重要的自定义节点:imagesconfigurations

1) images 节点 (物料库)

用于罗列所有需要被打包进镜像的原始二进制文件。每个文件作为一个子节点,包含以下关键属性:

  • data:二进制文件的相对路径,语法如 /incbin/("./Image")/incbin/("./ramdisk.img")
  • type:组件类型,如 "kernel""ramdisk""flat_dt"
  • **arch / os**:处理器架构(如 "arm64")和操作系统(如 "linux")。
  • compression:压缩算法(如 "gzip""none"/"uncompressed"),U-Boot 会据此在引导前自动解压。
  • **load / entry**:在内存中的加载绝对地址和执行入口地址。
  • hash:数据完整性校验算法(如 "sha256"),是防止镜像被篡改的核心依赖。

2) configurations 节点 (装箱单)

用于将 images 节点中的组件拼接成不同的“套餐”,以应对不同的硬件板型。

  • 可以通过 default = "config@1"; 指定默认配置。
  • 每个配置项(如 config@1, config@2)可以自由组合特定的 kernelramdiskfdt 节点。系统上电时,即可根据硬件特征直接调用对应配置。

4 its文件示例

device/rockchip/rk3588/boot.its

/*
 * Copyright (C) 2021 Rockchip Electronics Co., Ltd
 *
 * SPDX-License-Identifier: GPL-2.0
 */

/dts-v1/;
/ {
    description = "U-Boot FIT source file for arm";

    images {
        fdt {
            data = /incbin/("kernel/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-linux.dtb");
            type = "flat_dt";
            arch = "arm64";
            compression = "none";
            load = <0xffffff00>;

            hash {
                algo = "sha256";
            };
        };

        kernel {
            data = /incbin/("kernel/arch/arm64/boot/Image");
            type = "kernel";
            arch = "arm64";
            os = "linux";
            compression = "none";
            entry = <0xffffff01>;
            load = <0xffffff01>;

            hash {
                algo = "sha256";
            };
        };

        resource {
            data = /incbin/("kernel/resource.img");
            type = "multi";
            arch = "arm64";
            compression = "none";

            hash {
                algo = "sha256";
            };
        };

        initrd {
            description = "Ubuntu overlayroot ramdisk";
            data = /incbin/("../my_initrd.img");
            type = "ramdisk";
            arch = "arm64";
            os = "linux";
            compression = "none";
            load = <0xffffff02>;
            hash {
                algo = "sha256";
            };
        };
    };

    configurations {
        default = "conf";

        conf {
            rollback-index = <0x00>;
            fdt = "fdt";
            kernel = "kernel";
            multi = "resource";
            ramdisk = "initrd";

            signature {
                algo = "sha256,rsa2048";
                padding = "pss";
                key-name-hint = "dev";
                sign-images = "fdt", "kernel", "multi", "initrd";
            };
        };
    };
};

留下评论