ARM 架构上的 u-boot 重定位
以下是两阶段启动过程的整个顺序:
- ROM 代码读取 SPL(来自
MLO
SD 卡上的文件)CONFIG_SPL_TEXT_BASE
地址。该地址通常位于 SRAM 中,无需初始化即可使用(与 RAM 不同)。 ROM 代码跳转到 SPL 代码。
- SPL配置RAM,然后读取u-boot(来自
u-boot.img
SD 卡上的文件)CONFIG_SYS_TEXT_BASE
RAM 地址(通常位于 RAM 的开头)并运行它
- u-boot 将自身重新定位到
gd->relocaddr
RAM 地址(通常位于 RAM 的末尾)并跳转到重定位的代码
- 现在我们准备启动内核了
对于单阶段启动,您没有 SPL,通常只有u-boot.bin
文件被使用。在这种情况下,您只需执行步骤 3 和 4。
关于搬迁有两种情况(如doc/README.arm-重定位 http://git.denx.de/?p=u-boot.git;a=blob;f=doc/README.arm-relocation;h=645b3746c8a88fe25f7c9a33cd9b8b17aa7b5a57;hb=HEAD):
-
CONFIG_SYS_TEXT_BASE != gd->relocaddr
: 将进行搬迁
-
CONFIG_SYS_TEXT_BASE == gd->relocaddr
: 不会进行搬迁
在您的情况下,您会看到执行了重定位(如CONFIG_SYS_TEXT_BASE != gd->relocaddr
).
那么,解决你的问题:
为什么 U-Boot 需要这两个偏移量?
搬迁背后的原因描述于u-boot ARM重定位任务 http://www.denx.de/wiki/U-Boot/TaskAddArmRelocation:
...我们可以测量板上内存的实际大小,然后将 U-Boot 重新定位到 RAM 的最末端,使几乎整个 RAM 都可用作“应用程序”的一大连续区域,例如加载 Linux 内核、ramdisk 等。
事实上,如果你查看代码,你会发现gd->relocaddr
是 RAM 的末尾减去监控代码 (U-Boot) 的大小:
gd->relocaddr = gd->ram_top;
...
gd->relocaddr -= gd->mon_len;
还可以执行一些额外的内存保留。例如,在我的平台 (TI DRA7XX EVM) 上,我可以看到调用的下一个函数:
setup_dest_addr()
reserve_round_4k()
reserve_mmu()
reserve_uboot()
实际搬迁是在之后完成的board_init_f()
call.
拱/臂/lib/crt0.S:
bl board_init_f
...
b relocate_code
arch/arm/lib/relocate.S:
ENTRY(relocate_code)
现在很容易回答您的下一个问题:
U-Boot 的实际内存占用是多少?
搬迁之前,U-Boot 驻留在CONFIG_SYS_TEXT_BASE
。搬迁后U-Boot驻留在gs->relocaddr
.
关于你的最后一个问题:
我可以将内核放在哪里以确保它不会覆盖某些内容?
由于 U-Boot 被重新定位到 RAM 的末尾,理论上您可以使用任何 RAM 地址来放置内核。但看看CONFIG_EXTRA_ENV_SETTINGS
定义在include/configs/zynq-common.h
:
"sdboot=if mmcinfo; then " \
"run uenvboot; " \
"echo Copying Linux from SD to RAM... && " \
"load mmc 0 ${kernel_load_address} ${kernel_image} && " \
"load mmc 0 ${devicetree_load_address} ${devicetree_image} && " \
"load mmc 0 ${ramdisk_load_address} ${ramdisk_image} && " \
"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; " \
"fi\0" \
从那里你可以看到你应该加载内核到${kernel_load_address}
,即0x2080000
:
"kernel_load_address=0x2080000\0" \
有关其他常量,请参阅该定义的其余部分。
bdinfo命令
你可以找到bdinfo
命令有用:可以使用以下命令找到重定位地址以及其他有用信息bdinfo
来自 U-Boot shell 的命令。例如对于 DRA7XX EVM:
=> bdinfo
DRAM bank = 0x00000000
-> start = 0x80000000
-> size = 0x60000000
TLB addr = 0xDFFF0000
relocaddr = 0xDFF5D000
reloc off = 0x5F75D000
irq_sp = 0xDEF3CEE0
sp start = 0xDEF3CED0
从这里你可以看到:
- 内存开始于
0x80000000
- 内存大小是
0x60000000
- ...所以RAM结束(
gd->ram_top
) is 0x80000000 + 0x60000000 = 0xE0000000
- 搬迁地址是
0xDFF5D000
- 用于重定位的保留内存是
0xE0000000 - 0xDFF5D000 = 652 KB
- 监视器(U-Boot)大小约为
TLB addr - relocaddr = 0xDFFF0000 - 0xDFF5D000 = 588 KB
也可以看看:
[1] u-boot:搬迁 https://stackoverflow.com/questions/16719986/u-boot-relocation
[2] SPL(辅助程序加载器)有什么用 https://stackoverflow.com/questions/31244862/what-is-the-use-of-spl-secondary-program-loader/31252989#31252989
[3] 为 u-boot 添加 ARM 重定位支持的提交 http://git.denx.de/?p=u-boot.git;a=commit;h=f1d2b313c9eb6808d30c16a9eb5251240452a56c