手撕ARM64启动栈(三):QEMU + TF-A(ATF) BL1 核心职责——`bl1_main()` 逐函数拆解与 BL2 加载
系列文章目录手撕ARM64启动栈一QEMU TF-A → OP-TEE → U-Boot → Linux 全链路总览手撕ARM64启动栈二QEMU TF-A(ATF) BL1 执行上下文——GDB 实测复位到 BL2手撕ARM64启动栈三QEMU TF-A(ATF) BL1 核心职责——bl1_main()逐函数拆解与 BL2 加载手撕ARM64启动栈四QEMU TF-A(ATF) BL2 详解文章目录系列文章目录[手撕ARM64启动栈一QEMU TF-A → OP-TEE → U-Boot → Linux 全链路总览](https://blog.csdn.net/zheng_wuling/article/details/162657151?spm1011.2124.3001.6209) [手撕ARM64启动栈二QEMU TF-A(ATF) BL1 执行上下文——GDB 实测复位到 BL2](https://blog.csdn.net/zheng_wuling/article/details/162769218?spm1011.2124.3001.6209) [手撕ARM64启动栈三QEMU TF-A(ATF) BL1 核心职责——bl1_main() 逐函数拆解与 BL2 加载](https://blog.csdn.net/zheng_wuling/article/details/162847153?spm1011.2124.3001.6209) [手撕ARM64启动栈四QEMU TF-A(ATF) BL2 详解](https://blog.csdn.net/zheng_wuling/article/details/162975843?spm1011.2124.3001.6209)1. 引言2. bl1_main() 调用序列总览3. 逐函数拆解每个函数的职责3.1 plat_setup_early_console() / bl1_early_platform_setup()初始化控制台GDB 实测UARTCR.UARTEN 从 0 变 13.2 bl1_plat_arch_setup() / bl1_arch_setup()建立地址转换并设定下一级架构状态GDB 实测SCTLR_EL3.M 从 0 变 13.3 crypto_mod_init() / auth_mod_init()初始化校验框架3.4 bl1_platform_setup()注册镜像加载的 IO 后端4. 加载 BL2GDB 实测desc-image_info 从取到描述符到镜像已搬运5. 本篇小结日志与代码的对应关系1. 引言上一篇讲了 BL1 启动瞬间的执行上下文复位向量、el3_entrypoint_common、异常向量表以及 BL1 退出前交给 BL2 的最后状态。本篇回到bl1_main()bl1/bl1_main.c:50内部逐个拆解从打印欢迎信息到加载 BL2 之间调用的每一个平台初始化函数的功能。本篇结论基于TF_A_TRUSTED_BOARD_BOOTn见第一篇配置矩阵。涉及关键词ATF / TF-A / ARM Trusted Firmware、QEMU virt aarch64、BL1、bl1_main、OPTEE、OP-TEE。2.bl1_main()调用序列总览关键调用序列对照bl1/bl1_main.c的bl1_main()voidbl1_main(void){plat_setup_early_console();bl1_early_platform_setup();// 初始化串口之后才能打印bl1_plat_arch_setup();// 建页表、开 MMUNOTICE(FIRMWARE_WELCOME_STR);// Booting Trusted FirmwareNOTICE(BL1: %s\n,build_version_string);// BL1: v2.14.0(debug):v2.14.0NOTICE(BL1: %s\n,build_message);// BL1: Built : ...INFO(BL1: RAM %p - %p\n,...);// 打印 BL1 可见的 Trusted RAM 范围bl1_arch_setup();// 设 SCR_EL3.RW1下一级 EL 用 AArch64crypto_mod_init();// 初始化 crypto 框架auth_mod_init();// 初始化认证框架bl1_plat_mboot_init();// 度量启动初始化bl1_platform_setup();// 调 plat_qemu_io_setup()注册 FIP/semihosting IO 后端image_idbl1_plat_get_next_image_id();// QEMU virt 恒返回 BL2_IMAGE_IDif(image_idBL2_IMAGE_ID)bl1_load_bl2();// 正常启动加载 BL2elseNOTICE(BL1-FWU: *******FWU Process Started*******\n);// 固件升级分支...bl1_prepare_next_image(image_id);// 构造 BL2 的 entry_point_info上一篇已展开}bl1_plat_get_next_image_id()在QEMU 平台使用的是plat/common/plat_bl1_common.c里的弱符号默认实现恒定返回BL2_IMAGE_ID——所以永远走if加载 BL2。真实平台可以重写该函数如检测按键/GPIO/寄存器等返回非BL2_IMAGE_ID值以进入else的 FWU固件升级/恢复流程。bl1_main()调用序列流程图如下3. 逐函数拆解每个函数的职责bl1_main()里这串调用绝大多数是 TF-A 定义的平台移植钩子platform hook——框架规定了调用时机和函数签名具体实现交给各平台。其中bl1_early_platform_setup/bl1_plat_arch_setup/bl1_platform_setup是移植时必须实现的强制钩子官方《Porting Guide》trusted-firmware-a/docs/porting-guide.rst逐个给了职责定义。下面逐个说明每个钩子设计上负责什么。3.1plat_setup_early_console()/bl1_early_platform_setup()初始化控制台bl1_early_platform_setup()是 BL1 的早期平台初始化钩子。官方 porting guideporting-guide.rst:1653-1673原文Function : bl1_early_platform_setup() [mandatory]Argument : void Return : voidThis function executes with the MMU and data caches disabled. It is only calledby the primary CPU.On Arm standard platforms, this function:Enables a secure instance of SP805 to act as the Trusted Watchdog.Initializes a UART (PL011 console), which enables access to theprintffamily of functions in BL1.Enables issuing of snoop and DVM (Distributed Virtual Memory) requests tothe CCI slave interface corresponding to the cluster that includes theprimary CPU.——trusted-firmware-a/docs/porting-guide.rst:1653-1673即在 MMU 和数据 cache 关闭的状态下执行只由主 CPU 调用在 Arm 标准平台上负责使能 Trusted Watchdog、初始化一个 UARTPL011 控制台从而让 BL1 能用printf、以及使能 CCI 的 snoop/DVM 请求。也就是说它的核心职责是在 BL1 打印第一条日志之前把串口控制台拉起来。plat_setup_early_console()bl1_main.c:55则是它之前一个可选的最早期控制台钩子由EARLY_CONSOLE编译开关控制。QEMU 平台的bl1_early_platform_setup()plat/qemu/common/qemu_bl1_setup.c:52-60做两件事调qemu_console_init()初始化控制台并记录 BL1 可见的 Trusted RAM 范围voidbl1_early_platform_setup(void){/* Initialize the console to provide early debug support */qemu_console_init();/* Allow BL1 to see the whole Trusted RAM */bl1_tzram_layout.total_baseBL_RAM_BASE;bl1_tzram_layout.total_sizeBL_RAM_SIZE;}qemu_console_init()plat/qemu/common/qemu_console.c:14-22调用console_pl011_register()注册一个 PL011 UART 作启动运行时控制台。至此串口初始化完成BL1 从这里开始就能通过串口输出 log 了。GDB 实测UARTCR.UARTEN从 0 变 1执行前0x300—— PL011 复位默认值TXEbit8/RXEbit9默认打开但UARTENbit0默认关闭此时串口硬件还不能收发。Step Over 执行完这一行后0x301——UARTEN位被置 1串口正式使能。执行完bl1_early_platform_setup()UARTCR0x301表明已经把 UART 拉起其中$SCTLR_EL30x30c5183aM位/bit0 为0表明MMU还没enable。3.2bl1_plat_arch_setup()/bl1_arch_setup()建立地址转换并设定下一级架构状态bl1_plat_arch_setup()是平台相关的架构初始化钩子。官方 porting guideporting-guide.rst:1675-1689原文Function : bl1_plat_arch_setup() [mandatory]Argument : void Return : voidThis function performs any platform-specific and architectural setup that theplatform requires. Platform-specific setup might include configuration ofmemory controllers and the interconnect.In Arm standard platforms, this function enables the MMU.This function helps fulfill requirement 2 above.——trusted-firmware-a/docs/porting-guide.rst:1675-1689即执行平台特定和架构相关的设置平台特定部分可能包括内存控制器和互连interconnect的配置。QEMU 平台的实现plat/qemu/common/qemu_bl1_setup.c:73-90为建页表 开 MMUvoidbl1_plat_arch_setup(void){constmmap_region_tbl_regions[]{MAP_BL1_TOTAL,MAP_BL1_RO,{0}};setup_page_tables(bl_regions,plat_qemu_get_mmap());enable_mmu_el3(0);}GDB 实测SCTLR_EL3.M从 0 变 1执行前上一节截图同一时刻0x30c5183aM位bit0为0——MMU 尚未开启此时的取指/取数都是物理地址直通。Step Over 执行完这一行后0x30cd183fM位变为1——页表已建好MMU 正式生效。bl1_arch_setup()bl1/aarch64/bl1_arch_setup.c:15-19是平台无关的通用代码负责架构相关的 EL3 初始化当前实现是把下一级异常级别设为 AArch64voidbl1_arch_setup(void){/* Set the next EL to be AArch64 */write_scr_el3(read_scr_el3()|SCR_RW_BIT);}即置SCR_EL3.RW1告诉硬件下一级 ELBL2 所在的 S-EL1用 AArch64 指令集。3.3crypto_mod_init()/auth_mod_init()初始化校验框架这两个函数是 TF-A **可信启动Trusted Board Boot**认证框架的入口本质是初始化 crypto / 认证框架为后面加载镜像时的验签做准备。本文配置下 secure boot 关闭TF_A_TRUSTED_BOARD_BOOTnsecure boot 打开后它们才会真正初始化校验框架这里暂不关注留到后续 secure boot 相关文档详细介绍。3.4bl1_platform_setup()注册镜像加载的 IO 后端bl1_platform_setup()是完整平台初始化钩子。官方 porting guideporting-guide.rst:1691-1706原文Function : bl1_platform_setup() [mandatory]Argument : void Return : voidThis function executes with the MMU and data caches enabled. It is responsiblefor performing any remaining platform-specific setup that can occur after theMMU and data cache have been enabled.In Arm standard platforms, this function initializes the storage abstractionlayer used to load the next bootloader image.This function helps fulfill requirement 4 above.——trusted-firmware-a/docs/porting-guide.rst:1691-1706即在 MMU 和数据 cache 使能之后执行负责在 MMU/dcache 打开后才能进行的剩余平台特定设置在 Arm 标准平台上这个函数初始化用于加载下一个 bootloader 镜像的存储抽象层。QEMU 平台的实现plat/qemu/common/qemu_bl1_setup.cvoidbl1_platform_setup(void){plat_qemu_io_setup();}plat_qemu_io_setup()plat/qemu/common/qemu_io_storage.c注册 FIP 和 semihosting 两套 IO 后端的 policy 表规定每个镜像先从哪里读、失败后退到哪里: BL1 加载 BL2 时先尝试 FIP失败后回退到 semihosting。4. 加载 BL2bl1_main()调用序列里最后、也是最关键的一步是加载 BL2staticvoidbl1_load_bl2(void){descbl1_plat_get_image_desc(BL2_IMAGE_ID);INFO(BL1: Loading BL2\n);errload_auth_image(BL2_IMAGE_ID,info);NOTICE(BL1: Booting BL2\n);}对应日志INFO: BL1: Loading BL2 NOTICE: BL1: Booting BL2load_auth_image()common/bl_common.c:198-208内部按编译期开关分两条路径auth_mod_verify_img()做签名验证的那条路径由TRUSTED_BOARD_BOOT开关控制本篇配置下是n走的是纯搬运路径load_image()staticintload_auth_image_internal(unsignedintimage_id,image_info_t*image_data){#ifTRUSTED_BOARD_BOOTif(dyn_is_auth_disabled()0){returnload_auth_image_recursive(image_id,image_data);}#endifreturnload_image(image_id,image_data);// ← 本例实际执行这一行}签名验证相关的load_auth_image_recursive()/auth_mod_verify_img()留到后续 secure boot 专题文档展开本篇只关注load_image()这条路径。从bl1_load_bl2()起先经load_auth_image()→load_auth_image_internal()转发到load_image()TBBn 时无任何校验分支再进入load_image()common/bl_common.c:73-153内部找到镜像源 → 打开 → 读大小 → 检查大小 → 搬运数据到内存GDB 实测desc-image_info从取到描述符到镜像已搬运断点打在bl1_main.c:176info desc-image_info;bl1_load_bl2()内部desc bl1_plat_get_image_desc(BL2_IMAGE_ID);刚执行完的下一行WATCH 里把局部变量desc整个展开字段值说明desc0xe0ee080 bl2_img_desc静态描述符表里 BL2 那一项的地址非堆/栈临时对象desc-image_id0x1即BL2_IMAGE_IDdesc-state0x0IMAGE_STATE_RESET尚未开始加载desc-image_info.image_base0xe05b000BL2 将被搬运到的目标物理地址desc-image_info.image_max_size0x35000分配给 BL2 的最大空间对应BL2_BASE BL31_BASE - 0x35000platform_def.hdesc-image_info.image_size0x0此刻还没有加载大小未知desc-ep_info.pc0xe05b000与image_base相同——BL2 的入口地址就是它被搬运到的起始地址image_base 0xe05b000正是上一篇《执行上下文》断点 4/5 里next_bl_ep-pc/ELR_EL3最终被写入的那个值——两篇的实测数据在这里完全对得上本篇看到的是BL2 要被搬到哪上一篇看到的是BL1 ERET 跳到哪同一个地址。5. 本篇小结日志与代码的对应关系日志行 / 关键事实代码位置在 QEMU virt 上是否真实动作NOTICE: Booting Trusted Firmwarebl1_main.c:78—NOTICE: BL1: v2.14.0(debug):v2.14.0bl1_main.c:79—串口可以打印字符bl1_early_platform_setup()→qemu_console_init()qemu_console.c:14-22PL011 0x09000000plat_setup_early_console()本身因EARLY_CONSOLE0是空函数✅ 真实寄存器配置BL1 页表建立、MMU 开启bl1_plat_arch_setup()qemu_bl1_setup.c:73-90✅ 真实软件页表非内存控制器SCR_EL3.RW1bl1_arch_setup()bl1_arch_setup.c:15-19✅ 真实单条寄存器写load_auth_image()实际行为common/bl_common.cload_auth_image_internal()❌ TBBn 时等价于load_image()无校验NOTICE: BL1: Booting BL2bl1_load_bl2()末尾数据搬运完成至此BL1 阶段全部分析完成上一篇讲执行上下文复位向量、异常向量表、退出前状态本篇讲核心职责–逐函数拆解——串口初始化mmu页表建立与使能BL2镜像加载等。综合两篇,BL1 的主要职责已经清晰:上电复位后完成必要的底层初始化(硬件寄存器、EL3 异常向量表),建立 C 运行时环境与调用栈;随后进入 bl1_main() 执行平台相关初始化(串口、MMU 等;crypto/认证框架在本配置 TBBn 下为空);最后加载并跳转到 BL2,完成使命。下一篇开始进入BL2阶段分析BL2的详细流程其实到这里我们就可以知道ARM TF-A已将BL1流程(复位入口、C 运行时、bl1_main() 主序列)框架写好,芯片相关部分抽象成 bl1_early_platform_setup、bl1_plat_arch_setup、bl1_platform_setup 等平台钩子。如果需要移植到自己真实芯片,只要实现对应的钩子(串口、MMU、加载 BL2 的 IO 后端),BL1 就能跑起来并加载 BL2。

相关新闻

一键解锁HS2-HF_Patch:Honey Select 2游戏体验的终极增强方案

一键解锁HS2-HF_Patch:Honey Select 2游戏体验的终极增强方案

一键解锁HS2-HF_Patch:Honey Select 2游戏体验的终极增强方案 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 在Honey Select 2的游戏世界中&#x…

2026/7/26 8:57:02阅读更多 →
GPS周数翻转问题解析:从原理到嵌入式与服务器端处理方案

GPS周数翻转问题解析:从原理到嵌入式与服务器端处理方案

GPS 周数翻转(GPS Week Number Rollover)是 GPS 系统设计中的一个已知边界问题,它源于 GPS 时间系统对周数使用有限位数计数。当周数达到最大值后,会从零重新开始计数,这个过程称为“翻转”。对于依赖 GPS 时间戳进行时…

2026/7/26 8:55:02阅读更多 →
基于深度学习的昆虫识别系统设计与实践

基于深度学习的昆虫识别系统设计与实践

1. 项目背景与核心价值 昆虫识别系统是一个典型的计算机视觉应用项目,它结合了深度学习和图像处理技术来解决生物识别领域的实际问题。这类系统在农业病虫害防治、生态监测、生物多样性研究等领域有着广泛的应用前景。 我去年指导过三个类似方向的毕业设计&#xf…

2026/7/26 8:55:02阅读更多 →
魔兽争霸III终极优化指南:让经典游戏在现代化电脑上焕发新生

魔兽争霸III终极优化指南:让经典游戏在现代化电脑上焕发新生

魔兽争霸III终极优化指南:让经典游戏在现代化电脑上焕发新生 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为魔兽争霸III在Windows …

2026/7/26 10:17:26阅读更多 →
2026智能体实战:用MCP协议与GPT-5.6构建企业级AI Agent(附代码)

2026智能体实战:用MCP协议与GPT-5.6构建企业级AI Agent(附代码)

2026智能体实战:用MCP协议与GPT-5.6构建企业级AI Agent(附代码) 当GPT-5.6的Ultra多智能体架构遇见MCP协议,AI Agent正式从概念验证走向工程化落地。引言:2026,智能体元年 2026年7月,AI领域迎来…

2026/7/26 10:17:26阅读更多 →
Windows驱动存储清理终极指南:如何用DriverStoreExplorer释放磁盘空间提升系统性能

Windows驱动存储清理终极指南:如何用DriverStoreExplorer释放磁盘空间提升系统性能

Windows驱动存储清理终极指南:如何用DriverStoreExplorer释放磁盘空间提升系统性能 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 你是否发现Windows系统越来越慢&#xff…

2026/7/26 10:17:26阅读更多 →
彻底清理Windows驱动存储:DriverStoreExplorer深度使用指南

彻底清理Windows驱动存储:DriverStoreExplorer深度使用指南

彻底清理Windows驱动存储:DriverStoreExplorer深度使用指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer Windows驱动程序管理是每个用户都需要面对的系统维护任务。随着硬…

2026/7/26 10:17:26阅读更多 →
智能编程助手:提升开发效率的AI编码技术

智能编程助手:提升开发效率的AI编码技术

1. 项目概述:自动化编程助手的革命性突破在程序员的世界里,我们永远在寻找两全其美的解决方案——既想要高质量的代码产出,又希望保持可持续的工作节奏。最近在开发者社区引起热议的"Harness Engineering"技术,正在重新…

2026/7/26 10:17:26阅读更多 →
如何轻松下载在线视频?N_m3u8DL-CLI-SimpleG图形化工具完整指南

如何轻松下载在线视频?N_m3u8DL-CLI-SimpleG图形化工具完整指南

如何轻松下载在线视频?N_m3u8DL-CLI-SimpleG图形化工具完整指南 【免费下载链接】N_m3u8DL-CLI-SimpleG N_m3u8DL-CLIs simple GUI 项目地址: https://gitcode.com/gh_mirrors/nm3/N_m3u8DL-CLI-SimpleG 还在为复杂的命令行下载工具而烦恼吗?想要…

2026/7/26 10:15:25阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/26 0:01:28阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/26 0:01:28阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/26 0:01:28阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/26 0:01:28阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/26 0:01:28阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/26 0:01:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/25 23:03:25阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/25 19:03:04阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/25 19:03:04阅读更多 →