1、ATF移植概述:什么是ATF、ATF在系统启动中的角色、移植前的准备工作与硬件环境评估

1.1 什么是ATF?

ATF,全称是ARM Trusted Firmware。说白了,它就是ARM架构下的一套安全固件参考实现。我刚开始接触它的时候,也觉得这名字挺唬人。但用久了你会发现,它其实就是一块「安全垫片」——垫在硬件和操作系统之间,负责把系统从混乱的复位状态,安全地引导到正常世界。

ATF主要干三件事:

  • 安全启动:确保每一级镜像都是可信的,没被篡改过
  • 运行时服务:提供安全监控模式调用(SMC),让普通世界和安全世界能通信
  • 电源管理:处理CPU的开关、休眠、唤醒等底层操作

我个人习惯把ATF比作「看门大爷」。它不负责具体业务,但谁想进这栋楼,都得先过它这一关。嗯,这个比喻虽然糙了点,但道理是通的。

核心要点:ATF不是操作系统,也不是Bootloader。它是介于两者之间的安全固件层。你想想看,如果没有它,系统从上电到Linux启动之间,谁来做安全校验?谁来做EL3的初始化?

1.2 ATF在系统启动中的角色

系统启动是个接力赛。从ROM代码到BL1、BL2、BL31、BL32、BL33,每一棒都有明确分工。ATF主要参与的是BL1到BL33这一段。

我画了一张图,帮你理清这个流程:

ATF在系统启动中的角色 — 启动流程 ROM Code 固化在芯片内 BL1 ATF 第一级 BL2 ATF 第二级 BL31 ATF 运行时 ↓ 分叉加载 BL32 安全世界 OS BL33 非安全世界 OS 系统启动完成! 非ATF ATF组件 安全OS 非安全OS

你看,ATF从BL1开始介入,一直管到BL31把控制权交出去。BL31是个关键节点——它留在EL3,作为安全监控器常驻内存。而BL32和BL33,分别进入安全世界和非安全世界。

我在项目中遇到过一个问题:某款芯片的BL2加载BL31时,地址配置错了,导致BL31跑飞。查了两天才发现是链接脚本里少了个对齐宏。嗯,这种坑踩过一次就记住了。

1.3 移植前的准备工作

移植ATF不是上来就改代码。你得先摸清家底。我个人习惯列一个检查清单,逐项确认。

检查项 说明 重要程度
ARM架构版本 确认是Cortex-A系列还是Cortex-M系列,AArch32还是AArch64 ★★★★★
GIC版本 GICv2还是GICv3?中断模型差别很大 ★★★★★
内存布局 DRAM基址、SRAM大小、TZC区域划分 ★★★★☆
时钟与复位 CPU时钟、看门狗、复位逻辑 ★★★★☆
调试接口 JTAG/SWD是否可用,串口输出是否正常 ★★★★☆
安全特性 是否支持TrustZone、是否启用TZC-400 ★★★☆☆

我的小技巧:拿到一块新板子,别急着移植。先跑通原厂提供的Demo固件,确认硬件没问题。我曾经跳过这一步,结果折腾了三天发现是开发板虚焊了……

1.4 硬件环境评估

硬件环境评估,说白了就是搞清楚你的板子「长什么样」。我一般分三步走:

  1. 读原理图:重点关注电源域、复位信号、启动介质选择
  2. 看数据手册:找到内存映射图、外设基址、中断号
  3. 测串口:确保UART能正常输出,这是调试的生命线

你想想看,如果串口都不通,ATF打印的调试信息你根本看不到,那还怎么玩?

注意:有些芯片的串口默认是关闭的,或者需要配置GPIO复用。我遇到过一款SoC,它的UART0和JTAG共用引脚,必须通过eFuse选择。这种坑在原理图阶段就要发现,否则后面会非常被动。

另外,内存布局这块特别容易出问题。ATF需要知道自己能使用哪些内存区域。通常BL1放在ROM或SRAM里,BL2和BL31放在DRAM里。但DRAM的初始化本身就需要BL2来完成——这就成了「先有鸡还是先有蛋」的问题。

解决办法是:BL1和BL2尽量小,放在片上SRAM里。等BL2初始化完DRAM,再把BL31加载进去。嗯,这个套路几乎所有平台都通用。

1.5 开发环境搭建

工欲善其事,必先利其器。ATF移植需要准备以下工具链:

  • 交叉编译器:aarch64-linux-gnu-gcc 或 arm-linux-gnueabihf-gcc
  • 构建工具:make、cmake(可选)
  • 调试工具:OpenOCD + GDB,或者DS-5
  • 烧录工具:根据芯片厂商定,比如STM32CubeProgrammer、Rockchip的RKDevTool

我个人推荐用Linaro的交叉编译器,稳定且更新及时。别用太老的版本,我踩过gcc 4.9编译ATF报错的坑,升级到7.3就好了。

一句话总结:ATF移植,七分准备三分改。硬件环境摸透了,代码改动其实就那么几行。但要是硬件没搞明白,改代码就是瞎蒙。