2. 开发环境搭建

在构建 TrustZone 安全世界初始化固件之前,必须完成贯穿开发、编译、调试、运行全周期的环境搭建。本章按四个子专题组织:硬件平台选择(QEMU 与 FPGA 的取舍)、交叉编译链安装与验证、调试器接入方式(JTAG/SWD / GDB)以及 TrustZone 固件依赖(ATF、OP-TEE、U-Boot 等)。

推荐起点:初学者及原型验证阶段优先使用 QEMU;FPGA 适用于硬件时序验证与最终性能调优。本章以 QEMU 为默认平台给出所有命令行示例。

2.1 硬件平台选择:QEMU 与 FPGA 对比

维度QEMU(软件仿真)FPGA(硬件原型)
启动速度秒级,适合快速迭代分钟级(综合+布局布线)
硬件精确度指令级仿真,外设模型有限精确到时钟周期,真实外设时序
调试能力原生 GDB stub,断点/单步JTAG + 硬件调试器,支持实时追踪
成本免费,无硬件开销开发板 $200–$2000+
适用阶段功能验证、安全世界初始化流程驱动集成、性能优化、安全攻击测试

本课程所有代码与寄存器配置均针对 QEMU virt-8.2+ 平台,并额外标注与 FPGA 的差异点。

2.2 交叉编译链安装与验证

TrustZone 安全世界运行于 AArch64 状态(Cortex-A53/A72),必须使用 aarch64-none-elf- 或 aarch64-linux-gnu- 工具链。推荐版本为 ARM GCC 13.2.Rel1。

# 下载并解压
wget https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-elf.tar.xz
tar -xf arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-elf.tar.xz
mv arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-elf /opt/arm-gcc-aarch64

# 设置环境变量
export PATH=/opt/arm-gcc-aarch64/bin:$PATH

# 验证编译与 objdump
aarch64-none-elf-gcc -v 2>&1 | head -n 1
aarch64-none-elf-objdump -i
关键区别:aarch64-none-elf- 不依赖 libc,适合裸机/BL1/BL2 固件;aarch64-linux-gnu- 用于 Linux 内核与 OP-TEE OS 编译。安全世界初始化代码属于裸机环境,优先使用 none-elf 前缀。

2.3 调试器接入方式(JTAG / SWD / GDB)

QEMU 内置 GDB stub 提供与硬件调试器几乎一致的体验。FPGA 开发板需外接 JTAG/SWD 调试器(如 SEGGER J-Link、ARM DStream)。

调试方式协议连接接口典型工具
QEMU GDB StubTCP网络(localhost:1234)aarch64-none-elf-gdb
JTAGIEEE 1149.120-pin 盒带OpenOCD + GDB
SWDARM 专用2线(SWDIO+SWCLK)pyOCD / J-Link Commander

启动 QEMU 并附加调试器(单核 Cortex-A53):

qemu-system-aarch64 -machine virt -cpu cortex-a53 -smp 1 \
    -m 1024 -nographic -bios bl1.bin \
    -gdb tcp::1234 -S

参数 -S 让 CPU 在第一条指令处暂停,等待 GDB 连接。然后在另一个终端启动 GDB:

aarch64-none-elf-gdb bl1.elf
(gdb) target remote :1234
(gdb) info registers x0 x1 x2
(gdb) break bl1_entry
(gdb) continue
常见错误:QEMU 的 -bios 参数仅加载原始二进制文件,-kernel 则会自动将 Image 放入 DRAM 并设置启动参数。安全世界初始化阶段应使用 -bios,避免 QEMU 干扰 EL3 入口状态。

2.4 TrustZone 固件依赖关系

安全世界初始化并非单一固件,而是至少涉及三个软件组件的协作:

  • ARM Trusted Firmware-A(TF-A):提供 BL1、BL2、BL31,负责安全监视器、PSCI、中断路由。
  • OP-TEE:提供安全世界 OS(BL32),运行于 S-EL1,支持 TA 加载。
  • U-Boot(可选):作为 BL33 进入非安全世界,加载 Linux 内核。

典型构建链只需 TF-A + OP-TEE 即可完成安全世界初始化。下表给出最小依赖及其推荐版本:

组件GIT 仓库推荐分支 / Tag
TF-Ahttps://git.trustedfirmware.org/TF-A/trusted-firmware-a.gitv2.10.0
OP-TEE OShttps://github.com/OP-TEE/optee_os.git4.2.0
QEMUhttps://gitlab.com/qemu-project/qemu.gitv8.2.0
# 克隆 TF-A
git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git -b v2.10.0

# 克隆 OP-TEE OS
git clone https://github.com/OP-TEE/optee_os.git -b 4.2.0

# 为 QEMU 构建 TF-A(仅 BL1 + BL2 + BL31)
cd trusted-firmware-a
make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu DEBUG=1 bl1 bl2 bl31
输出产物:build/qemu/debug/bl1.bin、bl2.bin、bl31.bin,以及 ELF 调试文件 bl1/bl2/bl31.elf。这些 .bin 通过 QEMU 的 -bios 以及后续的 fip 打包工具组合成一个 FIP 映像。

2.5 完整验证:启动并观察安全世界初始化输出

将 TF-A 与 OP-TEE OS 合并为 FIP 映像,并用 QEMU 加载:

# 构建 OP-TEE OS(需指定 PLATFORM)
cd optee_os
make PLATFORM=vexpress-qemu_armv8a CROSS_COMPILE64=aarch64-none-elf- CFG_ARM64_core=y O=out

# 返回 TF-A 构建 FIP(合并 BL2、BL31、BL32)
cd ../trusted-firmware-a
make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu DEBUG=1 \
    BL32=../optee_os/out/core/tee-pager_v2.bin \
    fip

# 启动 QEMU
qemu-system-aarch64 -machine virt -cpu cortex-a53 -m 1024 -nographic \
    -bios build/qemu/debug/bl1.bin \
    -drive if=none,file=build/qemu/debug/fip.bin,format=raw,id=fip \
    -device virtio-blk-device,drive=fip
观察初始化进度:QEMU UART 输出应依次显示 BL1(标记冷启动 / 晶振频率)、BL2(加载映像)、BL31(设置异常向量表)、OP-TEE(打印版本与 init 信息)。如 GIC 或定时器未正确配置,输出会在 BL31 处卡住或循环错误断言。

2.6 常见错误与诊断

  • “NOTICE: BL31: Non‑secure world also cold‑booted” 消失:表明 BL31 未成功跳转到 BL32,检查 FIP 中 BL32 地址与构建时的 ARM_TSP_RAM_LOCATION。
  • “E/TC: OP-TEE init failed at …”:OP-TEE 依赖安全 DRAM(如 0x4000000),与 QEMU 内存布局冲突时出现;检查 QEMU 启动参数中的 -m 与 TF-A ARM_LINUX_KERNEL_AS_BL33 设定。
  • GDB 无法连接至端口 1234:确认未启用 -sandbox on 且防火墙未阻拦;改用 localhost:1234 明确 IP。
  • 交叉编译链接时失败:将 CROSS_COMPILE 改为完整路径 /opt/arm-gcc-aarch64/bin/aarch64-none-elf-。

2.7 性能与稳定性优化初步

  1. 编译优化:DEBUG=1 包含大量断言与日志;切换到 DEBUG=0 并启用 SPD=opteed 可减少 30% 二进制体积及缩短启动时间。
  2. GIC 配置:QEMU 默认使用 GICv3,TF-A 构建时必须指定 GICV3_GICD_BASE=0x2f000000 GICV3_GICR_BASE=0x2f100000,否则安全世界中断无法到达目标 PE。
  3. 系统计数器:FPGA 平台需提供真实晶振频率(如 24 MHz),QEMU 自动仿真该频率,无需额外校准。
TrustZone 开发环境搭建工具链与固件关系图 开发环境搭建:工具链与固件依赖 Host 开发机 (x86_64 / Linux) 交叉编译链 (aarch64-none-elf-gcc) | GDB (remote) | QEMU 启动脚本 目标运行时平台 QEMU virt (Cortex-A53) ↔ FPGA (ZynqMP / Juno) BL1 / BL2 (TF-A) – 安全世界冷启动 & 映像加载 BL31 (TF-A) – 安全监视器 / PSCI / 中断分发 BL32 (OP-TEE OS) – 安全世界 OS / TA 执行环境 调试通道 GDB :1234 / JTAG 最小安全世界初始化固件栈 TF-A (BL1+BL2+BL31) + OP-TEE (BL32) → FIP 映像 → QEMU 启动

2.8 小结:环境评估清单

  1. 交叉编译链(aarch64-none-elf-gcc 13.2)已安装且 PATH 有效。
  2. QEMU 8.2+ 支持 virt 平台及 GICv3 模型。
  3. TF-A v2.10.0 与 OP-TEE 4.2.0 已克隆至本地,make PLAT=qemu 无报错。
  4. 能通过 QEMU UART 看到 BL1、BL2、BL31 与 OP-TEE 的启动日志。
  5. 可附加 GDB 并设置断点于 bl1_entry,单步跟踪第一条安全世界指令。
时序敏感陷阱:FPGA 平台若未正确配置 TIMER_CLK 或 GIC 基地址,BL31 中初始化系统计数器会挂死。QEMU 不暴露此类硬件敏感性,但需为 FPGA 单独准备 DTS 与配套头文件。