文章目录
使用 Ninja 编译和运行 BL2、TF-M Secure 与 Non-Secure
前面已经搭好 TF-M 构建环境,这里使用 Ninja 编译 Secure 和 Non-Secure 示例,再通过 QEMU 启动。
使用 Ninja 构建 Secure
配置
cd "/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m"
source env/bin/activate
cmake -S . -B build_an521_ninja -G Ninja \
-DTFM_PLATFORM=arm/mps2/an521 \
-DCMAKE_BUILD_TYPE=Debug
-S .指定源码目录,.表示当前的trusted-firmware-m目录,从这里读取顶层CMakeLists.txt。-B build_an521_ninja指定构建目录,用于保存构建规则、配置缓存和编译产物,目录不存在时自动创建。-G Ninja选择 Ninja 生成器,在构建目录生成build.ninja,后续由 Ninja 执行编译。-DTFM_PLATFORM=arm/mps2/an521设置 TF-M 的目标平台,使用 MPS2 AN521 对应的平台配置。-D表示设置 CMake 配置变量。-DCMAKE_BUILD_TYPE=Debug选择调试构建,便于使用 GDB 调试,具体调试信息和优化选项由工程与工具链配置决定。
先使用基本配置编译,遇到问题再按后面对应的小节处理。默认使用 GNU Arm 工具链并启用 BL2,不需要重复指定。
不需要手动创建 build_an521_ninja,CMake 会自动创建。需要 compile_commands.json 时,再执行下面的命令,无需修改 CMakeLists.txt。
cmake -S . -B build_an521_ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-S .指定当前目录为源码目录。-B build_an521_ninja使用已有构建目录,保留其中的其他配置。-DCMAKE_EXPORT_COMPILE_COMMANDS=ON开启编译命令导出,生成compile_commands.json,供 clangd 等工具查询源文件的编译参数。
首次配置会下载 CMSIS、MCUboot、TF-PSA-Crypto 等依赖,并放在 build_an521_ninja/lib/ext/。这一步需要网络,外层的 tf-m-extras 用于构建 NS 示例,TF-M 也可能为自己的扩展依赖单独下载一份。
编译并导出 NS 接口
cmake --build build_an521_ninja --target install --parallel
--build build_an521_ninja构建已经配置好的build_an521_ninja目录,CMake 会调用其中对应的构建工具。--target install执行安装目标,先构建固件,再导出 NS 工程需要的文件到build_an521_ninja/api_ns/。--parallel启用并行构建,未指定任务数时采用环境或底层构建工具的默认设置。
对应的 Ninja 原生命令如下,二选一执行即可。
ninja -C build_an521_ninja install
-C build_an521_ninja让 Ninja 进入该构建目录执行。install指定安装目标,构建并导出 NS 工程需要的文件。
install 会先构建固件,再把 NS 工程需要的接口、平台文件、签名材料和配置导出到 build_an521_ninja/api_ns/,无需 sudo。
主要输出如下。
build_an521_ninja/
├── bin/
│ ├── bl2.axf
│ ├── bl2.hex
│ ├── tfm_s.axf
│ └── tfm_s.bin
├── api_ns/
│ ├── bin/
│ ├── cmake/
│ ├── config/
│ ├── image_signing/
│ ├── interface/
│ └── platform/
└── compile_commands.json 开启导出后生成
清理
cmake --build build_an521_ninja --target clean
--build build_an521_ninja使用该目录中已有的构建规则。--target clean执行清理目标,删除编译产物及工程额外指定的生成文件,重新构建的步骤见后面的清理小节。
使用 Ninja 构建 Non-Secure
先完成前面 Ninja 方式的 Secure 构建和 install,再配置 NS 工程。
配置
cd /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/tf-m-extras/examples/tf-m-example-ns-app
source /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/env/bin/activate
cmake -S . -B build -G Ninja \
-DCONFIG_SPE_PATH="/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/build_an521_ninja/api_ns" \
-DTFM_TOOLCHAIN=GNUARM
-S .指定当前的 NS 示例源码目录。-B build指定 NS 构建目录,与 Secure 的构建目录分开。-G Ninja选择 Ninja 生成器。-DCONFIG_SPE_PATH=.../build_an521_ninja/api_ns指向对应 Secure 构建导出的接口、配置和签名材料。-DTFM_TOOLCHAIN=GNUARM选择 GNU Arm 工具链。
配置报错
如果 Secure 只使用前面的基本配置,尚未启用相关安全分区,NS 配置可能在生成阶段报错。
工具链警告出现在未指定 TFM_TOOLCHAIN 时;上面的命令已经指定 GNUARM,通常不会再出现这两条警告。
1/api_ns" -DTFM_TOOLCHAIN=GNUARM
-- The C compiler identification is GNU 14.3.1
-- The ASM compiler identification is GNU
-- Found assembler: /home/tyustli/Desktop/tools/toolchains/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc
-- Found Python3: /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/env/bin/python3 (found version "3.12.3") found components: Interpreter
-- Configuring done (0.2s)
CMake Error at /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/build_an521_ninja/api_ns/CMakeLists.txt:33 (add_library):
No SOURCES given to target: tfm_api_ns
解决方法
tfm_api_ns 的源文件由 Secure 启用的安全分区决定,相关分区全部关闭时,这个库就没有源文件。先重新配置 TF-M,启用安全分区并导出 NS 接口,再回到 NS 工程。
下面启用 Crypto、ITS、PS 和 Platform 的配置。示例调用 psa_generate_random(),需要 Crypto 及其依赖的 ITS。这里也把 MCUBOOT_IMAGE_NUMBER 改为 1,为后面的 Secure + NS 组合镜像做准备。
配置 TF-M
cd /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m
source env/bin/activate
cmake -S . -B build_an521_ninja -G Ninja \
-DTFM_PLATFORM=arm/mps2/an521 \
-DCMAKE_BUILD_TYPE=Debug \
-DMCUBOOT_IMAGE_NUMBER=1 \
-DTFM_PARTITION_CRYPTO=ON \
-DTFM_PARTITION_INTERNAL_TRUSTED_STORAGE=ON \
-DTFM_PARTITION_PROTECTED_STORAGE=ON \
-DTFM_PARTITION_PLATFORM=ON
-S .指定当前 TF-M 源码目录。-B build_an521_ninja更新原来的 Secure 构建目录,保留已下载的依赖。-G Ninja沿用 Ninja 生成器。-DTFM_PLATFORM=arm/mps2/an521选择 MPS2 AN521 平台。-DCMAKE_BUILD_TYPE=Debug使用调试构建。-DMCUBOOT_IMAGE_NUMBER=1将 Secure 和 NS 合并为一个镜像签名和验证,组合镜像仍然需要包含 NS 程序。-DTFM_PARTITION_CRYPTO=ON启用密码服务,包括示例使用的随机数生成。-DTFM_PARTITION_INTERNAL_TRUSTED_STORAGE=ON启用内部可信存储。-DTFM_PARTITION_PROTECTED_STORAGE=ON启用受保护存储。-DTFM_PARTITION_PLATFORM=ON启用平台相关的 PSA 服务。
配置完成的日志如下
----------- Secure Partitions ------------------------
Non-Secure Mailbox Agent OFF
Protected Storage Partition ON
TF-M Internal Trusted Storage Partition ON
TFM Crypto Partition ON
TFM Platform Partition ON
TFM Initial Attestation Partition OFF
TFM Firmware Update Partition OFF
------------------------------------------------------
编译 TF-M
cmake --build build_an521_ninja --parallel
--build build_an521_ninja根据新配置重新构建 Secure。--parallel启用并行构建。
安装 NS 接口
cmake --build build_an521_ninja --target install --parallel
--build build_an521_ninja使用刚才的 Secure 构建目录。--target install更新导出的 NS 接口、平台配置和签名材料,输出到build_an521_ninja/api_ns/。--parallel在需要补编译时启用并行构建。
install 本身会先构建再导出文件,也可以直接执行这一步,代替单独编译和安装两步。
重新配置 NS
cd /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/tf-m-extras/examples/tf-m-example-ns-app
cmake -S . -B build -G Ninja \
-U 'TFM_PARTITION_*' \
-DCONFIG_SPE_PATH="/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/build_an521_ninja/api_ns" \
-DTFM_TOOLCHAIN=GNUARM
-S .指定切换目录后的 NS 源码目录。-B build沿用原来的 NS 构建目录。-G Ninja沿用 Ninja 生成器。-U 'TFM_PARTITION_*'清除 NS 缓存中的旧分区配置,重新读取 Secure 导出的值。引号防止 Shell 展开通配符。-DCONFIG_SPE_PATH=.../build_an521_ninja/api_ns使用这次更新后的 Secure 导出接口。-DTFM_TOOLCHAIN=GNUARM继续使用 GNU Arm 工具链。
首次配置失败后,NS 缓存可能保留分区的 OFF 值。这里仅清除 NS 的这组缓存,无需删除 Secure 构建目录或重新下载依赖。
编译 NS
配置成功后,再执行编译。
cmake --build build --parallel
--build build构建配置完成的 NS 工程。--parallel启用并行构建。
查看产物
tree build -L 1
build指定要查看的 NS 构建目录。-L 1只显示目录下的第一层内容。
按上面的单镜像配置重新构建后,主要输出如下,其他缓存文件省略。
build/
├── bin/
├── build.ninja
├── spe/
├── tfm_s_ns_signed.bin
└── tfm_s_ns_signed.hex
bin/ 下还有 tfm_ns.axf 和 tfm_ns.bin。tfm_s_ns_signed.hex 包含 Secure 和 Non-Secure。修改 Secure 配置或代码后,先重新构建并安装 Secure,再重新配置、编译 NS,避免使用旧的导出文件。
QEMU 启动
前面的 NS 处理步骤将 MCUBOOT_IMAGE_NUMBER 设为 1,重新构建 Secure 和 NS 后,会得到 bl2.hex 和 tfm_s_ns_signed.hex。先从加载三个镜像时遇到的问题说起。
尝试加载三个镜像
把 BL2、单独的 Secure 镜像和 Secure + NS 组合镜像一起加载,命令如下。
qemu-system-arm \
-M mps2-an521 \
-cpu cortex-m33 \
-nographic \
-device loader,file="/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/build_an521_ninja/bin/bl2.hex" \
-device loader,file="/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/build_an521_ninja/bin/tfm_s_signed.hex" \
-device loader,file="/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/tf-m-extras/examples/tf-m-example-ns-app/build/tfm_s_ns_signed.hex"
-M mps2-an521选择 MPS2 AN521 开发板模型。-cpu cortex-m33指定 Cortex-M33 处理器。-nographic关闭图形窗口,将串口和监视器复用到当前终端。-device loader,file=.../bl2.hex加载 BL2 引导程序。-device loader,file=.../tfm_s_signed.hex加载单独的 Secure 签名镜像。-device loader,file=.../tfm_s_ns_signed.hex加载包含 Secure 和 NS 的组合签名镜像。
启动报错
同时加载这些镜像时,出现了下面的报错。
rom: requested regions overlap (rom /home/ub22/lx/qemu/tf-m-extras/examples/tf-m-example-ns-app/build/tfm_s_ns_signed.hex. free=0x0000000010090000, addr=0x0000000010080000)
qemu-system-arm: rom check and register reset failed
requested regions overlap 表示镜像要写入的内存区域发生重叠。QEMU 在检查镜像装载区域时失败,还没有运行到 BL2 验证固件的阶段。
原因分析
这条命令加载了三个 HEX 文件。
bl2.hex
tfm_s_signed.hex
tfm_s_ns_signed.hex
bl2.hex 是 BL2 引导程序,当前 AN521 构建中的起始地址为 0x10000000。
tfm_s_signed.hex 是单独的 Secure 签名镜像,当前 AN521 构建中的起始地址为 0x10080000。这个地址指镜像装载位置,固件入口还要考虑镜像头。
tfm_s_ns_signed.hex 在这里的单镜像配置下,包含 Secure 和 Non-Secure 两部分。其加载关系如下。
tfm_s_ns_signed.hex
= Secure + Non-Secure
因此,同时加载三个文件相当于下面的关系。
bl2.hex + tfm_s_signed.hex + tfm_s_ns_signed.hex
= BL2 + Secure +(Secure + Non-Secure)
Secure 区域被加载了两次,于是 QEMU 报地址重叠。报错中的 addr=0x0000000010080000 也对应这次冲突的装载地址。
HEX 文件本身带有装载地址,loader 会按文件中的地址放置数据,这里无需再指定 addr。
解决方法
删除加载 tfm_s_signed.hex 的那一项。
-device loader,file=.../build_an521_ninja/bin/tfm_s_signed.hex
只保留 bl2.hex 和 tfm_s_ns_signed.hex,分别加载引导程序和包含 Secure、NS 的组合签名镜像。
启动命令
qemu-system-arm \
-M mps2-an521 \
-cpu cortex-m33 \
-nographic \
-device loader,file="/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/build_an521_ninja/bin/bl2.hex" \
-device loader,file="/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/tf-m-extras/examples/tf-m-example-ns-app/build/tfm_s_ns_signed.hex"
-M mps2-an521选择 AN521 开发板模型。-cpu cortex-m33指定 Cortex-M33 处理器。-nographic在当前终端显示串口输出。- 第一个
-device loader,file=...加载 Ninja 构建的build_an521_ninja/bin/bl2.hex。 - 第二个
-device loader,file=...加载 NS 工程build/tfm_s_ns_signed.hex,其中已经包含 Secure。
镜像来自同一套配置时,启动后可以看到 BL2、TF-M 和 Hello TF-M world 的输出,完整日志保留在文末。
调试与退出
需要 GDB 调试时,在启动命令末尾追加 -S -s。
-S启动时暂停处理器,等待调试器连接后继续执行。-s开启 GDB 调试端口,等价于-gdb tcp::1234。
退出 QEMU 使用 Ctrl+A,松开后按 X。
日常修改与重新构建
只修改源码
直接增量编译即可,不必先 clean。以 Ninja 为例。
cd "/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m"
cmake --build build_an521_ninja --target install --parallel
cd "/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/tf-m-extras/examples/tf-m-example-ns-app"
cmake -S . -B build
cmake --build build --parallel
--build build_an521_ninja增量构建 Secure,只重新处理受修改影响的目标。--target install更新导出的 NS 接口及相关文件。-S .指定切换目录后的 NS 工程为源码目录。-B build使用 NS 已有的构建目录,重新读取 Secure 导出的配置。--build build增量构建 NS。--parallel启用并行构建,分别用于两次构建。
修改配置
在原构建目录上重新运行 CMake,修改需要改变的 -D 参数,然后重新编译。已有缓存会保留其余配置和依赖路径。
cd "/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m"
cmake -S . -B build_an521_ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build_an521_ninja --target install --parallel
-S .指定当前 TF-M 源码目录。-B build_an521_ninja在原构建目录上更新配置,保留未修改的缓存项。-DCMAKE_BUILD_TYPE=Debug将构建类型设置为 Debug。--build build_an521_ninja按更新后的配置构建。--target install更新固件和导出的 NS 接口。--parallel启用并行构建。
通常不需要删除 CMakeCache.txt。删缓存会丢失原先的配置与本地依赖路径,恢复配置时还需要重新提供完整参数。
重新配置后分区仍显示 ON
之前通过 -DTFM_PARTITION_CRYPTO=ON 等参数启用分区后,再执行基本配置命令,分区仍可能显示 ON。
cd /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m
cmake -S . -B build_an521_ninja -G Ninja \
-DTFM_PLATFORM=arm/mps2/an521 \
-DCMAKE_BUILD_TYPE=Debug
-S .指定当前 TF-M 源码目录。-B build_an521_ninja复用已有的构建目录和配置缓存。-G Ninja沿用 Ninja 生成器。-DTFM_PLATFORM=arm/mps2/an521指定目标平台。-DCMAKE_BUILD_TYPE=Debug设置调试构建,其他未指定的缓存项继续保留。
----------- Secure Partitions ------------------------
Non-Secure Mailbox Agent OFF
Protected Storage Partition ON
TF-M Internal Trusted Storage Partition ON
TFM Crypto Partition ON
TFM Platform Partition ON
TFM Initial Attestation Partition OFF
TFM Firmware Update Partition OFF
原因
-D 设置的配置会写入 build_an521_ninja/CMakeCache.txt。再次配置同一个构建目录时,CMake 会读取这些缓存。命令中省略之前的分区参数,只表示这次不修改它们,已经保存的 ON 会继续生效。
这里显示的是之前保存的配置。当前基本配置中这些分区的初始值为 OFF,重新运行 CMake 不会自动恢复初始值,普通 clean 也不会重置配置缓存。
查看缓存
grep 'TFM_PARTITION' build_an521_ninja/CMakeCache.txt
之前启用过这四个分区时,可以看到类似内容。
TFM_PARTITION_CRYPTO:BOOL=ON
TFM_PARTITION_INTERNAL_TRUSTED_STORAGE:BOOL=ON
TFM_PARTITION_PLATFORM:BOOL=ON
TFM_PARTITION_PROTECTED_STORAGE:BOOL=ON
显式改回 OFF
只想关闭这些分区时,直接覆盖缓存,不需要删除构建目录。
cmake -S . -B build_an521_ninja -G Ninja \
-DTFM_PLATFORM=arm/mps2/an521 \
-DCMAKE_BUILD_TYPE=Debug \
-DTFM_PARTITION_CRYPTO=OFF \
-DTFM_PARTITION_INTERNAL_TRUSTED_STORAGE=OFF \
-DTFM_PARTITION_PLATFORM=OFF \
-DTFM_PARTITION_PROTECTED_STORAGE=OFF
-S .指定 TF-M 源码目录。-B build_an521_ninja更新已有构建目录,保留其他缓存和已下载的依赖。-G Ninja沿用 Ninja 生成器。-DTFM_PLATFORM=arm/mps2/an521保持 AN521 平台。-DCMAKE_BUILD_TYPE=Debug保持调试构建。-DTFM_PARTITION_CRYPTO=OFF关闭 Crypto 分区。-DTFM_PARTITION_INTERNAL_TRUSTED_STORAGE=OFF关闭 ITS 分区。-DTFM_PARTITION_PLATFORM=OFF关闭 Platform 分区。-DTFM_PARTITION_PROTECTED_STORAGE=OFF关闭 PS 分区。
重新配置后,上面四项会显示 OFF。配置命令只更新构建规则,实际固件还要重新编译。后续运行前面的 NS 随机数示例时,需要按 NS 章节重新启用所需分区,并重新构建、导出接口。
删除整个构建目录后重新配置
需要从头配置时,可以删除整个构建目录,再执行基本配置命令。
cd /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m
rm -rf build_an521_ninja
cmake -S . -B build_an521_ninja -G Ninja \
-DTFM_PLATFORM=arm/mps2/an521 \
-DCMAKE_BUILD_TYPE=Debug
rm -rf build_an521_ninja删除整个构建目录,包括缓存、编译产物和目录内下载的依赖源码。-S .指定 TF-M 源码目录。-B build_an521_ninja创建新的构建目录。-G Ninja重新生成 Ninja 构建规则。-DTFM_PLATFORM=arm/mps2/an521重新指定平台。-DCMAKE_BUILD_TYPE=Debug重新指定构建类型。
这会清除该目录保存的全部配置。自动下载的依赖通常位于 build_an521_ninja/lib/ext/,删除整个目录后,下次配置需要重新下载;使用构建目录外的本地依赖时,需要重新提供对应的路径配置。只改分区开关时,优先使用前面的显式覆盖方法。
删除构建目录,但是保留外部下载的代码
将构建目录除了 build_an521_ninja/lib/ext 目录下的所有文件夹都删除,只保留这个文件夹,重新构建的时候加入下面的编译选项,
FETCHCONTENT_FULLY_DISCONNECTED=ON
这个编译选项的作用是强制离线,禁止自动下载
需要清理产物时
Ninja 清理后,先重新配置,再构建。TF-M 的 clean 会删除 generated/ 等生成文件,重新配置可以补齐这些文件。
cd "/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m"
cmake --build build_an521_ninja --target clean
cmake -S . -B build_an521_ninja
cmake --build build_an521_ninja --target install --parallel
--build build_an521_ninja使用 Secure 的构建目录执行指定目标。--target clean清理编译产物及额外生成文件。-S .指定 TF-M 源码目录,重新运行配置。-B build_an521_ninja沿用已有构建目录和缓存,重新生成被 clean 删除的配置产物。--target install重新构建并导出 NS 接口。--parallel启用并行构建。
原生清理命令为 ninja -C build_an521_ninja clean。
-C build_an521_ninja指定 Ninja 执行清理的构建目录。clean执行清理目标。
遇到的问题
pip 提示不是 Python 工程
ERROR: file:///home/tyustli/Desktop/tyustli/study/code/qemu does not appear to be a Python project: neither 'setup.py' nor 'pyproject.toml' found.
这是在外层 qemu 目录执行 python -m pip install -e . 导致的。切换到 TF-M 源码目录,再使用已有的 env 安装。
cd /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m
source env/bin/activate
python -m pip install -e .
找不到 imagesign_wrapper
/bin/sh: 1: mcuboot_imagesign_wrapper: not found
先激活环境并安装 TF-M 自己的 Python 包,再继续原来的构建。
cd "/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m"
source env/bin/activate
python -m pip install -e .
command -v mcuboot_imagesign_wrapper
command -v mcuboot_imagesign_assemble
cmake --build build_an521_ninja --target install --parallel
--build build_an521_ninja在安装 Python 工具后继续构建原来的 Secure 工程。--target install构建固件并更新导出的 NS 接口。--parallel启用并行构建。
如果激活 env 后仍使用系统 Python,再指定虚拟环境中的解释器。
cmake -S . -B build_an521_ninja \
-DPython3_EXECUTABLE="/home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m/env/bin/python"
cmake --build build_an521_ninja --target install --parallel
-S .指定当前 TF-M 源码目录。-B build_an521_ninja更新原构建目录中的 Python 配置。-DPython3_EXECUTABLE=.../env/bin/python指定 CMake 使用 env 中的 Python 解释器运行相关脚本。--build build_an521_ninja按更新后的配置继续构建。--target install构建并导出 NS 接口。--parallel启用并行构建。
NS 工程遇到相同问题时,在 NS 目录执行 cmake -S . -B build 并追加同一个 -DPython3_EXECUTABLE 参数。签名命令本身还需要能从 PATH 找到,所以构建时也要保持 env 已激活。
BL2 找不到可启动镜像
[INF] Starting bootloader
[INF] Beginning BL2 provisioning
[WRN] TFM_DUMMY_PROVISIONING is not suitable for production! This device is NOT SECURE
[INF] PSA Crypto init done, sig_type: EC-P256, using builtin keys
[INF] Image index: 1, Swap type: none
[ERR] Image in the primary slot is not valid!
[ERR] Unable to find bootable image
MCUBOOT_IMAGE_NUMBER=2 时,BL2 分别验证 Secure 和 Non-Secure。只加载 Secure,没有有效的 NS 镜像,就可能在 Image index: 1 报错。
这里改用 MCUBOOT_IMAGE_NUMBER=1,将 Secure 与 Non-Secure 合并后作为一个镜像签名和验证。
在原构建目录上修改配置,然后重新构建、安装 Secure,再编译 NS。
cd /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/trusted-firmware-m
cmake -S . -B build_an521_ninja -DMCUBOOT_IMAGE_NUMBER=1
cmake --build build_an521_ninja --target install --parallel
cd /home/tyustli/Desktop/tyustli/study/code/qemu/trust_firmware/tfm/code/tf-m-extras/examples/tf-m-example-ns-app
cmake -S . -B build
cmake --build build --parallel
-S .分别指定cd后的 Secure 或 NS 源码目录。-B build_an521_ninja更新 Secure 原有构建目录中的配置。-DMCUBOOT_IMAGE_NUMBER=1将 Secure 和 NS 合并为一个镜像签名,由 BL2 按单镜像方式验证。--build build_an521_ninja重新构建 Secure。--target install更新 NS 所需的导出文件和镜像配置。-B build重新配置 NS,使其读取新的 Secure 导出配置。--build build重新构建 NS,生成组合签名镜像。--parallel启用并行构建。
这时生成新的 tfm_s_ns_signed.hex,再用前面的 QEMU 命令启动。只修改成 1,再加载一个旧的或仅含 Secure 的镜像,不能代替完整的 S + NS 镜像。
同时检查 QEMU 加载的是签名镜像,而不是未经签名的 tfm_s.bin / tfm_ns.bin,并确保 BL2 与镜像使用相同配置。
构建目录或生成器不匹配
进入源码目录后,使用 cmake --build build_an521_ninja。只有当前目录就是构建目录时,才能使用 cmake --build .。
该构建目录使用 Ninja,构建规则保存在 build.ninja。遇到生成器不匹配时,应使用原来的 Ninja 生成器,或另建构建目录。
完整启动日志
构建时间和随机数每次可能不同,程序最后停留在循环中,需要手动退出 QEMU。
[INF] Starting bootloader
[INF] Beginning BL2 provisioning
[WRN] TFM_DUMMY_PROVISIONING is not suitable for production! This device is NOT SECURE
[INF] PSA Crypto init done, sig_type: EC-P256, using builtin keys
[INF] Image index: 0, Swap type: none
[INF] Bootloader chainload address offset: 0x80000
[INF] Image version: v2.3.0
[INF] Jumping to the first image slot
[NOT] Booting TF-M v2.3.0
[NOT] Built Fri 12 Jun 2026 11:16:33 UTC
[INF] Beginning TF-M provisioning
[WRN] TFM_DUMMY_PROVISIONING is not suitable for production! This device is NOT SECURE
[WRN] This device was provisioned with dummy keys. This device is NOT SECURE
[VER] Isolation level is: 1
Creating an empty ITS flash layout.
Creating an empty PS flash layout.
[INF] [Crypto] Provision entropy seed...
[INF] [Crypto] Provision entropy seed... complete.
[VER] [Crypto] Init TF-PSA-Crypto 1.1.0...
[VER] [Crypto] Internal heap size is 12288 bytes
[VER] [Crypto] Init TF-PSA-Crypto 1.1.0... complete.
[INF] [PS] Encryption alg: 0x5500200
Non-Secure system starting...
Hello TF-M world
PSA Framework Version = 1.1
Testing psa get random number...
1: psa_generate_random() = 108
2: psa_generate_random() = 53
3: psa_generate_random() = 110
4: psa_generate_random() = 151
5: psa_generate_random() = 54
End of TF-M example App
日志中的 dummy provisioning / dummy keys 表示使用了演示密钥。它不影响这里的功能学习,不能作为生产设备的安全配置。
本文详细介绍了使用Ninja构建ARM TrustZone-M(TF-M)Secure和Non-Secure固件的完整流程,涵盖CMake配置、NS接口导出、依赖管理、增量编译、QEMU单镜像加载启动及常见问题排查。重点解决镜像地址重叠、分区配置残留、imagesign_wrapper缺失、BL2验证失败等典型构建与运行问题,并强调MPS2 AN521平台下Secure+NS组合镜像的正确生成与加载方法。

441

被折叠的 条评论
为什么被折叠?



