[uboot] (番外篇)global_data介绍

本文介绍了U-Boot中的global_data,用于在只读存储器运行时传递数据。内容包括global_data的功能、数据结构、存放位置及获取方式,详细讲解了其在内存中的布局和使用方法。

以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为例

[uboot] uboot流程系列
[project X] tiny210(s5pv210)上电启动流程(BL0-BL2)
[uboot] (第一章)uboot流程——概述
[uboot] (第二章)uboot流程——uboot-spl编译流程

===================================================================================

一、global_data功能

1、global_data存在的意义

在某些情况下,uboot是在某些只读存储器上运行,比如ROM、nor flash等等。
在uboot被重定向到RAM(可读可写)之前,我们都无法写入数据,更无法通过全局变量来传递数据。
而global_data则是为了解决这个问题。
这里顺便一下,后续的uboot的relocation操作,也就是uboot的重定向操作,最主要的目的也是为了解决这个问题,后续会专门说明。

2、 global_data简单介绍

global_data又称之为GD.
简单地说,uboot把global_data放在RAM区,并且使用global_data来存储全局数据。由此来解决上述场景中无法使用全局变量的问题。

二、global_data数据结构

1、数据结构说明

global_data数据结构结构体定义为struct global_data,被typedef为gd_t。
也就是说可以直接通过struct global_data或者gd_t来进行声明。
struct global_data定义如下(过滤掉一些被宏定义包含的部分):
include/asm-generic/global_data.h

typedef struct global_data {
    bd_t *bd;
    unsigned long flags;
    unsigned int baudrate;
    unsigned long cpu_clk;  /* CPU clock in Hz!     */
    unsigned long bus_clk;
    /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */
    unsigned long pci_clk;
    unsigned long mem_clk;
    unsigned long have_console; /* serial_init() was called */
    unsigned long env_addr; /* Address  of Environment struct */
    unsigned long env_valid;    
<think> 嗯,用户想了解U-Boot中initr_reloc_global_data的信息,包括用途、原理和实现。根据引用资料,这个函数属于init_sequence_r初始化序列,在重定位阶段后执行。用户可能正在研究U-Boot启动流程,或是调试重定位相关的问题。 从引用[1][2][3]看,initr_reloc_global_data的核心功能是修复全局数据指针gd。在重定位后,所有地址偏移量发生变化,而gd指针存储着关键数据结构的地址,必须更新才能正确访问。引用[3]提到它会重新计算gd地址并修复内部指针。 用户可能是嵌入式开发者,需要深入理解U-Boot初始化机制。考虑到ta直接询问具体函数而非整体流程,应该具备一定基础。需要强调这个函数在重定位后的必要性——比如未更新gd会导致后续initr_malloc等函数访问错误内存区域。 技术细节上要说明两点:一是gd本身地址的更新方式(当前地址减旧偏移量),二是gd->reloc_off字段的设置。后者很重要,因为后续如initr_malloc会依赖这个偏移量调整内存分配器的基地址。引用[5]的sync指令虽不直接相关,但可提及重定位后内存一致性保障。 最后补充注意事项:该函数通常无需手动调用,但若自定义重定位流程可能需要注意gd更新时机。用户如果遇到启动崩溃,可以检查gd->reloc_off值是否正确。 </think>在 U-Boot 启动流程中,`initr_reloc_global_data` 是一个关键函数,负责在代码重定位后更新全局数据结构 `gd`(global data)。以下是其详细说明: ### 一、作用与目的 1. **修复全局数据指针 (gd)**: - U-Boot 在重定位(从加载地址移动到链接地址)后,其自身代码和数据的地址发生变化。 - `gd` 是一个指向 `struct global_data` 的指针,存储着 U-Boot 运行时的核心状态(堆指针、环境变量地址、设备树地址、板级信息等)[^2][^3]。 - 重定位前,`gd` 指向的是 *重定位前* 地址空间的 `struct global_data` 实例。 - `initr_reloc_global_data` 的核心任务是将 `gd` 指针的值更新为指向 *重定位后* 地址空间中正确的 `struct global_data` 位置[^2][^3]。 2. **设置重定位偏移量**: - 函数会计算重定位的偏移量 `reloc_off`(通常是 `gd->relocaddr - gd->reloc_off` 的结果,其中 `gd->relocaddr` 是目标链接地址)。 - 将这个偏移量 `reloc_off` 存储在更新后的 `gd->reloc_off` 中[^2][^3]。 - 这个偏移量对于后续需要根据重定位调整自身指针的其他数据结构和函数至关重要。 ### 二、执行时机 - `initr_reloc_global_data` 是 `init_sequence_r[]` 函数指针数组中的一个成员[^1][^3][^5]。 - `init_sequence_r[]` 在 U-Boot 完成代码重定位(`relocate_code`)和向量表重定位(`relocate_vectors`)之后,由 `board_init_r` 函数调用执行[^2][^4]。 - 它在重定位后的板级初始化阶段 (`board_init_r`) 的早期被调用,通常在初始化堆(`initr_malloc`)之前[^1][^3]。这是为了确保后续所有依赖 `gd` 的操作(如内存分配)使用的是正确的地址。 ### 三、实现原理 (伪代码/逻辑) ```c static int initr_reloc_global_data(void) { /* 1. 计算重定位偏移量:目标地址 - 原始加载地址 */ gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; /* 或其他计算偏移的方式 */ /* 2. 关键步骤:更新 gd 指针本身 */ /* 将当前 gd 的值(指向旧地址的 gd)加上偏移量,得到新地址的 gd */ gd = (struct global_data *)((ulong)gd + gd->reloc_off); /* 3. 更新 gd 内部的指针成员(如果需要)*/ /* 例如,如果 gd->env_addr 指向环境变量,也需要调整: */ /* gd->env_addr += gd->reloc_off; */ /* 通常,重定位例程 (relocate_code) 可能已经处理了部分或全部 gd 内部指针的调整, 此处可能不需要再额外调整,但更新 gd 自身是必须的。*/ return 0; } ``` *关键点:* 函数通过将当前 `gd` 指针的值加上计算出的重定位偏移量 `gd->reloc_off`,使其指向重定位后内存中 `struct global_data` 结构体的新位置。修正后的 `gd` 指针和 `reloc_off` 值是后续初始化步骤正确工作的基础[^2][^3][^5]。 ### 四、重要性 - 如果 `gd` 指针没有在重定位后及时更新,后续所有通过 `gd` 访问 U-Boot 状态(如堆、环境变量、设备树、板信息)的操作都将访问到错误的(旧地址空间的)内存位置,导致 U-Boot 崩溃或行为异常。 - `gd->reloc_off` 为其他需要调整自身地址的数据结构或函数(如环境变量重定位、设备树重定位)提供了必要的偏移量信息。 ### 五、总结 `initr_reloc_global_data` 是 U-Boot 重定位后板级初始化 (`board_init_r` / `init_sequence_r`) 中的一个 **关键步骤**。它负责: 1. **修正全局数据指针 `gd`**,使其指向重定位后内存中的正确位置。 2. **计算并存储重定位偏移量 `gd->reloc_off`**,供后续初始化步骤使用。 它的正确执行确保了 U-Boot 在完成地址空间切换后,其核心状态数据结构 `gd` 可以被准确访问,是整个重定位后初始化流程得以顺利进行的前提[^1][^2][^3][^5]。 [^1]: 文章详细列出了`init_sequence_r`中的函数调用顺序,`initr_reloc_global_data`是其中重要的一环。 [^2]: 解释了重定位(`relocate_code`, `relocate_vectors`) 后`board_init_r`的执行流程,以及`initr_reloc_global_data`在此流程中更新全局数据指针`gd`的核心作用。 [^3]: 强调`initr_reloc_global_data`在重定位后对`gd`指针的修正,是后续`initr_malloc`等函数正确操作的基础。 [^5]: 在讨论`init_sequence_r`时提到内存同步指令`sync`,间接说明了重定位后更新关键数据(如`gd`)时确保内存一致性的重要性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值