首页 > 解决方案 > 为什么在 U-boot 中正确进行代码重定位?

问题描述

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

据我了解,ROM 代码首先执行,并将 MLO 文件从 MMC 加载到 SOC 的内部 SRAM 中。MLO 文件包含 x-loader 的代码,这是一个第二阶段程序加载器 (SPL)。然后 SPL 设置 DRAM 并将第三阶段 Program Loader(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 位于重置向量处(因此它首先运行),经过一些初始化后,它调用位于拱/臂/lib/crt0.S 。

在 crt0.S 中,board_init_f() 被调用,它设置 DRAM(和其他东西),然后返回到它离开的地方(在 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 并再次重新定位?我在这里错过了什么吗?

标签: beagleboneblackbootloaderu-bootomap

解决方案


如果这已经由 SPL 完成,为什么 U-boot 正确需要再次设置 DRAM 并再次重新定位?

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

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

我在这里错过了什么吗?

更方便的是把U-Boot加载到主存中间,然后让U-Boot自己重定位到高内存。


推荐阅读