IMX6ULL运行Linux系统的Bootloader的三个阶段详解(BootROM、SPL、U-Boot)(SPL和U-Boot合成镜像`u-boot-dtb.imx`时需要作填充数据处理)

三个阶段概述

IMX6ULL运行Linux系统的Bootloader过程通常分为三个部分


1️⃣ 处理器内部 ROM 代码(BootROM)

  • 这部分代码存储在 SoC 的只读存储器(ROM) 中,由芯片厂商在生产时烧录,无法修改。
  • 主要作用:
    • 读取 eMMC、SPI Flash、SD 卡、NAND Flash 等存储设备的 引导扇区
    • 加载并执行 SPL(或 TPL)
    • 如果没有 SPL,它可能直接加载完整的 Bootloader(如 U-Boot)。

📌 在 i.MX6ULL 中,BootROM 负责加载 SPL(通常从 eMMC 的 0x400(即1KB) 偏移处开始读取SPL)


2️⃣ SPL(Secondary Program Loader)

  • SPL 是一个精简版的 Bootloader,主要任务是初始化 DDR(RAM),然后加载完整的 U-Boot。
  • SPL 代码精简,因为它通常运行在片上 SRAM(OCRAM)中,而 SRAM 只有几十 KB,无法容纳完整的 U-Boot。
  • 在 i.MX6ULL 上,SPL 可能会:
    • 初始化时钟、电源管理。
    • 初始化 eMMC/SD/NAND 以便加载完整的 U-Boot。
    • 把 U-Boot 从 eMMC 0x10000(64KB 处)加载到 DDR 并跳转执行

📌 在 i.MX6ULL 上,SPL 由 u-boot-spl.bin 生成,并包含在 u-boot.imx


3️⃣ U-Boot(完整 Bootloader)

  • U-Boot 是真正的 Bootloader,它运行在 DDR 内存中,提供完整的功能:
    • 初始化更多外设(串口、网卡、USB 等)。
    • 解析设备树(FDT)。
    • 读取内核镜像(zImage、Image)和 DTB 文件。
    • 加载 Linux 内核,并跳转执行。

📌 在 i.MX6ULL 上,U-Boot 通常存储在 eMMC 0x10000(64KB 处)并由 SPL 加载执行


完整的启动流程

1. BootROM(ROM 代码)
   └── 读取 eMMC/SD/NAND,引导 SPL
2. SPL(运行在 OCRAM)
   └── 初始化 RAM,加载 U-Boot
3. U-Boot(运行在 DDR)
   └── 读取 zImage/DTB,加载 Linux

小结

可以把 IMX6ULL运行Linux 的 Bootloader 分为三个部分

  1. BootROM(处理器内部 ROM)—— 负责加载 SPL。
  2. SPL(Secondary Program Loader)—— 负责初始化 RAM,并加载 U-Boot。
  3. U-Boot(完整 Bootloader)—— 负责加载 Linux 内核并启动系统。

🎯 在 i.MX6ULL 平台上,BootROM 先从 eMMC 0x400(1KB) 处加载 SPL,SPL 再加载 U-Boot(0x10000 处,即64KB 处),U-Boot 最终加载 Linux 内核。

SPL和U-Boot在镜像文件中是如何存储的?如何保证二者写到eMMC中后,是如何分别存储到指定的位置的?

从上面的叙述中,我们知道对于u-boot的源码而言,当执行下面的命令:

make -j4

后,得到了镜像文件u-boot-dtb.imx,从Bootloader的三个阶段来讲,这个镜像文件中包含着后两个阶段——SPL和U-Boot的代码。
SPL对应的二进制文件通常为u-boot-spl.bin,路径为spl/u-boot-spl.bin
U-Boot对应的二进制文件通常为u-boot.bin

也就是说镜像文件u-boot-dtb.imx是由二进制文件u-boot-spl.bin和二进制文件u-boot.bin合并而成的。

那么现在问题来了,当我们用烧写工具把镜像文件u-boot-dtb.imx烧写到eMMC时,按道理来说二者应该是连续存放的,因为它们拼接形成了镜像文件u-boot-dtb.imx呀,但事实上我们却发现二者并没有连续存放,SPL在eMMC中的起始位置是0x400(即1KB) 处,而U-Boot在eMMC中的起始位置是在0x10000(即64KB)处,二者中间还隔了一段存储空间,那这是怎么回事呢?

答案很简单:
在连接它们形成镜像文件的时候,中间是填充了占位数据的,占位数据通常是 0x00 或 0xFF。

具体说明如下:

1. 为什么会有填充数据?
在编译 u-boot.imx 时,SPL 和 U-Boot 的存放地址是预先确定的,比如:

  • SPL 从 0x400(1KB) 处开始存放。
  • U-Boot 需要存放在 0x10000(64KB) 处。

但 SPL 的大小通常不会刚好填满 0x400 ~ 0xFFFF 这段区域,而 U-Boot 也不能直接紧挨着 SPL 放置,因为启动流程会按照 固定偏移地址 读取 U-Boot。因此,编译时会自动在 u-boot.imx 里插入填充数据,使 U-Boot 仍然对齐到 0x10000 处


2. 填充数据是如何插入的?
填充数据是在镜像打包阶段加入的,U-Boot 的 imx-mkimage 工具或者 binman 工具会:

  • 计算 SPL 的大小
  • 计算 U-Boot 需要放置的偏移
  • 在两者之间插入 0x000xFF 作为填充

如果你用 hexdump 查看 u-boot.imx,你会看到:

hexdump -C u-boot.imx | less

可能的输出:

00000400  xx xx xx xx  xx xx xx xx  xx xx xx xx  xx xx xx xx  |XXXXXXXXXXXXXXXX|
...
0000ff00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  |................|
00010000  yy yy yy yy  yy yy yy yy  yy yy yy yy  yy yy yy yy  |YYYYYYYYYYYYYYYY|
  • xx xx xx xxSPL 代码
  • 00 00 00 00填充数据
  • yy yy yy yyU-Boot 代码

3. 烧录时,这些填充数据也会被写入 eMMC 吗?
是的,烧录会原封不动地写入 u-boot.imx 的所有内容,包括这些填充数据。例如下面这条在Linux下的烧录命令(dd命令):

dd if=u-boot.imx of=/dev/mmcblk0 bs=1K seek=1

运等,eMMC 里会按顺序存放:

eMMC 物理地址:
+------------+------------+---------------------+------------+
|  0x00400   |  SPL      | (填充区 0x00)       |  U-Boot    |
|  (1KB)     |  (~30KB)  | (占位到 64KB)       |  (完整)    |
+------------+------------+---------------------+------------+

这些填充数据对 eMMC 运行没有影响,因为 SPL 只会去 0x10000 处加载 U-Boot,而不会读取填充区。


4. 结论
如果 SPL 和 U-Boot 之间有空白区域,u-boot.imx 镜像文件会用 0x00 或 0xFF 进行填充,确保 U-Boot 位于正确偏移地址。
使用 dd 烧录时,填充数据也会被写入 eMMC,但不会影响运行
如果手动烧录 SPL 和 U-Boot,可以省略填充数据,直接写入相应偏移地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值