• 【精读Uboot】its文件语法


    前面我们分析了SPL汇编的执行过程,在SPL之后就要进入另一个loader加载镜像了。在正式分析跳转流程之前,我们需要搞清楚在我们平时下载的imx-boot-xxx这个镜像是如何组成的。

    在编译完Uboot、optee和ATF之后,会产生u-boot-spl.binu-boot-nodtb.binimx8mp-evk.dtbbl31.bintee.bin。首先将ddr的固件和u-boot-spl.bin拼接为u-boot-spl-ddr.bin,这个bin文件就是SPL部分。其余的bin文件需要组装为一个含uboot.bin的文件,然后将这俩个bin组装起来,加上IVT等头信息就得到了最终可用的imx-boot-xxx

    1 image source file

    Linux kernel在ARM架构中引入device tree(全称是flattened device tree,后续将会以FDT代称)的时候,怀揣着一个Unify Kernel的梦想,即同一个Image,通过切换不同的dtb支持多个不同的平台。device tree在kernel中普及之后,Uboot也引入了device tree。因此为了和kernel类似,Uboot也需要一种新的image格式,这种格式需要支持以下特性:

    1. Image中需要包含多个dtb文件
    2. 可以方便的选择使用哪个dtb文件

    结合以上两点需求,Uboot推出了新的image格式:FIT image,其中FIT是flattened image tree的简称。它利用了Device Tree Source files(DTS)的语法,生成的image文件也和dtb文件类似(从its编译为itb)。

    1.1 image source file的语法分析

    下面是i.MX8MP使用的its文件,在image标签中声明了uboot-1fdt-1atf-1tee-1子标签,分别代表uboot,dtb,atf和tee。

    对于子标签当中的定义,description描述这个子标签是什么;data声明这个bin文件的位置和名称;type声明这个子标签的类型;arch表明最终固件运行的架构;compression表示是否是压缩格式;load声明这个固件在RAM中的加载地址,子固件需要被SPL拷贝到RAM中的对应地址;entry表示二进制文件入口地址。

    configurations中声明你需要的配置选择项,可以是多个不同的配置。firmware声明uboot标签名, loadables声明可以跳转的其余固件,fdt声明dtb的标签名。

    在SPL 阶段,首先优先加载firmware节点,将fdt加载到紧跟着firmware之后的位置,然后尝试加载kernel节点;失败了再去加载loadables节点里的固件。这里的加载是指加载到RAM的指定位置。

    /dts-v1/;
    
    / {
    	description = "Configuration to load ATF before U-Boot";
    	#address-cells = <1>;
    
    	images {
    		uboot-1 {
    			description = "U-Boot (64-bit)";
    			data = /incbin/("u-boot-nodtb.bin");
    			type = "standalone";
    			arch = "arm64";
    			compression = "none";
    			load = <0x40200000>;
    		};
    		fdt-1 {
    			description = "evk";
    			data = /incbin/("evk.dtb");
    			type = "flat_dt";
    			compression = "none";
    		};
    		atf-1 {
    			description = "ARM Trusted Firmware";
    			data = /incbin/("bl31.bin");
    			type = "firmware";
    			arch = "arm64";
    			compression = "none";
    			load = <0x00970000>;
    			entry = <0x00970000>;
    		};
    		tee-1 {
    			description = "TEE firmware";
    			data = /incbin/("tee.bin");
    			type = "firmware";
    			arch = "arm64";
    			compression = "none";
    			load = <0x56000000>;
    			entry = <0x56000000>;
    		};
    	};
    	configurations {
    		default = "config-1";
    
    		config-1 {
    			description = "evk";
    			firmware = "uboot-1";
    			loadables = "atf-1", "tee-1";
    			fdt = "fdt-1";
    		};
    	};
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    1.2 示意图

    下图是i.MX8MP平台在SPL阶段解包FIT后存放各bin文件的示意图。

    its.drawio

    2. soc.mk

    最终的imx-boot文件由 soc.mk制作。u-boot-spl-ddr.bin声明了如何将DDR的固件和u-boot-spl.bin拼接起来;u-boot.itb声明了如何制作fit文件;flash_evk_no_hdmi声明了如何制作最终的imx-boot-xxx

    请自行理解这段Makefile语法。

    SPL_LOAD_ADDR = 0x920000
    SPL_FSPI_LOAD_ADDR = 0x920000
    TEE_LOAD_ADDR =  0x56000000
    ATF_LOAD_ADDR = 0x00970000
    
    lpddr4_imem_1d = lpddr4_pmu_train_1d_imem$(LPDDR_FW_VERSION).bin
    lpddr4_dmem_1d = lpddr4_pmu_train_1d_dmem$(LPDDR_FW_VERSION).bin
    lpddr4_imem_2d = lpddr4_pmu_train_2d_imem$(LPDDR_FW_VERSION).bin
    lpddr4_dmem_2d = lpddr4_pmu_train_2d_dmem$(LPDDR_FW_VERSION).bin
    
    u-boot-spl-ddr.bin: u-boot-spl.bin $(lpddr4_imem_1d) $(lpddr4_dmem_1d) $(lpddr4_imem_2d) $(lpddr4_dmem_2d)
    	@objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 $(lpddr4_imem_1d) lpddr4_pmu_train_1d_imem_pad.bin
    	@objcopy -I binary -O binary --pad-to 0x4000 --gap-fill=0x0 $(lpddr4_dmem_1d) lpddr4_pmu_train_1d_dmem_pad.bin
    	@objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 $(lpddr4_imem_2d) lpddr4_pmu_train_2d_imem_pad.bin
    	@cat lpddr4_pmu_train_1d_imem_pad.bin lpddr4_pmu_train_1d_dmem_pad.bin > lpddr4_pmu_train_1d_fw.bin
    	@cat lpddr4_pmu_train_2d_imem_pad.bin $(lpddr4_dmem_2d) > lpddr4_pmu_train_2d_fw.bin
    	@dd if=u-boot-spl.bin of=u-boot-spl-pad.bin bs=4 conv=sync
    	@cat u-boot-spl-pad.bin lpddr4_pmu_train_1d_fw.bin lpddr4_pmu_train_2d_fw.bin > u-boot-spl-ddr.bin
    	@rm -f u-boot-spl-pad.bin lpddr4_pmu_train_1d_fw.bin lpddr4_pmu_train_2d_fw.bin lpddr4_pmu_train_1d_imem_pad.bin lpddr4_pmu_train_1d_dmem_pad.bin lpddr4_pmu_train_2d_imem_pad.bin
    
    u-boot.itb: $(dtb)
    	./$(PAD_IMAGE) $(TEE)
    	./$(PAD_IMAGE) bl31.bin
    	./$(PAD_IMAGE) u-boot-nodtb.bin $(dtb)
    	BL32=$(TEE) DEK_BLOB_LOAD_ADDR=$(DEK_BLOB_LOAD_ADDR) TEE_LOAD_ADDR=$(TEE_LOAD_ADDR) ATF_LOAD_ADDR=$(ATF_LOAD_ADDR) ../$(SOC_DIR)/mkimage_fit_atf.sh $(dtb) > u-boot.its
    	mkimage -E -p 0x3000 -f u-boot.its u-boot.itb
    	@rm -f u-boot.its $(dtb)
    	
    
    flash_evk_no_hdmi: $(MKIMG) u-boot-spl-ddr.bin u-boot.itb
    	./mkimage_imx8 -version $(VERSION) -fit -loader u-boot-spl-ddr.bin $(SPL_LOAD_ADDR) -second_loader u-boot.itb 0x40200000 0x60000 -out $(OUTIMG)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    比UUID更快更安全NanoID到底是怎么实现的?(荣耀典藏版)
    Python中的变量是什么类型?
    shardingJdbc分库分表实战
    spark DStream从不同数据源采集数据(RDD 队列、文件、diy 采集器、kafka)(scala 编程)
    【西瓜书】5.神经网络
    智能物流新纪元:分布式I/O模块重塑仓储自动化
    项目经理如何提升团队执行力?
    10 个Python 自动化脚本的摸鱼神器 ,你确定你不学习一下?
    Day8 ---- 云资讯项目介绍与创建
    如何搬运视频赚钱?
  • 原文地址:https://blog.csdn.net/qq_38131812/article/details/132751946