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 中指定了。 相比第一种用法,更适用于多个文件的拼接。