为什么代码重定位在 U-boot 中完成?

Why is code relocation done in U-boot proper?

我试图通过浏览源代码来了解 BeagleBone Black 的启动过程。假设我将 MLO 和 u-boot.img 文件保存在 micro-SD 卡中,并使 BeagleBone 从 SD 卡启动。

据我了解,ROM 代码首先执行,它将 MLO 文件从 MMC 加载到 SOC 的内部 SRAM 中。 MLO 文件包含 x-loader 的代码,这是一个第二阶段程序加载器 (SPL)。然后 SPL 设置 DRAM 并将第三阶段程序加载器(U-boot 本身)复制到 DRAM 中。 U-boot本身直接从DRAM开始执行。

U-boot 本身的体系结构相关部分位于 U-boot 源的 arch/arm/ 目录中。 与 SPL 有关的代码位于 spl/ 目录中。(在执行 make mrproper 和 make SPL 时,*.o 文件仅在 spl/ 目录中创建)

对于 U-boot 本身,我猜这是执行流程 - arch/arm/cpu/armv7/start.S 位于重置向量(因此它首先运行),并且在一些初始化之后它调用位于 arch/arm/ 的'_main'过程库/crt0.S .

在 crt0.S 中,调用 board_init_f(),它设置 DRAM(和其他东西),然后 returns 回到它停止的地方(在 main_ ).它稍后调用函数 relocate_code 再次将其重新定位到 DRAM。

ENTRY(_main)

/*
 * Set up initial C runtime environment and call board_init_f(0).
 */

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
        ldr     r0, =(CONFIG_SPL_STACK)
#else
        ldr     r0, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
        bic     r0, r0, #7      /* 8-byte alignment for ABI compliance */
        mov     sp, r0
        bl      board_init_f_alloc_reserve
        mov     sp, r0
        /* set up gd here, outside any C code */
        mov     r9, r0
        bl      board_init_f_init_reserve

        mov     r0, #0
        bl      board_init_f

#if ! defined(CONFIG_SPL_BUILD)

/*
 * Set up intermediate environment (new sp and gd) and call
 * relocate_code(addr_moni). Trick here is that we'll return
 * 'here' but relocated.
 */

        ldr     r0, [r9, #GD_START_ADDR_SP]     /* sp = gd->start_addr_sp */
        bic     r0, r0, #7      /* 8-byte alignment for ABI compliance */
        mov     sp, r0
        ldr     r9, [r9, #GD_BD]                /* r9 = gd->bd */
        sub     r9, r9, #GD_SIZE                /* new GD is below bd */

        adr     lr, here
        ldr     r0, [r9, #GD_RELOC_OFF]         /* r0 = gd->reloc_off */
        add     lr, lr, r0
#if defined(CONFIG_CPU_V7M)
        orr     lr, #1                          /* As required by Thumb-only */
#endif
        ldr     r0, [r9, #GD_RELOCADDR]         /* r0 = gd->relocaddr */
        b       relocate_code
here:

如果 SPL 已经完成,为什么 U-boot 本身需要重新设置 DRAM 并重新定位?我在这里遗漏了什么吗?

Why U-boot proper needs to setup DRAM again and relocate itself again if this was already done by SPL?

重定位到内存顶部是为了最大化连续空闲space。
您可以 build/link 并在这个高端内存地址加载 U-Boot(以保存在副本上)。但是每当你用添加的功能重建 U-Boot 并且图像变大时,就必须重新计算加载地址。
这也意味着必须更改 SPL。

顺便说一句 "setup DRAM" 通常会被认为是初始化 DRAM 控制器,在这个阶段还没有完成。
除了重新定位其代码,U-Boot 还必须移动堆栈和堆,即 C 运行时环境。

Am i missing something here?

把U-Boot加载到主存中间,然后让U-Boot自己重新定位到高端内存,这样比较方便。