不止是加个头用mkimage制作可启动脚本和FIT镜像玩转U-Boot高级功能在嵌入式开发领域U-Boot作为最流行的开源引导加载程序其核心工具mkimage的功能远不止于为内核镜像添加头部信息那么简单。对于已经掌握基础uImage制作的中高级开发者而言深入挖掘mkimage的高级功能能够解锁U-Boot更强大的引导能力实现多重启动、动态设备树配置等复杂场景。本文将带您突破传统uImage制作的局限探索两个极具实用价值的高级应用可执行脚本镜像和FITFlattened Image Tree镜像的制作与使用。1. 制作U-Boot可执行脚本镜像当我们需要在U-Boot环境中执行一系列命令时传统做法是手动输入或通过环境变量预设。但mkimage的script类型提供了一种更优雅的解决方案——将脚本打包成可启动镜像实现自动化配置和菜单驱动启动。1.1 脚本镜像的工作原理脚本镜像的核心是将纯文本的U-Boot命令序列转换为U-Boot可直接识别和执行的镜像格式。与内核镜像不同它不需要指定加载地址和入口点因为U-Boot会逐行解释执行其中的命令。创建一个简单的启动菜单脚本示例# 创建脚本内容 cat EOF bootscript.txt echo ### Boot Menu ### echo 1. Start Linux (default) echo 2. Enter recovery mode echo 3. Test hardware echo -n Select: setenv bootchoice \${keyc} if test \${bootchoice} 2; then setenv bootargs recovery echo Entering recovery mode... elif test \${bootchoice} 3; then run hardware_test exit fi bootm \${kernel_addr} EOF1.2 使用mkimage打包脚本将文本脚本转换为U-Boot可执行镜像的关键命令mkimage -T script -C none -A arm -O linux -n Boot Menu -d bootscript.txt boot.scr参数解析-T script指定镜像类型为可执行脚本-C none不压缩脚本内容-A arm目标架构根据实际情况调整-O linux操作系统类型-n设置镜像描述名称-d指定输入脚本文件生成的boot.scr文件可以直接被U-Boot加载执行U-Boot load mmc 0:1 ${loadaddr} boot.scr U-Boot source ${loadaddr}1.3 高级脚本技巧脚本镜像的真正威力在于它可以集成复杂的逻辑控制条件分支示例if test ${boot_type} netboot; then dhcp ${kernel_addr} kernel.img tftp ${fdt_addr} board.dtb else load mmc 0:1 ${kernel_addr} /boot/zImage load mmc 0:1 ${fdt_addr} /boot/dtbs/${fdtfile} fi环境变量处理# 检查并设置默认变量 if test -z ${baudrate}; then setenv baudrate 115200 fi循环控制setenv i 1 while test $i -le 5; do echo Attempt $i/5 ping 192.168.1.1 if test $? -eq 0; then break fi setexpr i $i 1 done2. FIT镜像现代U-Boot的多合一解决方案随着嵌入式系统复杂度提升传统的分散加载内核、设备树和initrd的方式显得力不从心。FITFlattened Image Tree格式应运而生它通过一个结构化描述文件(.its)将多个组件打包成单一镜像支持哈希校验、多重配置等高级特性。2.1 FIT镜像的核心优势与传统uImage相比FIT提供了以下关键改进特性传统uImageFIT镜像多组件支持单一组件内核、设备树、ramdisk等组合设备树处理需单独加载可内嵌多个设备树校验机制可选CRC强制哈希校验配置管理无支持多重启动配置版本控制无可包含版本信息2.2 创建FIT描述文件(.its)FIT镜像的制作始于编写一个结构化的描述文件。以下是一个典型示例/dts-v1/; / { description Example FIT Configuration; #address-cells 1; images { kernel1 { description Linux Kernel; data /incbin/(./zImage); type kernel; arch arm; os linux; compression gzip; load 0x80008000; entry 0x80008000; hash1 { algo sha256; }; }; fdt1 { description Device Tree Blob; data /incbin/(./board.dtb); type flat_dt; arch arm; compression none; hash1 { algo sha256; }; }; ramdisk1 { description Initial RAM Disk; data /incbin/(./initramfs.cpio.gz); type ramdisk; arch arm; os linux; compression gzip; hash1 { algo sha256; }; }; }; configurations { default config1; config1 { description Standard Boot Configuration; kernel kernel1; fdt fdt1; ramdisk ramdisk1; }; }; };2.3 编译FIT镜像使用mkimage将.its描述文件转换为可启动的FIT镜像mkimage -f image.its image.fit关键参数说明-f指定输入的.its描述文件输出文件通常以.fit或.itb为扩展名2.4 在U-Boot中使用FIT镜像加载和启动FIT镜像的基本流程U-Boot load mmc 0:1 ${loadaddr} image.fit U-Boot bootm ${loadaddr}对于包含多个配置的FIT镜像可以指定特定配置U-Boot bootm ${loadaddr}#config2查看FIT镜像信息U-Boot iminfo ${loadaddr}3. 高级FIT功能实战3.1 多重设备树支持FIT的强大之处在于可以包含多个设备树根据硬件自动选择images { fdt1 { description Device Tree for Board Rev A; data /incbin/(./board-reva.dtb); type flat_dt; arch arm; compression none; hash1 { algo sha256; }; }; fdt2 { description Device Tree for Board Rev B; data /incbin/(./board-revb.dtb); type flat_dt; arch arm; compression none; hash1 { algo sha256; }; }; }; configurations { configreva { description Configuration for Rev A Boards; kernel kernel1; fdt fdt1; }; configrevb { description Configuration for Rev B Boards; kernel kernel1; fdt fdt2; }; };3.2 安全启动支持FIT原生支持签名验证为安全启动提供基础/dts-v1/; / { ... configurations { default config1; config1 { description Signed Configuration; kernel kernel1; fdt fdt1; signature1 { algo sha256,rsa2048; key-name-hint dev_key; }; }; }; };签名过程需要额外的工具和密钥管理openssl genrsa -out dev.key 2048 openssl req -batch -new -x509 -key dev.key -out dev.crt mkimage -f image.its -k keys/ -K u-boot.dtb -r image.fit3.3 覆盖叠加(Overlay)支持现代U-Boot支持通过FIT应用设备树覆盖images { overlay1 { description DT Overlay for Additional Hardware; data /incbin/(./hw-addon.dtbo); type flat_dt; arch arm; compression none; }; }; configurations { config1 { kernel kernel1; fdt fdt1; overlay overlay1; }; };4. 调试与问题排查4.1 常见错误与解决方案错误现象可能原因解决方案Bad Magic Number镜像损坏或格式错误检查mkimage参数重新生成Hash node not foundFIT镜像缺少哈希节点在.its文件中添加hash节Invalid FDT设备树文件损坏重新编译.dtb文件No configuration selected未指定默认配置在.its中添加default属性4.2 调试工具与技巧解包FIT镜像dumpimage -l image.fit dumpimage -T flat_dt -p 0 -o kernel.fit image.fit验证签名fit_check_sign -f image.fit -k dev.keyU-Boot环境调试U-Boot setenv verify yes U-Boot setenv bootargs debug earlycon查看详细启动信息U-Boot setenv bootm_boot_mode sec U-Boot bootm ${loadaddr}在实际项目中FIT镜像的调试往往需要结合具体硬件平台。例如在内存受限的系统上可能需要调整内核和设备树的加载地址U-Boot setenv fdt_high 0xffffffff U-Boot setenv initrd_high 0xffffffff这些命令可以防止U-Boot在加载大镜像时出现内存冲突问题。