OpenWrt fit 理解
开始
在 OpenWrt 经常看到这样的写法:
fit 你在做什么?fit 的定义在 include/image-commands.mk 中
define Build/fit $(TOPDIR)/scripts/mkits.sh \ -D $(DEVICE_NAME) -o $@.its -k $@ \ -C $(word 1,$(1)) $(if $(word 2,$(1)),\ $(if $(DEVICE_DTS_OVERLAY),-d $(KERNEL_BUILD_DIR)/image-$$(basename $(word 2,$(1))),\ -d $(word 2,$(1)))) \ $(if $(findstring with-rootfs,$(word 3,$(1))),-r $(IMAGE_ROOTFS)) \ $(if $(findstring with-initrd,$(word 3,$(1))), \ $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS_SEPARATE), \ -i $(KERNEL_BUILD_DIR)/initrd.cpio$(strip $(call Build/initrd_compression)))) \ -a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ $(if $(DEVICE_FDT_NUM),-n $(DEVICE_FDT_NUM)) \ $(if $(DEVICE_DTS_DELIMITER),-l $(DEVICE_DTS_DELIMITER)) \ $(if $(DEVICE_DTS_OVERLAY),$(foreach dtso,$(DEVICE_DTS_OVERLAY), -O $(dtso):$(KERNEL_BUILD_DIR)/image-$(dtso).dtb)) \ -c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config-1") \ -A $(LINUX_KARCH) -v $(LINUX_VERSION) PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage $(if $(findstring external,$(word 3,$(1))),\ -E -B 0x1000 $(if $(findstring static,$(word 3,$(1))),-p 0x1000)) -f $@.its $@.new @mv $@.new $@ endef
里面做了两件事情:
- scripts/mkits.sh 生成 .its
- mkimage 生成 fit
实例展开如下:
/home/my/openwrt/scripts/mkits.sh -D my -o /home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/my-kernel.bin.its -k /home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/my-kernel.bin -C none -d /home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/linux-5.15.31/arch/riscv/boot/dts/allwinner/my.dtb -a 0x40200000 -e 0x40200000 -c "config-1" -A riscv -v 5.15.31
mkimage -f /home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/my-kernel.bin.its /home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/my-kernel.bin.new
scripts/mkits.sh 理解
用法如下:
lql@debian:~/my/openwrt$ ./scripts/mkits.sh Usage: mkits.sh -A arch -C comp -a addr -e entry -v version -k kernel [-D name -n address -d dtb] -o its_file -A ==> set architecture to 'arch' -C ==> set compression type 'comp' -c ==> set config name 'config' -a ==> set load address to 'addr' (hex) -e ==> set entry point to 'entry' (hex) -f ==> set device tree compatible string -i ==> include initrd Blob 'initrd' -v ==> set kernel version to 'version' -k ==> include kernel image 'kernel' -D ==> human friendly Device Tree Blob 'name' -n ==> fdt unit-address 'address' -d ==> include Device Tree Blob 'dtb' -r ==> include RootFS blob 'rootfs' -H ==> specify hash algo instead of SHA1 -l ==> legacy mode character (@ etc otherwise -) -o ==> create output file 'its_file' -O ==> create config with dt overlay 'name:dtb' (can be specified more than once)
脚本理解:
#!/bin/sh # # Licensed under the terms of the GNU GPL License version 2 or later. # # Author: Peter Tyser <ptyser@xes-inc.com> # # U-Boot firmware supports the booting of images in the Flattened Image # Tree (FIT) format. The FIT format uses a device tree structure to # describe a kernel image, device tree blob, ramdisk, etc. This script # creates an Image Tree Source (.its file) which can be passed to the # 'mkimage' utility to generate an Image Tree Blob (.itb file). The .itb # file can then be booted by U-Boot (or other bootloaders which support # FIT images). See doc/uImage.FIT/howto.txt in U-Boot source code for # additional information on FIT images. #
脚本的开头说明了一切:
- fit 是指 Flattened ImageTree (FIT)
- mkits.sh目的是生成 Image Tree Source (.its file)
- .its 文件是给 mkimage 用于生成 Image Tree Blob (.itb file)
- 更多关于FIT请看u-boot 源码中的 doc/uImage.FIT/howto.txt
生成的目标文件 .its 如下:
/dts-v1/; / { description = "RISCV OpenWrt FIT (Flattened Image Tree)"; #address-cells = <1>; images { kernel-1 { description = "RISCV OpenWrt Linux-5.15.31"; data = /incbin/("/home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/my-kernel.bin"); type = "kernel"; arch = "riscv"; os = "linux"; compression = "none"; load = <0x40200000>; entry = <0x40200000>; hash@1 { algo = "crc32"; }; hash@2 { algo = "sha1"; }; }; fdt-1 { description = "RISCV OpenWrt my device tree blob"; data = /incbin/("/home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/linux-5.15.31/arch/riscv/boot/dts/allwinner/my.dtb"); type = "flat_dt"; arch = "riscv"; compression = "none"; hash@1 { algo = "crc32"; }; hash@2 { algo = "sha1"; }; }; }; configurations { default = "config-1"; config-1 { description = "OpenWrt my"; kernel = "kernel-1"; fdt = "fdt-1"; }; }; };
mkimage
关于 mkimage , 并不陌生,常规用法如下,用于生成 uImage
define Build/uImage
mkimage \
-A $(LINUX_KARCH) \
-O linux \
-T kernel \
-C $(word 1,$(1)) \
-a $(KERNEL_LOADADDR) \
-e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \
-n '$(if $(UIMAGE_NAME),$(UIMAGE_NAME),$(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION))' \
$(if $(UIMAGE_MAGIC),-M $(UIMAGE_MAGIC)) \
$(wordlist 2,$(words $(1)),$(1)) \
-d $@ $@.new
mv $@.new $@
ende
mkimage -h 查看 usage
lql@debian:~/my/openwrt$ mkimage -h
mkimage: invalid option -- 'h'
Error: Invalid option
Usage: mkimage -l image
-l ==> list image header information
mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
-A ==> set architecture to 'arch'
-O ==> set operating system to 'os'
-T ==> set image type to 'type'
-C ==> set compression type 'comp'
-a ==> set load address to 'addr' (hex)
-e ==> set entry point to 'ep' (hex)
-n ==> set image name to 'name'
-d ==> use image data from 'datafile'
-x ==> set XIP (execute in place)
mkimage [-D dtc_options] [-f fit-image.its|-f auto|-F] [-b <dtb> [-b <dtb>]] [-i <ramdisk.cpio.gz>] fit-image
<dtb> file is used with -f auto, it may occur multiple times.
-D => set all options for device tree compiler
-f => input filename for FIT source
-i => input filename for ramdisk file
Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)
mkimage -V ==> print version information and exit
Use -T to see a list of available image types
这里我们看到另一种用法:用 -f 指定 FIT 文件 。
mkimage -f /home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/my-kernel.bin.its /home/my/openwrt/build_dir/target-riscv64_riscv64_musl/linux-sunxid1/my-kernel.bin.new
输入文件和各项参数都在 .its 中指定了。 相比第一种用法,更适用于多个文件的拼接。