1. ATF概述:ARM Trusted Firmware到底是什么?
说实话,我刚接触ATF那会儿,也一头雾水。ARM Trusted Firmware,简称ATF,是ARM官方提供的一套开源固件。它运行在系统的安全世界(Secure World)里,说白了就是给ARM架构的芯片提供一个可信的启动环境。
你可能会问:为什么需要这么个东西?我举个例子。我在一个车载项目里遇到过,客户要求系统启动时必须验证每一段代码的签名,从ROM到OS,中间但凡有一个环节被篡改,整辆车就不能启动。没有ATF,这种需求几乎没法落地。
ATF的核心定位:它是ARM架构下安全启动的基石,负责从EL3(异常级别3)开始,初始化安全世界,加载并验证后续的固件和操作系统。
1.1 为什么需要ATF?
ARMv8-A架构引入了异常级别(Exception Levels),从EL0到EL3。EL3是最高权限级别,只有安全世界的代码才能运行在这里。ATF就是运行在EL3上的固件。
我习惯把ATF的作用归纳为三点:
- 安全启动(Secure Boot):从ROM代码开始,逐级验证镜像的签名。我在调试一个平板项目时,就因为签名算法没对齐,卡在BL2加载BL31那一步,折腾了两天。
- 运行时服务(Runtime Services):提供PSCI(电源状态协调接口)、SMC(安全监控调用)等服务。操作系统通过SMC指令陷入EL3,请求ATF帮忙开关CPU、调整频率。
- 可信执行环境(TEE)的载体:ATF负责加载和切换TEE OS(如OP-TEE),让安全应用和普通世界隔离运行。
我的经验:很多刚入行的朋友以为ATF只是个启动加载器。其实它更像一个微型操作系统,运行在EL3,管理整个安全世界。你想想看,它要处理中断、管理电源、提供服务,复杂度不低。
1.2 ATF在系统启动中的角色
系统上电后,ATF的启动流程大致是这样的:
- ROM代码(BL1):芯片内部的ROM固件,不可修改。它加载BL2到SRAM,并验证签名。
- 平台初始化(BL2):初始化DDR、时钟、外设。然后加载BL31、BL32(TEE)、BL33(U-Boot/EDK2)。
- 运行时固件(BL31):驻留在EL3,提供PSCI和SMC服务。它不退出,一直运行。
- TEE OS(BL32,可选):安全世界的操作系统,运行在EL1。
- 非安全固件(BL33):通常是U-Boot或EDK2,最终引导Linux或Windows。
嗯,这里要注意:BL1和BL2是临时执行的,执行完就释放内存。BL31是常驻的,它像管家一样,随时响应安全请求。
1.3 ATF的组件与文件结构
ATF源码目录结构很清晰。我习惯先看plat/目录,那里是平台相关代码。每个芯片厂商都有自己的子目录,比如plat/rockchip/、plat/nxp/。
| 组件 | 源码位置 | 功能简述 |
|---|---|---|
| BL1 | bl1/ |
ROM加载器,验证BL2签名 |
| BL2 | bl2/ |
平台初始化,加载后续镜像 |
| BL31 | bl31/ |
运行时固件,PSCI/SMC服务 |
| BL32 | bl32/ |
TEE OS接口层(如OP-TEE) |
| 平台代码 | plat/<vendor>/ |
板级初始化、电源管理 |
| 驱动 | drivers/ |
UART、GIC、MMC等外设驱动 |
避坑提醒:我曾经在移植ATF到一块新板子时,直接复制了参考平台的代码。结果BL2初始化DDR时序不对,系统反复重启。后来发现是plat_get_my_entrypoint()这个函数没适配。每个平台的DDR参数、时钟配置都不一样,千万别偷懒。
1.4 异常级别与安全模型
ARMv8-A的异常级别设计,是理解ATF的关键。我画个简图帮你理清:
- EL0:用户态应用,无特权。
- EL1:操作系统内核(Linux、TEE OS)。
- EL2:虚拟机监视器(Hypervisor)。
- EL3:安全固件(ATF),最高权限。
ATF运行在EL3,可以访问所有资源。它通过SMC指令与EL1/EL2通信。举个例子,Linux要关闭一个CPU核心,不能直接操作硬件,得发一个SMC请求给ATF,ATF在EL3执行PSCI命令,完成电源操作。
我的习惯:调试ATF时,我会在BL31的smc_handler()里加打印,看SMC函数ID和参数。这样能快速定位是哪个服务出了问题。你想想看,如果PSCI返回错误,Linux那边就会卡在CPU hotplug上,查起来很头疼。
1.5 小结
ATF不是可有可无的组件。它是ARM安全世界的基石,负责安全启动、运行时服务和TEE管理。理解它的角色,是后续部署和调试的前提。