U-Boot FIT镜像启动异常问题排查与原因分析
Starting kernel ...的原因 问题现象
- 通过Yocto(meta-updater层)构建的U-Boot FIT镜像启动时卡在
Starting kernel ...阶段 - 手动将kernel或device tree复制到其他内存地址后用
bootz启动,或者调整.its文件把device tree放在kernel之前,镜像就能正常运行
原始配置与镜像信息
原始.its文件
/dts-v1/; / { description = "Kernel fitImage for FSLC FrameBuffer/5.10.9+gitAUTOINC+32513c25d8/exappscreen"; #address-cells = <1>; images { kernel-1 { description = "Linux kernel"; data = /incbin/("linux.bin"); type = "kernel"; arch = "arm"; os = "linux"; compression = "none"; load = <0x80008000>; entry = <0x80008000>; hash-1 { algo = "sha256"; }; }; fdt-exappscreen.dtb { description = "Flattened Device Tree blob"; data = /incbin/("arch/arm/boot/dts/exappscreen.dtb"); type = "flat_dt"; arch = "arm"; compression = "none"; hash-1 { algo = "sha256"; }; }; ramdisk-1 { description = "initramfs-ostree-image"; data = /incbin/("/home/dane/yocto/fsl-community-bsp/exappscreen/tmp/deploy/images/exappscreen/initramfs-ostree-image-exappscreen.cpio.gz"); type = "ramdisk"; arch = "arm"; os = "linux"; compression = "none"; hash-1 { algo = "sha256"; }; }; }; configurations { default = "conf-exappscreen.dtb"; conf-exappscreen.dtb { description = "1 Linux kernel, FDT blob, ramdisk"; kernel = "kernel-1"; fdt = "fdt-exappscreen.dtb"; ramdisk = "ramdisk-1"; hash-1 { algo = "sha256"; }; }; }; };
原始FIT镜像iminfo输出
## Checking Image at 82000000 ... FIT image found FIT description: Kernel fitImage for FSLC FrameBuffer/5.10.9+gitAUTOINC+32513c25d8/exappscreen Created: 2021-03-09 2:17:18 UTC Image 0 (kernel-1) Description: Linux kernel Created: 2021-03-09 2:17:18 UTC Type: Kernel Image Compression: uncompressed Data Start: 0x82000100 Data Size: 7806336 Bytes = 7.4 MiB Architecture: ARM OS: Linux Load Address: 0x80008000 Entry Point: 0x80008000 Hash algo: sha256 Hash value: cf08dd91b86a8478417c12398866832358463797dc6990be5ae33a48c4fae5d5 Image 1 (fdt-exappscreen.dtb) Description: Flattened Device Tree blob Created: 2021-03-09 2:17:18 UTC Type: Flat Device Tree Compression: uncompressed Data Start: 0x82771f8c Data Size: 32086 Bytes = 31.3 KiB Architecture: ARM Hash algo: sha256 Hash value: 8f08ffc245d6dd1a70a4c6a85bac46b2007af3594237179f3cdc89c0892522a1 Image 2 (ramdisk-1) Description: initramfs-ostree-image Created: 2021-03-09 2:17:18 UTC Type: RAMDisk Image Compression: uncompressed Data Start: 0x82779db0 Data Size: 1864194 Bytes = 1.8 MiB Architecture: ARM OS: Linux Load Address: unavailable Entry Point: unavailable Hash algo: sha256 Hash value: fb57b408c01ed997e07be816393940ae618b8b20d37b85ac1b47e4a5215bb783 Default Configuration: 'conf-exappscreen.dtb' Configuration 0 (conf-exappscreen.dtb) Description: 1 Linux kernel, FDT blob, ramdisk Kernel: kernel-1 Init Ramdisk: ramdisk-1 FDT: fdt-exappscreen.dtb Hash algo: sha256 Hash value: unavailable ## Checking hash(es) for FIT Image at 82000000 ... Hash(es) for Image 0 (kernel-1): sha256+ Hash(es) for Image 1 (fdt-exappscreen.dtb): sha256+ Hash(es) for Image 2 (ramdisk-1): sha256+
修改后可正常运行的配置与镜像信息
修改后的.its文件
/dts-v1/; / { description = "Kernel fitImage for FSLC FrameBuffer/5.10.9+gitAUTOINC+32513c25d8/exappscreen"; #address-cells = <1>; images { fdt-exappscreen.dtb { description = "Flattened Device Tree blob"; data = /incbin/("./exappscreen--5.10.9+git0+32513c25d8-r0-exappscreen-20231120190329.dtb"); type = "flat_dt"; arch = "arm"; compression = "none"; hash-1 { algo = "sha256"; }; }; kernel-1 { description = "Linux kernel"; data = /incbin/("./zImage--5.10.9+git0+32513c25d8-r0-exappscreen-20231120190329.bin"); type = "kernel"; arch = "arm"; os = "linux"; compression = "none"; load = <0x80008000>; entry = <0x80008000>; hash-1 { algo = "sha256"; }; }; ramdisk-1 { description = "initramfs-ostree-image"; data = /incbin/("./initramfs-ostree-image-exappscreen-20231129181607.cpio.gz"); type = "ramdisk"; arch = "arm"; os = "linux"; compression = "gzip"; hash-1 { algo = "sha256"; }; }; }; configurations { default = "conf-exappscreen.dtb"; conf-exappscreen.dtb { description = "1 Linux kernel, FDT blob, ramdisk"; kernel = "kernel-1"; fdt = "fdt-exappscreen.dtb"; ramdisk = "ramdisk-1"; hash-1 { algo = "sha256"; }; }; }; };
修改后FIT镜像iminfo输出
## Checking Image at 82000000 ... FIT image found FIT description: Kernel fitImage for FSLC FrameBuffer/5.10.9+gitAUTOINC+32513c25d8/exappscreen Created: 2023-12-01 13:27:09 UTC Image 0 (fdt-exappscreen.dtb) Description: Flattened Device Tree blob Created: 2023-12-01 13:27:09 UTC Type: Flat Device Tree Compression: uncompressed Data Start: 0x82000114 Data Size: 32086 Bytes = 31.3 KiB Architecture: ARM Hash algo: sha256 Hash value: 8f08ffc245d6dd1a70a4c6a85bac46b2007af3594237179f3cdc89c0892522a1 Image 1 (kernel-1) Description: Linux kernel Created: 2023-12-01 13:27:09 UTC Type: Kernel Image Compression: uncompressed Data Start: 0x82007f30 Data Size: 7806336 Bytes = 7.4 MiB Architecture: ARM OS: Linux Load Address: 0x80008000 Entry Point: 0x80008000 Hash algo: sha256 Hash value: cf08dd91b86a8478417c12398866832358463797dc6990be5ae33a48c4fae5d5 Image 2 (ramdisk-1) Description: initramfs-ostree-image Created: 2023-12-01 13:27:09 UTC Type: RAMDisk Image Compression: gzip compressed Data Start: 0x82779db0 Data Size: 1864194 Bytes = 1.8 MiB Architecture: ARM OS: Linux Load Address: unavailable Entry Point: unavailable Hash algo: sha256 Hash value: fb57b408c01ed997e07be816393940ae618b8b20d37b85ac1b47e4a5215bb783 Default Configuration: 'conf-exappscreen.dtb' Configuration 0 (conf-exappscreen.dtb) Description: 1 Linux kernel, FDT blob, ramdisk Kernel: kernel-1 Init Ramdisk: ramdisk-1 FDT: fdt-exappscreen.dtb Hash algo: sha256 Hash value: unavailable
原因分析
从配置和镜像信息对比可以看出,核心差异在于FIT镜像内部的文件存储顺序,以及由此导致的内存覆盖问题:
原始镜像的内存布局冲突
原始FIT镜像加载在0x82000000地址,其中kernel数据从0x82000100开始,大小7.4MiB,结束地址为0x82000100 + 0x76C000 = 0x8276C100。虽然device tree起始地址0x82771F8C看起来和kernel不重叠,但问题出在kernel自身运行时会覆盖FDT所在的内存区域。
ARM内核启动时,会将自身从加载地址0x80008000复制到高端内存(通常是内存末尾附近),或在运行过程中使用FDT所在区域作为临时缓冲区,导致FDT被破坏,内核无法正确解析硬件信息,最终卡在Starting kernel ...阶段。修改后镜像的内存布局避免了冲突
修改.its文件将FDT放在kernel之前,FDT的起始地址是0x82000114,大小仅31.3KiB,结束地址为0x82000114 + 0x7D56 = 0x82007E6A,而kernel从0x82007F30开始,两者完全不重叠。此时内核启动时,即使操作自身加载区域附近的内存,也不会覆盖FDT的数据,内核能正常读取FDT完成初始化。手动启动可行的原因
用bootz手动启动时,kernel和FDT被复制到了其他内存地址,避开了原始FIT镜像所在的内存区域,避免了内核运行时对FDT的覆盖,因此能正常启动。
另外注意到修改后的ramdisk启用了gzip压缩,但这不是核心原因——原始镜像中ramdisk的位置和修改后一致,且手动启动时未修改ramdisk压缩方式也能正常运行,所以压缩方式不影响启动结果。
内容的提问来源于stack exchange,提问作者Dane

