ATF 热启动(Warm Boot)全流程
热启动(Warm Reset)是指系统已完成冷启动并运行后,通过软件或硬件触发的复位流程。与冷启动相比,热启动的核心特点是保留 DRAM 内容,跳过耗时的 DRAM 初始化(训练),从而大幅缩短启动时间。
DRAM 训练(也叫 DDR 训练),是DDR 内存控制器在冷启动初始化阶段,通过一系列硬件校准算法,动态调整内存信号的时序、相位、电压、驱动强度等关键参数,确保 CPU 与 DRAM 颗粒之间的高速并行数据传输稳定、无错的硬件校准过程。
一、热启动概述
1. 与冷启动的核心差异
| 维度 | 冷启动(Cold Boot) | 热启动(Warm Boot) |
|---|---|---|
| 触发条件 | 系统上电、硬复位 | 软件触发(PSCI)、看门狗复位、软复位按钮 |
| DRAM 状态 | 未初始化,需完整训练(Training) | 已初始化,内容保留,跳过训练 |
| 镜像加载 | 从 Flash 重新加载 BL1/BL2/BL31/BL32/BL33 | 可选:若内存内容保留,可跳过部分镜像重加载 |
| 启动时间 | 长(需 DRAM 训练) | 短(跳过 DRAM 训练) |
2. 常见触发方式
- 软件触发 :
- Linux/Android 通过 PSCI(Power State Coordination Interface)调用
SYSTEM_RESET或SYSTEM_RESET2 - 直接写平台的复位控制寄存器
- Linux/Android 通过 PSCI(Power State Coordination Interface)调用
- 硬件触发 :
- 看门狗定时器超时(Watchdog Reset)
- 软复位按钮(保留 DRAM 电源)
- 调试器触发复位
二、ATF 热启动全流程
ATF 热启动仍遵循"BL1 → BL2 → BL31 → BL32/BL33"的基本链路,但在各阶段会根据复位原因跳过冗余步骤。
第一阶段:复位触发与 BL1 处理
1.1 复位入口
系统复位后,CPU 强制进入 EL3(AArch64) 或 Secure Monitor Mode(AArch32) ,从 BL1 ROM 的固定入口地址开始执行(与冷启动一致)。
1.2 BL1 核心逻辑
BL1 会先完成最小化硬件初始化 (如关中断、初始化 SRAM、UART),然后通过平台复位状态寄存器判断复位原因(冷启动/热启动)。
核心代码(BL1)
-
文件 :
bl1\bl1_main.c -
关键函数 :
bl1_main()cvoid bl1_main(void) { unsigned int image_id; // 存储下一个要加载的镜像ID /* 如果启用EARLY_CONSOLE标志,则启用早期控制台 */ plat_setup_early_console(); /* 执行早期平台特定设置 */ bl1_early_platform_setup(); /* 执行晚期平台特定设置 */ bl1_plat_arch_setup(); // 2. 获取复位原因(平台相关代码) uint32_t reset_status = bl1_plat_get_reset_status(); // 3. 若为热启动,可选择跳过部分 BL1 初始化(平台自定义) if (reset_status == WARM_RESET) { // 可选:跳过某些非必要初始化 } // 4. 加载并验签 BL2(与冷启动一致,热启动通常仍需走 BL2) bl1_load_bl2(); // 5. 准备跳转参数,跳转到 BL2 bl1_prepare_next_image(); } -
复位原因检测(平台相关):
-
文件 :
plat/<厂商>/<平台>/<平台>_pm.c(如plat/arm/board/fvp/fvp_pm.c) -
关键函数 :
bl1_plat_get_reset_status()或plat_get_reset_status()c// 示例:FVP 平台获取复位状态 uint32_t fvp_get_reset_status(void) { return mmio_read_32(FVP_RESET_STATUS_REG) & FVP_WARM_RESET_FLAG; }
-
第二阶段:BL2 处理(热启动核心优化点)
BL2 是热启动优化的核心阶段 ------热启动时 DRAM 已初始化且内容保留,BL2 会跳过 DRAM 训练(Training),仅需验证/加载后续镜像(或直接使用内存中已有的镜像)。
2.1 BL2 核心逻辑
- 基础初始化:初始化 UART、存储控制器(若需从 Flash 读镜像)。
- DRAM 状态检测:通过平台寄存器或内存魔数(Magic Number)判断 DRAM 是否已初始化。
- 跳过 DRAM 初始化:若为热启动,直接使用现有 DRAM,不执行耗时的训练流程。
- 镜像处理 :
- 若内存中 BL31/BL32/BL33 镜像完整(通过校验和/魔数验证),则跳过从 Flash 重加载;
- 否则,仍需从 Flash 重新加载并验签。
- 准备跳转参数:将 BL31/BL32/BL33 的入口地址传递给 BL31。
- 跳转到 BL31。
核心代码(BL2)
-
文件 :
bl2/bl2_main.c -
关键函数 :
bl2_main()cvoid bl2_main(void) { // 1. 基础初始化 bl2_early_platform_setup2(); bl2_plat_arch_setup(); // 2. 检测 DRAM 状态(平台相关) bool dram_is_ready = bl2_plat_is_dram_ready(); // 3. 仅冷启动时初始化 DRAM if (!dram_is_ready) { // 执行 DRAM 训练(耗时步骤,热启动跳过) bl2_plat_dram_init(); } // 4. 加载/验签 BL31/BL32/BL33(热启动可优化为跳过) bl2_load_images(); // 5. 准备跳转参数,跳转到 BL31 bl2_prepare_next_image(); } -
DRAM 状态检测(平台相关):
-
文件 :
plat/<厂商>/<平台>/<平台>_bl2_setup.c -
关键函数 :
bl2_plat_is_dram_ready()c// 示例:通过内存魔数判断 DRAM 是否保留 #define DRAM_MAGIC 0x12345678 bool bl2_plat_is_dram_ready(void) { // 检查 DRAM 特定地址的魔数是否匹配 return mmio_read_32(DRAM_MAGIC_ADDR) == DRAM_MAGIC; }
-
第三阶段:BL31 处理(热启动与 PSCI 联动)
BL31 是热启动的控制枢纽,负责:
- 初始化 EL3 运行时环境;
- 处理 PSCI 热启动请求(如
CPU_ON、SYSTEM_RESET); - 协调安全世界(OP-TEE)与非安全世界(Linux/Android)的状态恢复。
3.1 BL31 核心逻辑
- EL3 基础初始化:初始化栈、异常向量表、GIC 中断控制器。
- PSCI 服务初始化:注册 PSCI 处理函数,支持热启动相关的标准接口。
- 安全世界状态处理 :
- 若 OP-TEE(BL32)仍在内存中,可跳过 OP-TEE 重初始化,直接恢复其上下文;
- 否则,仍需跳转到 OP-TEE 重新初始化。
- 切换到非安全世界 :配置非安全世界上下文,通过
ERET跳转到 BL33(LK/U-Boot)。
3.2 PSCI 热启动关键接口
PSCI 是软件触发热启动的标准接口,Linux/Android 通过 SMC 调用以下 PSCI 函数:
PSCI_VERSION:获取 PSCI 版本;SYSTEM_RESET/SYSTEM_RESET2:触发系统热复位;CPU_ON:热启动指定的 CPU 核心(多核系统)。
核心代码(BL31 与 PSCI)
-
PSCI 系统复位处理:
- 文件 :
lib\psci\psci_system_off.c - 关键函数 :
psci_system_reset()

- 文件 :
-
PSCI CPU 热启动处理:
-
文件 :
lib\psci\psci_on.c -
关键函数 :
psci_cpu_on_start()cint psci_cpu_on_start(u_register_t target_cpu, u_register_t entry_point) { // 1. 验证目标 CPU 状态 if (!psci_is_valid_cpu(target_cpu)) return PSCI_E_INVALID_PARAMS; // 2. 配置目标 CPU 的入口地址 psci_set_cpu_entry_point(target_cpu, entry_point); // 3. 平台相关:唤醒目标 CPU plat_psci_cpu_on(target_cpu); return PSCI_E_SUCCESS; }
-
-
BL31 主流程:
-
文件 :
bl31/bl31_main.c -
关键函数 :
bl31_main()cvoid bl31_main(void) { // 1. EL3 基础初始化 bl31_early_platform_setup2(); bl31_plat_arch_setup(); // 2. 初始化运行时服务(包括 PSCI) runtime_svc_init(); // 3. 准备下一个镜像(BL32 或 BL33) entry_point_info_t *next_image = bl31_plat_get_next_image_ep_info(SECURE); if (!next_image) { next_image = bl31_plat_get_next_image_ep_info(NON_SECURE); } // 4. 跳转到下一个镜像 el3_exit(next_image); }
-
第四阶段:BL32(OP-TEE)与 BL33(非安全世界)处理
4.1 BL32(OP-TEE)
- 若为热启动且 OP-TEE 内存保留,BL31 可直接恢复 OP-TEE 上下文,跳过其完整初始化;
- 否则,仍需跳转到 OP-TEE 执行
init_tee_runtime()(与冷启动一致)。
4.2 BL33(LK/U-Boot)与 Linux
- BL33 会检测热启动状态,跳过部分外设初始化;
- Linux 内核启动后,通过
/proc/cmdline或平台寄存器识别热启动,跳过某些驱动的重初始化,快速恢复用户空间。
三、热启动特殊路径:RESET_TO_BL31
部分平台支持 RESET_TO_BL31=1 编译配置,热启动时可跳过 BL1/BL2,直接从 BL31 入口启动,进一步缩短启动时间。
核心逻辑
- 系统复位后,CPU 直接跳转到 BL31 的加载地址(而非 BL1 ROM);
- BL31 检测复位原因,若为热启动,跳过 BL1/BL2 处理,直接初始化 EL3 并切换到非安全世界。
核心代码
通过链接脚本直接进行跳转

执行bl31热启动流程


四、总结:热启动核心优化点
- DRAM 初始化:热启动跳过 DRAM 训练(最大的时间优化);
- 镜像加载:若内存内容保留,可跳过从 Flash 重加载 BL31/BL32/BL33;
- 安全世界:OP-TEE 可直接恢复上下文,跳过完整初始化;
- 路径简化 :支持
RESET_TO_BL31,跳过 BL1/BL2。
通过以上优化,热启动时间通常可从冷启动的数秒缩短至数百毫秒甚至更短。