uboot代码流程分析
331.3.4uboot代码流程分析
/* 课程源码版本:U-Boot 2016.03(NXP i.MX 下游版本)。 */
/* 以下仅收录视频实际定位并讲解的主线代码;各片段之间并非连续源码,未展示的条件编译、芯片勘误处理和初始化数组成员不擅自补入。 */
/* arch/arm/lib/vectors.S:ARM 异常向量表入口。 */
.globl _start /* 将 _start 导出为全局符号,链接器可以把它作为入口引用。 */
.section ".vectors", "ax" /* 把后续内容放入可分配、可执行的异常向量段。 */
_start: /* 定义 U-Boot 汇编入口 _start。 */
b reset /* 复位向量:无条件跳到 start.S 中的 reset;b 不保存返回地址。 */
ldr pc, _undefined_instruction /* 未定义指令异常:把处理入口装入 pc。 */
ldr pc, _software_interrupt /* 软件中断异常:跳到相应处理入口。 */
ldr pc, _prefetch_abort /* 指令预取异常:跳到相应处理入口。 */
ldr pc, _data_abort /* 数据访问异常:跳到相应处理入口。 */
ldr pc, _not_used /* 保留向量:跳到预设处理入口。 */
ldr pc, _irq /* IRQ 异常:跳到 IRQ 处理入口。 */
ldr pc, _fiq /* FIQ 异常:跳到 FIQ 处理入口。 */
/* arch/arm/cpu/armv7/start.S:reset 的视频重点片段。 */
.globl reset /* 导出 reset 符号,供复位向量跳转。 */
.globl save_boot_params_ret /* 导出保存启动参数后的返回标签。 */
reset: /* ARMv7 通用复位入口。 */
b save_boot_params /* 先让板级代码保存 ROM 传入的启动参数。 */
save_boot_params_ret: /* save_boot_params 执行后回到这里。 */
mrs r0, cpsr /* 读取当前程序状态寄存器 CPSR。 */
and r1, r0, #0x1f /* 取 CPSR 的处理器模式位。 */
teq r1, #0x1a /* 判断当前是否为 Hyp 模式。 */
bicne r0, r0, #0x1f /* 非 Hyp 模式时,先清除原模式位。 */
orrne r0, r0, #0x13 /* 非 Hyp 模式时,设置为 SVC32 模式。 */
orr r0, r0, #0xc0 /* 置 I、F 位,暂时屏蔽 IRQ 和 FIQ。 */
msr cpsr, r0 /* 把新状态写回 CPSR。 */
mrc p15, 0, r0, c1, c0, 0 /* 读取 CP15 系统控制寄存器。 */
bic r0, #CR_V /* 清除高向量位,选择低地址异常向量。 */
mcr p15, 0, r0, c1, c0, 0 /* 写回系统控制寄存器。 */
ldr r0, =_start /* 取 _start 地址。 */
mcr p15, 0, r0, c12, c0, 0 /* 写 VBAR,使异常向量基址指向 _start。 */
bl cpu_init_cp15 /* 调用 CP15 初始化;bl 会把返回地址保存到 lr。 */
bl cpu_init_crit /* 调用关键低级初始化。 */
bl _main /* 转入 crt0.S 的 _main,建立 C 运行环境。 */
/* arch/arm/cpu/armv7/start.S:cpu_init_cp15 的视频重点片段。 */
ENTRY(cpu_init_cp15) /* 声明 cpu_init_cp15 汇编函数入口。 */
mov r0, #0 /* 准备全零操作数。 */
mcr p15, 0, r0, c8, c7, 0 /* 失效指令与数据 TLB。 */
mcr p15, 0, r0, c7, c5, 0 /* 失效指令缓存。 */
mcr p15, 0, r0, c7, c5, 6 /* 失效分支预测器阵列。 */
mcr p15, 0, r0, c7, c10, 4 /* 执行数据同步屏障。 */
mcr p15, 0, r0, c7, c5, 4 /* 执行指令同步屏障。 */
mrc p15, 0, r0, c1, c0, 0 /* 读取系统控制寄存器 SCTLR。 */
bic r0, r0, #0x00002000 /* 清除 V 位,使用低地址异常向量。 */
bic r0, r0, #0x00000007 /* 清除 M、A、C 位:先关闭 MMU、对齐检查和数据缓存。 */
orr r0, r0, #0x00000002 /* 重新开启对齐检查 A 位。 */
orr r0, r0, #0x00000800 /* 开启分支预测 Z 位。 */
#ifdef CONFIG_SYS_ICACHE_OFF /* 若配置明确要求关闭指令缓存。 */
bic r0, r0, #0x00001000 /* 清除 I 位,关闭指令缓存。 */
#else /* 否则走此默认分支。 */
orr r0, r0, #0x00001000 /* 置 I 位,开启指令缓存。 */
#endif /* 结束指令缓存配置分支。 */
mcr p15, 0, r0, c1, c0, 0 /* 把新的控制值写回 SCTLR。 */
/* arch/arm/cpu/armv7/start.S:cpu_init_crit 的完整主体。 */
ENTRY(cpu_init_crit) /* 声明关键低级初始化入口。 */
b lowlevel_init /* 直接跳到 lowlevel_init,不在这里建立返回链。 */
ENDPROC(cpu_init_crit) /* 标记 cpu_init_crit 汇编过程结束。 */
/* arch/arm/cpu/armv7/lowlevel_init.S:视频讲解的早期初始化主线。 */
ENTRY(lowlevel_init) /* 声明 lowlevel_init 汇编函数入口。 */
ldr sp, =CONFIG_SYS_INIT_SP_ADDR /* 把配置的片上初始地址装入栈指针 sp。 */
bic sp, sp, #7 /* 将 sp 向下对齐到 8 字节边界。 */
push {ip, lr} /* 保存旧 lr(由 ip 传入)和当前 lr。 */
bl s_init /* 调用 SoC/板级最早期初始化。 */
pop {ip, pc} /* 恢复寄存器,并通过装入 pc 返回调用者。 */
ENDPROC(lowlevel_init) /* 标记 lowlevel_init 过程结束。 */
/* arch/arm/lib/crt0.S:_main 建立初始 C 环境并进入 board_init_f。 */
ENTRY(_main) /* 声明 _main 汇编入口;这不是 common/main.c 的 main_loop。 */
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /* 装入初始栈顶地址。 */
bic sp, sp, #7 /* 按 ARM ABI 要求做 8 字节对齐。 */
mov r0, sp /* 把当前栈指针作为参数放入 r0。 */
bl board_init_f_alloc_reserve /* 在初始栈区域预留早期 global_data 等空间。 */
mov sp, r0 /* 使用函数返回的新栈位置。 */
mov r9, r0 /* ARM32 约定用 r9 保存 global_data 指针 gd。 */
bl board_init_f_init_reserve /* 初始化刚预留的早期数据区。 */
mov r0, #0 /* 准备 board_init_f 的 boot_flags 参数 0。 */
bl board_init_f /* 进入重定位前的 C 初始化序列。 */
/* arch/arm/lib/crt0.S:_main 完成重定位、BSS 清零后转入 board_init_r。 */
mov r0, r9 /* 第一个参数传入新的 gd 指针。 */
ldr r1, [r9, #GD_RELOCADDR] /* 第二个参数传入 U-Boot 重定位目的地址。 */
ldr pc, =board_init_r /* 非 Thumb 构建中直接转到 board_init_r;它不应返回。 */
ENDPROC(_main) /* 标记 _main 汇编过程结束。 */
/* common/board_f.c:视频定位到的 board_init_f 核心。 */
void board_init_f(ulong boot_flags) /* 重定位前的板级通用初始化入口。 */
{ /* 函数体开始。 */
gd->flags = boot_flags; /* 保存启动标志。 */
gd->have_console = 0; /* 标记完整控制台尚未就绪。 */
if (initcall_run_list(init_sequence_f)) /* 按顺序运行 init_sequence_f,非零表示某一步失败。 */
hang(); /* 初始化失败时停止继续启动。 */
} /* board_init_f 结束。 */
/* common/board_r.c:init_sequence_r 的末项及 board_init_r 核心。 */
run_main_loop, /* 重定位后初始化数组的最后一步:进入永久命令主循环。 */
void board_init_r(gd_t *new_gd, ulong dest_addr) /* 重定位后的板级通用初始化入口。 */
{ /* 函数体开始。 */
if (initcall_run_list(init_sequence_r)) /* 按顺序执行重定位后的初始化函数数组。 */
hang(); /* 任一初始化函数返回非零时停止。 */
hang(); /* 正常情况下 run_main_loop 不返回;若意外返回则停止。 */
} /* board_init_r 结束。 */
/* common/main.c:视频框出的命令处理主线。 */
void main_loop(void) /* U-Boot 初始化完成后的命令处理入口。 */
{ /* 函数体开始。 */
const char *s; /* 保存经环境变量选择后的自动启动命令字符串。 */
cli_init(); /* 初始化命令行解释器。 */
run_preboot_environment_command(); /* 若配置了 preboot,则先执行它。 */
s = bootdelay_process(); /* 读取并处理启动延时,返回待执行的 bootcmd。 */
if (cli_process_fdt(&s)) /* 若设备树提供了安全启动命令,则进行相应处理。 */
cli_secure_boot_cmd(s); /* 在安全模式下执行该命令;通常不会返回。 */
autoboot_command(s); /* 倒计时未被打断时执行自动启动命令。 */
cli_loop(); /* 自动启动被打断或命令返回后,进入交互式命令循环。 */
} /* main_loop 结束。 */
本节沿着课程视频实际打开的七个文件,追踪 U-Boot 从 ARM 异常向量入口到交互式命令行的主干流程。课程压缩包中的源码顶层版本号为 U-Boot 2016.03;本文的文件名、函数名和行号语义均以该版本为准,其他版本可能已有调整。
主调用链可以先压缩成一行:
_start → reset → cpu_init_cp15 → cpu_init_crit → lowlevel_init → s_init → _main → board_init_f → 重定位并清零 BSS → board_init_r → run_main_loop → main_loop → 自动启动或 cli_loop
其中,b 是不保存返回地址的直接分支,bl 是会把返回地址写入链接寄存器 lr 的函数调用式分支。因此,阅读汇编流程时不能把所有跳转都理解成普通 C 函数调用。该区别可参见 Arm 官方对 Branch 与 Branch with Link 的说明。
一、uboot源码简要分析
U-Boot 是可移植的通用引导程序,同一套源码覆盖多种处理器、SoC 和开发板。真正参与本次 i.MX6ULL 构建的代码由板级配置和大量 CONFIG_* 条件宏共同决定,所以“在源码树中找到某个函数”不等于“该函数的所有分支都会被当前开发板编译执行”。
还要注意:_start 是 U-Boot 镜像自身的入口,并不是芯片上电后执行的第一条代码。i.MX6ULL 上电后先执行片内 Boot ROM;Boot ROM 完成启动介质判断、镜像装载等工作后,才把控制权交给 U-Boot。这与上一节的 Boot ROM → U-Boot → Linux 启动层次相衔接。
1.1 任务信息资源导图
课程中的操作方式是:在 Ubuntu 虚拟机中保留已经编译过的 U-Boot 源码,通过 Samba 共享目录让 Windows 侧的 VS Code 打开代码,再借助符号跳转追踪调用关系。“Samba”只是跨系统访问文件的方式,不参与 U-Boot 编译或启动。
本节七个文件及其职责如下:
| 顺序 | 课程源码路径 | 主要职责 |
|---|---|---|
| 1 | arch/arm/lib/vectors.S | 定义 _start 和 ARM 异常向量表 |
| 2 | arch/arm/cpu/armv7/start.S | ARMv7 复位入口、处理器状态与 CP15 早期设置 |
| 3 | arch/arm/cpu/armv7/lowlevel_init.S | 建立临时栈并调用 s_init() |
| 4 | arch/arm/lib/crt0.S | 建立 C 运行环境、组织重定位并衔接前后两阶段初始化 |
| 5 | common/board_f.c | 执行重定位前的 init_sequence_f[] |
| 6 | common/board_r.c | 执行重定位后的 init_sequence_r[] |
| 7 | common/main.c | 处理自动启动倒计时并进入命令解释器 |
源码扩展名应写作大写 .S。大写 .S 通常表示该汇编文件在汇编前还要经过 C 预处理器,因此文件中可以使用 #ifdef、配置宏和头文件;这也是本节源码里条件编译很多的原因。
1.2 uboot源码
阅读这条启动链时,可以把它分为四层:
- 纯汇编入口:异常向量、处理器模式、CP15、临时栈。
- C 环境建立:准备
sp和gd,调用board_init_f()。 - 重定位前后初始化:先运行
init_sequence_f[],再重定位代码、清零 BSS,随后运行init_sequence_r[]。 - 命令处理:根据
bootdelay决定执行bootcmd,或进入=>交互命令行。
U-Boot 官方初始化流程文档也将通用 ARM 路径概括为 start.S、低级初始化、board_init_f()、重定位、board_init_r() 和主循环几个阶段。
1.2.1 vectors.s
实际文件名是 arch/arm/lib/vectors.S。文件中的 .vectors 段保存异常向量表,_start 是这一段的入口。复位发生时,处理器从复位向量取指,第一项 b reset 把控制权交给 start.S。
后续七项并不是普通变量:ldr pc, ... 会改写程序计数器 pc,从而跳往未定义指令、软件中断、预取异常、数据异常、IRQ、FIQ 等处理入口。
视频定位的是课程版本第 48 行附近的 _start,而第 54 行是 b reset。行号只用于帮助回看本版本源码,不应当当作跨版本固定接口。
1.2.2 cpu/armv7/start.s
实际路径为 arch/arm/cpu/armv7/start.S。reset 的主干工作是:
- 先调用板级
save_boot_params保存 Boot ROM 传入的启动信息; - 在不是 Hyp 模式时切换到 32 位 SVC 模式;
- 屏蔽 IRQ 和 FIQ,避免基础运行环境尚未建立时被中断打断;
- 配置低地址异常向量,并让 VBAR 指向
_start; - 依次调用
cpu_init_cp15、cpu_init_crit和_main。
这里的 SVC 是 ARM 的特权模式之一。屏蔽中断只是早期启动阶段的临时措施,不表示 U-Boot 运行期间永远不使用中断。
1.2.3 cpu_init_cp15
CP15 是 ARMv7-A 的系统控制协处理器接口。课程把这一段概括为“关闭 MMU 和 Cache”,但源码需要更精确地读:
bic ... #0x7先清除 SCTLR 的 M、A、C 位,即关闭 MMU、对齐检查和数据缓存;- 随后代码又置位 A,重新开启对齐检查;
- 代码还开启分支预测;
- 指令缓存是否关闭取决于
CONFIG_SYS_ICACHE_OFF。默认的#else分支会开启 I-Cache,而不是关闭全部缓存。
函数中还有视频未展开的 CPU 勘误处理分支。它们属于当前源码真实内容,但不应脱离具体芯片配置笼统解释为每次都会执行。
1.2.4 cpu_init_crit
cpu_init_crit 的主体只有一条 b lowlevel_init。这里使用 b 而不是 bl,意味着它把 lowlevel_init 当成尾跳转:lowlevel_init 最终恢复的返回地址仍然回到更早调用 cpu_init_crit 的位置,而不是回到这条 b 的下一行。
源码行尾旧注释写有设置 PLL、MUX、Memory,但通用 cpu_init_crit 本身没有逐项做这些事;实际工作要继续看 lowlevel_init、s_init 以及当前 SoC/开发板启用的实现,不能仅凭注释断定。
1.2.5 lowlevel_init.s
实际路径为 arch/arm/cpu/armv7/lowlevel_init.S。它先把 CONFIG_SYS_INIT_SP_ADDR 写入栈指针 sp,按 8 字节对齐;部分配置还会从栈中为早期 global_data 预留空间。这里建立的是临时栈和早期全局数据区,不是堆。
push {ip, lr} 保存返回现场,bl s_init 调用最早期 SoC/板级初始化,随后 pop {ip, pc} 恢复现场并返回。源码注释严格限制 s_init():它不应在此设置 DRAM、不应依赖完整 global_data、不应清零 BSS,也不应启动控制台,因为这些运行条件尚未准备好。
课程口述把 s_init() 简化成“空函数”。对当前 i.MX6ULL 路径而言,arch/arm/cpu/armv7/mx6/soc.c 中的实现检测到 MXC_CPU_MX6ULL 后立即 return,所以运行效果近似空操作;但函数源码本身并非空函数,对其他 i.MX6 型号还包含额外处理。这个边界不能省略。
1.2.6 bl_main
本小节标题沿用原笔记,但源码指令实际是 bl _main,并不存在名为 bl_main 的函数。bl 是指令,_main 才是符号名。
_main 位于 arch/arm/lib/crt0.S,承担从早期汇编环境过渡到 C 代码的枢纽工作:
- 建立并按 ABI 对齐初始栈;
- 预留并初始化早期
global_data,ARM32 用r9保存gd指针; - 以参数 0 调用
board_init_f(); - 根据
board_init_f()计算的地址切换新栈和新gd,重定位 U-Boot; - 重定位异常向量,完成 CPU 运行环境设置并清零 BSS;
- 把
gd与重定位地址作为参数转入board_init_r()。
global_data 用于在普通全局变量尚不可安全使用的早期阶段保存启动状态;ARM32 使用 r9 保存其指针是 U-Boot 的体系结构约定,参见 U-Boot 官方 global data 文档。
1.2.7 board_init_f
board_init_f() 位于 common/board_f.c。后缀 f 可帮助记忆为重定位前(before relocation)的阶段,但它不是语言层面的关键字。
函数将启动标志写入 gd,把“完整控制台已就绪”标志清零,然后调用:
initcall_run_list(init_sequence_f)
init_sequence_f[] 是以 NULL 结束的初始化函数指针数组。initcall_run_list() 按顺序调用每个成员;任一成员返回非零,board_init_f() 就调用 hang() 停止启动。数组内容受配置影响,课程版本中可包含早期 CPU/定时器/串口准备、DRAM 容量探测、为重定位和运行数据预留地址等步骤。
board_init_f() 本身不直接调用 board_init_r()。在 ARM 主线中,它返回 _main,由 crt0.S 完成重定位、向量调整和 BSS 清零后,再转入 board_init_r()。U-Boot Generic Board 文档同样把 common/board_f.c 和 common/board_r.c 区分为重定位前、后的两个阶段。
1.2.8 board_init_r
board_init_r() 位于 common/board_r.c,负责重定位后的完整初始化。它用 initcall_run_list(init_sequence_r) 运行第二个函数数组;按配置不同,其中会逐步初始化缓存、内存分配器、环境变量、完整控制台、存储设备、网络等子系统。
课程版本中 init_sequence_r[] 从第 868 行附近开始,到第 1084 行结束;原识别结果中的“1804 行”是 OCR 错误。数组末项为 run_main_loop。这个包装函数以无限循环反复调用 main_loop(),因此正常路径不会回到 board_init_r();末尾的 hang() 只是处理异常返回。
1.2.9 main.c
main_loop() 位于 common/main.c。课程重点标出了三处:
- 第 68 行
s = bootdelay_process();:读取并处理bootdelay,选择待执行的自动启动命令bootcmd,将命令字符串返回给s;它不只是泛泛地“读取环境变量”。 - 第 72 行
autoboot_command(s);:显示并处理自动启动倒计时。若用户没有中断,才执行s指向的命令。在本开发板环境中,bootcmd通常继续加载内核和设备树并启动 Linux,但这个函数本身并不等同于“启动内核”。 - 第 74 行
cli_loop();:自动启动被打断,或自动命令失败、执行完后返回时,进入 U-Boot 交互式命令循环。
因此,正常自动启动成功后,内核接管 CPU,autoboot_command() 通常不会返回到 cli_loop();只有启动被打断或未成功转交时,用户才会看到 => 提示符。
1.2.10 实践操作
视频使用开发板自带的 CH340 USB 转串口芯片,Windows 中识别为 COM10。COM10 只是当时电脑分配的端口号,换电脑或 USB 插口后可能变化,应以设备管理器实际显示为准。
串口终端参数设置为:
| 参数 | 值 |
|---|---|
| 波特率 | 115200 |
| 数据位 | 8 |
| 停止位 | 1 |
| 校验位 | None |
| 流控 | None |
建议先打开终端再给开发板上电,这样才能看到最早期日志。若另接 USB-TTL 模块,应使用开发板允许的 3.3 V TTL 电平、共地,并让 TX/RX 交叉连接;不能把 RS-232 电平直接接入 SoC 串口。课程使用板载 CH340 时,按开发板接口定义连接 USB 即可。
二、U-Boot
2.1 断电重启
视频第一次上电没有按键,倒计时结束后 U-Boot 按环境变量继续读取 zImage 和 topeet_emmc_hdmi.dtb,随后出现 Starting kernel ...,说明控制权开始移交 Linux。
要进入 U-Boot 交互模式,可按以下顺序操作:
- 关闭开发板电源。
- 确认串口终端已连接并使用
115200 8N1。 - 重新上电,观察启动日志。
- 出现
Hit any key to stop autoboot倒计时时按任意键。 - 看到
=>提示符后再输入命令。
不必限定按 Enter;普通按键也可中断。按键必须发生在倒计时窗口内,过早可能尚未启用串口输入,过晚则自动启动命令已经执行。
2.2 U-Boot模式
本节所说的两种“模式”实质是同一套 main_loop() 的两条控制路径:
| 路径 | 条件 | 结果 |
|---|---|---|
| 自动启动 | 倒计时内未检测到中断按键 | autoboot_command() 执行 bootcmd,通常加载 Linux |
| 交互命令行 | 倒计时被按键打断,或自动命令返回 | cli_loop() 接管,显示 => 并等待命令 |
倒计时长度由 bootdelay 环境变量控制。视频环境中 printenv 显示 bootdelay=3,因此提示从 3 秒开始。若环境变量、编译配置或安全启动策略不同,实际行为也会不同。
2.2.1 断电重启
进入 => 后,视频实际输入的命令是:
printenv
它会打印全部 U-Boot 环境变量。视频可见的关键项包括 baudrate=115200、bootdelay=3、较长的 bootcmd=...,以及 fdt_file=topeet_emmc_hdmi.dtb。原 OCR 将命令识别为多个无意义单词,正确拼写是一个完整的 printenv。
若只想核对本节相关值,更清晰的只读命令是:
printenv bootdelay bootcmd baudrate fdt_file
在较新的命令说明中,printenv 是 env print 的兼容别名,参见 U-Boot 官方 env 命令文档。printenv 只读取环境;setenv 会修改内存中的环境副本,而 saveenv 会把环境持久化到存储介质。未确认启动配置前不要随意执行 saveenv,否则可能改变下次开机行为。
2.3 U-Boot源码分析
把串口现象反向映射到代码,可以得到下面的闭环:
_start和reset完成汇编入口与处理器早期状态设置。lowlevel_init准备临时栈,当前 i.MX6ULL 的s_init()很快返回。_main建立 C 环境并调用board_init_f()。init_sequence_f[]完成重定位前准备,_main随后重定位 U-Boot、清零 BSS。board_init_r()运行init_sequence_r[],其末项进入run_main_loop()。main_loop()取得bootdelay和bootcmd;未按键就执行自动命令,按键中断则落入cli_loop()。cli_loop()显示=>,用户输入printenv后由命令解析器查找并执行对应命令。
这也解释了为何串口日志和源码能够一一对应:Hit any key to stop autoboot 来自自动启动判断,=> 来自命令行循环,而 printenv 输出的是 U-Boot 自己维护的环境数据,并非 Linux Shell 的环境变量。
需要注意,能中断倒计时并不等同于经过身份认证。量产设备若暴露可写的 U-Boot 控制台,攻击者可能改变启动参数或读取存储内容;是否禁用交互、保护环境、启用验证启动,应根据产品安全需求另行设计。
三、课程总结
本节完成了 U-Boot 主干源码的第一次端到端追踪:
vectors.S的_start通过复位向量跳到reset;start.S建立 ARMv7 早期状态,并进入低级初始化与_main;lowlevel_init.S建立临时栈,调用受严格限制的s_init();crt0.S的_main串起board_init_f()、重定位、BSS 清零和board_init_r();board_f.c与board_r.c分别执行重定位前后的初始化函数数组;main.c根据bootdelay在自动执行bootcmd与进入cli_loop()之间分流;- 串口中断倒计时并执行
printenv,验证了源码控制流与真实启动现象。
本节最重要的阅读方法不是死记行号,而是抓住“入口—早期汇编—C 环境—重定位前初始化—重定位后初始化—命令循环”这条骨架,再结合当前开发板配置判断条件编译的真实路径。后续分析编译脚本或板级配置时,也应继续回到这个骨架上定位它影响的是哪一个阶段。
校核依据:课程视频与随课 U-Boot 2016.03 源码;U-Boot Board Initialisation Flow、U-Boot Generic Board、U-Boot Global data、U-Boot environment commands及 Arm Branch and Call Sequences。