什么是FITFIT(Flattened Image Tree)是uboot的一种新的镜像打包方案它是由uboot负责解析的生成的文件名是xxx.itb在一个itb镜像中我们可以打包进去多个内核、设备树、ramdisk的镜像然后按照实际需求进行组合使用。他通过its文件进行配置然后通过内核编译出来的mkimage工具进行编译mkimage -f xxx.its abc.itb。FIT不仅能打包内核镜像也能打包二进制文件支持的格式可以通过mkimage -T list指令列出。下面是内核、设备树、ramdisk打包的一个示例 abc.its注打包成FIT格式的内核设备树在uboot中通过bootm启动bootm启动之前要先将fit镜像给load进去fatload或者ext4load或者load/dts-v1/; / { description Various kernels, ramdisks and FDT blobs; #address-cells 1; images { kernel-1 { description vanilla-2.6.23; data /incbin/(./vmlinux.bin.gz); type kernel; //类型是kernel arch arm; os linux; compression gzip; load 0x00200000; //U-Boot 把这个 image 解压/加载到哪个内存地址 entry 0x00200000; //CPU 跳转执行的地址 //mkimage 会计算hash值存在FIT中u-boot启动是会计算校验和是否一致 hash-1 { algo md5; }; hash-2 { algo sha1; }; }; kernel-2 { description 2.6.23-denx; data /incbin/(./2.6.23-denx.bin.gz); type kernel; arch arm; os linux; compression gzip; load 0x00200000; entry 0x00200000; hash-1 { algo sha1; }; }; kernel-3 { description 2.4.25-denx; data /incbin/(./2.4.25-denx.bin.gz); type kernel; arch arm; os linux; compression gzip; load 0x00200000; entry 0x00200000; hash-1 { algo md5; }; }; ramdisk-1 { description eldk-4.2-ramdisk; data /incbin/(./eldk-4.2-ramdisk); type ramdisk; arch arm; os linux; compression gzip; load 0x0a200000; hash-1 { algo sha1; }; }; ramdisk-2 { description eldk-3.1-ramdisk; data /incbin/(./eldk-3.1-ramdisk); type ramdisk; //类型是ramdisk arch arm; os linux; compression gzip; load 0x0a200000; hash-1 { algo crc32; }; }; fdt-1 { description tqm5200-fdt; data /incbin/(./tqm5200.dtb); type flat_dt; //类型是设备树 arch arm; compression none; hash-1 { algo crc32; }; }; fdt-2 { description tqm5200s-fdt; data /incbin/(./tqm5200s.dtb); type flat_dt; arch arm; compression none; load 00700000; hash-1 { algo sha1; }; }; }; //uboot 启动时可以选择不同的配置去启动如 //fatload 0:1 0x43000000 abc.itb //bootm 0x43000000#config-1 configurations { default config-1; config-1 { description tqm5200 vanilla-2.6.23 configuration; kernel kernel-1; ramdisk ramdisk-1; fdt fdt-1; }; config-2 { description tqm5200s denx-2.6.23 configuration; kernel kernel-2; ramdisk ramdisk-1; fdt fdt-2; }; config-3 { description tqm5200s denx-2.4.25 configuration; kernel kernel-3; ramdisk ramdisk-2; }; }; };打包二进制文件示例 firmware.its/dts-v1/; / { description MyFirmware; images { myfw { description My Firmware Image; data /incbin/(/home/cmb/smios/uboot_TYsys/u-boot-2023.10/examples/standalone/hello_world.bin); type firmware; //类型是固件 arch arm; os linux; compression none; load 0x80007800; entry 0x80007800; }; }; };镜像打包、解包工具打包解包工具目前用的比较好的有 mkimage、dumpimage、binwalk 、cpiomkimage dumpimage - U-Boot自带的打包、解包工具使用mkimage打包出来的FIT镜像就可以使用dumpimage进行解包用法dumpimage -l image.itb作用解析 U-Boot image header显示镜像信息dumpimage -T flat_dt -p 0 -o kernel.gz image.itb作用从FIT镜像中提取第0个image,输出到kernel.gz,格式是FIT image格式其实看下FIT和配置文件its,他就是设备树的写法然后打包出来的FIT镜像的保存方式其实跟dtb是一样的所以还可以通过 “dtc -i dtb -o dts image.itb” 把FIT镜像的配置文件its给解析出来。binwalk - 基于python的解包工具binwalk 是 嵌入式固件分析中非常常用的工具主要用来 扫描和自动提取固件中的各种文件系统、压缩数据、内核、DTB、uImage、squashfs、cpio 等。安装sudo apt install binwalk用法binwalk firmware.bin作用扫描固件列含义DECIMAL偏移十进制HEXADECIMAL偏移十六进制DESCRIPTION识别到的格式binwalk -e firmware.bin作用自动提取运行后生成目录_firmware.bin.extracted/binwalk -Me firmware.bin作用递归提取会把提取出来的镜像继续解包cpio - ramdisk 镜像打包解包工具cpio是Linux的一种归档工具和tar类似常用语ramdisk的打包和解包。用法cpio -idmv ramdisk.cpio作用从ramdisk.cpio读取归档内容并解压到当前目录注意是使用 “ ramdisk.cpio” 因为cpio默认是从stdin读归档数据的。find . | cpio -o -H newc ramdisk.cpio作用将当前目录下的所有文件打包成ramdisk.cpiouboot 中的load指令在U-Boot中load指令就是将EMMC中的数据读到DDR中然后其他指令才能去执行。load有好几个指令可以分为两大类原始块读取按扇区读和文件系统读取按文件名读load 指令语法load dev:partition例子load mmc 0:1 0x43000000 image.itb含义从mmc0的第1分区读取image.itb文件到0x43000000地址load会自动识别文件系统FAT、EXT2、EXT4,所以等价于fatload、ext4loadfatload 指令语法fatload dev:partition例子fatload mmc 0:1 0x43000000 image.itb还可以支持USB 设备如fatload usb 0:1 0x43000000 a.pngext4load 指令语法ext4load dev:partition filename例如ext4load mmc 0:2 0x42000000 /boot/image.itbext2load 指令ext4向下兼容ext2,所以现在基本都用ext4load.tftpboot 指令从TFTP服务器下载文件语法tftpboot filename例如 tftpboot 0x43000000 image.itbmmc read 原始扇区读取这个指令不是按照文件名读取而是按照扇区读取。语法 mmc read例如 mmc read 0x42000000 0x8000 0x200从mmc的第0x8000扇区开始读取0x200个扇区保存到DDR的0x42000000地址nand read(NAND Flash)如果设备是NAND Flash则使用nand read指令语法nand read例如nand read 0x43000000 0x200000 0x800000从NAND Flash的第0x200000字节开始读取0x800000字节保存到DDR的0x43000000地址sf read (SPI NOR Flash)如果设备是SPI NOR Flash则使用sf read指令语法sf read例如sf read 0x43000000 0x200000 0x800000loadx/loady/loadb通过串口传输文件PC → 串口 → U-Boot → RAMloadx语法loadx例如loadx 0x43000000意思是等待PC通过XMODEM发送文件接收后存到0x43000000PC 端发送文件Linux下sx file.bin /dev/ttyUSB0 /dev/ttyUSB0loady语法loady和loadx类似不过他用YMODEM协议传输速度比XMODEM快PC 端发送文件Linux下sb file.bin /dev/ttyUSB0 /dev/ttyUSB0loadb语法loadbPC 端发送文件Linux下kermit 然后 send file.bin优点是可靠支持错误恢复适合长距离通信但是使用复杂用的比较少调试的时候使用这个就不用烧Flash了直接通过串口下载kernel到RAM命令协议特点loadxXMODEM最简单、最常见loadyYMODEM支持文件名、批量loadbKermit兼容性好常见配套指令查看文件fatls mmc 0:1ext4ls mmc 0:2 /查看分区mmc part查看设备mmc listuboot中分区的格式化当我们使用fatloada/ext4load从EMMC分区中读文件的时候要求对应的mmc是带格式化的分区的这是怎么实现的呢其实uboot仅仅知道EMMC的分区是怎么分的比如说第几个分区的起始位置是多少大小是多少他是不知道这个里面是什么格式的决定分区格式的其实是我们烧录进去的镜像比如说我想在LCD屏上画一个开机界面然后把图片放到了EMMC的分区4中使用fatload加载图片这要怎么做呢首先创建一个FAT格式的镜像里面保存该开机图片如# 制作FAT镜像ddif/dev/zerooffat.imgbs1Mcount5mkfs.vfat fat.imgsudomount-oloop ./fat.img ./mntcdmntsudomkdirlogosudocp/home/cmb2204/github/smios/baremetal/uboot-ubl/logo/ST75161/black_cell.bmp ./sudoumount./mnt然后将fat.img烧录到EMMC的分区4中在uboot中加载图片# uboot 中加载图片fatload mmc0:4 0x12340000 logo/black_cell.bmp# 使用bmp指令显示图片bmp info 0x12340000bmp display 0x12340000