3. TEE开发环境搭建:基于QEMU的ARM TrustZone模拟器搭建、OP-TEE源码编译与部署
说实话,很多初学者一上来就买开发板,结果发现调试起来特别麻烦。我个人习惯先用模拟器把环境跑通,再上真板子。这样效率高,而且能省不少钱。
这一章,我们就来搞定基于QEMU的ARM TrustZone模拟器,再把OP-TEE的源码编译部署上去。你跟着我走一遍,大概两个小时就能看到一个跑起来的TEE环境。
3.1 为什么选QEMU?
QEMU能模拟完整的ARMv8-A平台,包括GIC、UART、定时器这些外设。最关键的是,它支持TrustZone扩展。这意味着你可以在普通Linux里跑一个完整的TEE系统,而不需要买硬件。
我在项目里遇到过一种情况:客户要求快速验证一个安全存储方案,但开发板还在采购流程里。当时就是用QEMU搭的环境,提前两周完成了原型验证。嗯,这个选择后来被证明非常正确。
核心优势:
- 零硬件成本,一台笔记本就够了
- 调试方便,GDB直接连上去
- 快照功能,出错了随时回滚
- 支持多核模拟,接近真实硬件行为
3.2 环境准备
先看看你的机器。我建议用Ubuntu 20.04或22.04 LTS,64位系统。其他发行版也行,但依赖包的名字可能不一样,你得自己查一下。
需要安装的依赖包不少,我列个清单:
sudo apt-get update
sudo apt-get install -y \
git \
wget \
make \
gcc \
g++ \
python3 \
python3-pip \
device-tree-compiler \
flex \
bison \
libssl-dev \
libncurses-dev \
libglib2.0-dev \
libfdt-dev \
libpixman-1-dev \
zlib1g-dev \
libgmp-dev \
libmpc-dev \
libmpfr-dev \
texinfo \
cpio \
rsync \
unzip \
bc \
u-boot-tools \
android-tools-mkbootimg
小技巧: 如果你用的是Ubuntu 22.04,记得把python改成python3。我一开始没注意,结果编译脚本报错,查了半天才发现是python软链接的问题。
3.3 下载OP-TEE源码
OP-TEE官方提供了一个repo清单文件,能一次性拉取所有组件。包括:
- optee_os — TEE内核,运行在安全世界
- optee_client — 普通世界的客户端API库
- optee_test — 测试用例,验证功能是否正常
- build — 编译脚本和配置文件
- linux — 打了补丁的Linux内核
- qemu — 支持TrustZone的QEMU
拉取命令如下:
mkdir ~/optee
cd ~/optee
repo init -u https://github.com/OP-TEE/manifest.git -m qemu_v8.xml
repo sync -j4
这个过程比较慢,取决于你的网速。我建议用-j4参数,同时拉取4个任务。我曾经试过-j8,结果把公司的出口带宽占满了,被IT部门打电话警告……
注意: repo工具需要先安装。如果提示找不到repo,执行:
sudo apt-get install repo
或者从Google官方源下载:
mkdir ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH
3.4 编译OP-TEE
源码拉下来之后,进入build目录,直接make就行。但别急,先看看编译选项。
OP-TEE的编译系统基于Makefile,支持多种目标平台。我们用的是qemu_v8,对应ARMv8-A架构的QEMU模拟器。
cd ~/optee/build
make -j$(nproc) QEMU_V8=y
这里有几个关键点:
- -j$(nproc):用所有CPU核心并行编译,速度最快
- QEMU_V8=y:指定目标平台为QEMU v8
- 第一次编译会下载交叉编译工具链,大概几百MB
编译完成后,你会看到类似这样的输出:
Built optee_os
Built optee_client
Built optee_test
Built linux
Built qemu
Built rootfs
Built all targets successfully
我记得第一次编译时,卡在了rootfs生成那一步。后来发现是磁盘空间不够,OP-TEE的根文件系统需要至少2GB空闲空间。所以编译前先检查一下:
df -h ~/optee
3.5 启动QEMU模拟器
编译成功后,启动模拟器只需要一条命令:
cd ~/optee/build
make run-only QEMU_V8=y
你会看到两个终端窗口弹出来:
- 一个运行普通世界(Normal World)的Linux
- 一个运行安全世界(Secure World)的OP-TEE
登录普通世界的Linux,用户名root,密码空。然后运行测试用例:
xtest
这个命令会执行所有TEE功能测试。如果一切正常,你会看到一堆绿色的PASS。我建议先跑一个简单的测试:
xtest 1001
这个测试只验证基本的TA加载和调用,跑得很快。
常见问题:
- QEMU窗口不显示? 检查是否安装了SDL库:
sudo apt-get install libsdl2-dev - 启动卡在"Waiting for root device"? 重新编译rootfs:
make -j$(nproc) rootfs QEMU_V8=y - xtest报错"TEEC_ERROR_NOT_SUPPORTED"? 检查OP-TEE内核是否正常启动,看安全世界终端的日志
3.6 整体架构图
下面这张图展示了整个环境的组件关系和启动流程。我画的时候特意把安全世界和普通世界的边界标清楚了。
3.7 验证环境是否正常
环境跑起来之后,我习惯做几个快速验证:
- 检查OP-TEE版本:在安全世界终端输入
version,应该显示当前编译的版本号 - 查看安全内存:
cat /proc/iomem | grep optee,确认安全内存区域已注册 - 运行基础测试:
xtest 1001,看是否返回TEEC_SUCCESS - 检查日志:
dmesg | grep optee,看驱动加载是否正常
调试技巧: 如果想看更详细的日志,可以在编译时开启调试选项:
make -j$(nproc) QEMU_V8=y CFG_TEE_CORE_LOG_LEVEL=4
日志级别从0(无日志)到4(最详细)。我调试时一般用3,信息量适中。
3.8 常见问题与避坑
我整理了几个容易踩的坑,都是我在项目中实际遇到过的:
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 编译报错"undefined reference to ..." | 交叉编译工具链版本不匹配 | 删除toolchain目录,重新make,让脚本自动下载 |
| QEMU启动后黑屏 | 缺少图形库或显示配置错误 | 安装libsdl2-dev,或改用-nographic模式 |
| xtest全部FAIL | OP-TEE内核未正确加载 | 检查安全世界终端是否有"OP-TEE"启动信息 |
| repo sync失败 | 网络问题或GitHub被墙 | 使用代理,或换用国内镜像源 |
我曾经在给客户做POC时,现场网络特别差,repo sync反复中断。后来我提前把整个optee目录打包成tar.gz,带到现场直接解压编译,省了不少时间。所以建议你也备份一份完整的源码包。
3.9 下一步做什么?
环境搭好之后,你可以试试自己写一个简单的TA。比如实现一个加法函数,从普通世界传入两个数,在安全世界里计算,再返回结果。这个例子虽然简单,但能帮你理解CA和TA之间的通信流程。
嗯,这一章的内容就到这里。环境搭好了,后面的事情就好办了。