3. TEE开发环境搭建:QEMU模拟器搭建、OP-TEE源码编译、Linux内核与TEE驱动配置
说实话,做TEE开发最头疼的就是硬件板子还没回来,代码已经写好了。这时候怎么办?靠模拟器。
我个人习惯在开发初期先用QEMU把整个环境跑通。你想想看,等硬件回来再调驱动,那得多耽误事。这一章我就带你搭一套完整的OP-TEE + QEMU开发环境。包括模拟器搭建、源码编译、内核和驱动配置。每一步我都会把踩过的坑指出来。
本章目标:在x86主机上通过QEMU模拟ARM64平台,运行完整的OP-TEE + Linux系统。最终能启动到Linux shell,并验证TEE驱动加载成功。
3.1 环境概览与依赖安装
先看看整体架构。QEMU模拟一个ARM64开发板,上面跑两个世界:
嗯,这张图你得记住。后面所有配置都是围绕这个结构展开的。
先装依赖。我用的是Ubuntu 22.04,其他发行版也差不多。
# 基础工具
sudo apt update
sudo apt install -y \
git wget curl \
build-essential \
python3 python3-pip \
device-tree-compiler \
flex bison \
libssl-dev \
libncurses-dev \
xterm
# QEMU(要支持ARM64)
sudo apt install -y qemu-system-arm
# 交叉编译工具链
sudo apt install -y \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu
# 验证
aarch64-linux-gnu-gcc --version
qemu-system-aarch64 --version
我的经验:千万别用系统自带的旧版QEMU。我踩过坑,旧版QEMU对GICv3支持有问题,OP-TEE启动会卡死。建议从源码编译QEMU 7.2+,或者用OP-TEE官方推荐的版本。
3.2 获取OP-TEE源码与构建系统
OP-TEE官方提供了一个repo清单,能把所有组件一次性拉下来。我个人习惯用这个方式,省得一个个找版本匹配。
# 安装repo工具
mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH
# 创建工作目录
mkdir -p ~/optee
cd ~/optee
# 初始化repo(以4.0.0版本为例)
repo init -u https://github.com/OP-TEE/manifest.git -m qemu_v8.xml -b 4.0.0
# 同步源码(这一步比较久,建议挂代理)
repo sync -j$(nproc)
同步完成后,目录结构是这样的:
| 目录/文件 | 说明 |
|---|---|
optee_os/ |
OP-TEE 内核(安全世界OS) |
linux/ |
Linux内核源码(含OP-TEE驱动) |
build/ |
构建脚本和Makefile |
out/ |
编译输出目录 |
toolchains/ |
交叉编译工具链(自动下载) |
qemu_v8.mk |
QEMU v8平台的顶层Makefile |
注意:repo sync可能会因为网络问题失败。我建议用repo sync --fail-fast,这样失败后能快速定位是哪个仓库的问题。如果某个仓库反复失败,手动git clone也行。
3.3 编译OP-TEE与Linux内核
编译过程其实很简单。OP-TEE的构建系统已经帮你配好了所有依赖。你只需要执行一条命令。
cd ~/optee/build
make -j$(nproc) QEMU_V8
这条命令会依次做以下几件事:
- 编译OP-TEE OS(生成
tee-pager_v2.bin) - 编译Linux内核(生成
Image) - 编译设备树(生成
qemu_arm64.dtb) - 编译U-Boot(引导加载程序)
- 生成根文件系统(基于Buildroot)
我第一次编译时等了大概40分钟。如果你机器性能好,20分钟也能搞定。
关键输出文件:
out/bin/tee-pager_v2.bin— OP-TEE OS镜像out/bin/Image— Linux内核镜像out/bin/qemu_arm64.dtb— 设备树out-br/images/rootfs.cpio.gz— 根文件系统
3.4 Linux内核与TEE驱动配置
这里我要重点说一下。OP-TEE驱动默认是编译进内核的,但有时候你改了内核配置,驱动可能没打开。我曾经遇到过这个问题,折腾了半天才发现是驱动没编译进去。
检查内核配置:
cd ~/optee/linux
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
确保以下选项开启:
| 配置项 | 路径 | 值 |
|---|---|---|
CONFIG_OPTEE |
Device Drivers → TEE → OP-TEE | y(编译进内核) |
CONFIG_OPTEE_SHM_NUM_PRIV_PAGES |
同上 | 1(默认即可) |
CONFIG_TEE |
Device Drivers → TEE | y |
CONFIG_ARM_SMCCC |
Kernel Features → ARM SMC Calling Convention | y |
保存配置后,重新编译内核:
cd ~/optee/build
make -j$(nproc) QEMU_V8 linux
避坑指南:我曾经把OP-TEE驱动编译成模块(m),结果启动后忘了加载模块,CA调用TEE接口直接返回-ENODEV。建议你直接编译进内核,省心。
3.5 启动QEMU并验证
编译完成后,启动QEMU:
cd ~/optee/build
make run QEMU_V8
你会看到两个终端窗口弹出来:
- 一个窗口是安全世界的控制台(OP-TEE的日志)
- 另一个窗口是非安全世界的控制台(Linux shell)
在Linux shell中,验证TEE驱动:
# 检查TEE设备节点
ls -l /dev/tee*
# 应该看到 /dev/tee0 和 /dev/teepriv0
# 检查内核日志
dmesg | grep optee
# 应该看到 "optee: OP-TEE: revision 4.0.0" 之类的信息
# 运行OP-TEE自带的测试
xtest
# 如果所有测试通过,说明环境搭建成功
常见问题:
- 如果QEMU启动后黑屏,检查终端模拟器是否安装(
sudo apt install xterm) - 如果
/dev/tee0不存在,检查内核配置中OP-TEE驱动是否编译进内核 - 如果xtest报错,检查OP-TEE OS版本和Linux内核版本是否匹配
3.6 我的调试小技巧
最后分享几个我常用的调试方法:
- 加日志:在OP-TEE OS源码的
core/arch/arm/kernel/下加DMSG()打印,重新编译就能看到安全世界的调试信息。 - GDB调试:QEMU支持GDB连接。启动时加
-s -S参数,然后在另一个终端用aarch64-linux-gnu-gdb vmlinux连接。 - 抓包SMC调用:在OP-TEE OS的
core/arch/arm/sm/下加日志,能看到每次安全调用的参数。
嗯,环境搭建这部分就到这里。你跟着步骤走,应该能顺利跑起来。如果卡住了,回头检查一下依赖版本和内核配置。这些东西我当初也调了好几天,别着急。