TF-M and QEMU 4.0 (Zephyr)
This guide walks you through the process of buildng a TF-M secure binary with IPC support, and Zephyr-based non-secure binary, merging the outputs into a single file, and running the resulting firmware image in QEMU 4.0.
The tutorial is based on:
- The upstream TF-M code at https://git.trustedfirmware.org/trusted-firmware-m.git/ (commit: bba856401c7eb5d66d170c3ba96b9cfa8e955a2a)
- Zephyr PR #16450
For system requirements to build TF-M, see `tfm_build_instruction.txt
` in the tf-m `docs
` folder (system setup is out of scope for this guide).
Clone Zephyr Based on PR #16450
To setup a clean Zephyr installation on your system based on PR #16450, make sure west is installed on your system and run the following commands:
$ west init -m https://github.com/karl-zh/zephyr.git --mr mps2_an521_support_tfm_ipc zephyr $ cd zephyr $ west update $ source zephyr/zephyr-env.sh
Copy Build Scripts
Next, place the following two build scripts in the zephyr/samples/tfm_integration folder:
$ cd zephyr/samples/tfm_integration $ wget https://gist.githubusercontent.com/microbuilder/d40905d533d29a3745370e8650dde880/raw/01d5bbfbcb1ba7c7fbc8f4d612f9e553b34898e8/tfm-build.sh $ wget https://gist.githubusercontent.com/microbuilder/bc7eb0dc9e65de3cd99e65c31f836ef2/raw/efe3105c4a5acbf9a116ae2f2b46ad9457601d7f/tfm-run.sh $ chmod +x tfm-build.sh $ chmod +x tfm-run.sh
Build TF-M Secure Binary with IPC Support
This demo makes use of the ConfigRegressionIPC.cmake config file to enable to test service ID at address 0x1000.
It assumes that your system meets the requirements for TF-M builds, and will clone all repos required for a TF-M build (CMSIS 5, mbedcrypto, mbedtls).
These commands assume you are running from the zephyr/samples/tfm_integration folder.
$ ./tfm-build.sh
This should (eventually) result in the following output if everything was downloaded correctly:
... -- Installing: /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/ext/tfm/build/install/outputs/AN521/tfm_s.bin -- Installing: /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/ext/tfm/build/install/outputs/fvp/tfm_s.axf -- Installing: /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/ext/tfm/build/install/outputs/fvp/tfm_s.bin -- Installing: /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/ext/tfm/build/install/export/tfm/test/inc/test_framework_integ_test.h -- Installing: /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/ext/tfm/build/install/export/tfm/test/inc/os_wrapper.h -- Installing: /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/ext/tfm/build/install/export/tfm/test/inc/tfm_secure_client_service_api.h -- Installing: /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/ext/tfm/build/install/export/tfm/test/lib/libtfm_non_secure_tests.a
Next, build the Zephyr application image and merge the resulting non-secure binary with the secure trusted-firmware binary built above:
$ ./tfm-run.sh
The above command will also execute the merged secure and non-secure binary in QEMU 4.0, and assumes qemu-system-arm is available in the system's PATH environment variable.
If everything built, merged and executed correctly, you should get the following output from QEMU:
Found 'install' dir Zephyr version: 1.14.99 -- Found PythonInterp: /usr/local/bin/python3 (found suitable version "3.7.3", minimum required is "3.4") -- Selected BOARD mps2_an521_nonsecure -- Found west: /usr/local/bin/west (found suitable version "0.5.7", minimum required is "0.5.6") -- Loading /Users/kevin/Downloads/test/zephyr/zephyr/boards/arm/mps2_an521/mps2_an521_nonsecure.dts as base -- Overlaying /Users/kevin/Downloads/test/zephyr/zephyr/dts/common/common.dts Parsing Kconfig tree in /Users/kevin/Downloads/test/zephyr/zephyr/Kconfig Loading /Users/kevin/Downloads/test/zephyr/zephyr/boards/arm/mps2_an521/mps2_an521_nonsecure_defconfig as base Merging /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/prj.conf Configuration written to '/Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/build/zephyr/.config' -- Cache files will be written to: /Users/kevin/Library/Caches/zephyr -- The C compiler identification is GNU 7.3.1 -- The CXX compiler identification is GNU 7.3.1 -- The ASM compiler identification is GNU -- Found assembler: /usr/local/prog/gcc-arm-none-eabi-7-2018-q2-update/bin/arm-none-eabi-gcc -- Performing Test toolchain_is_ok -- Performing Test toolchain_is_ok - Success Including module: tinycbor in path: /Users/kevin/Downloads/test/zephyr/modules/lib/tinycbor -- Configuring done -- Generating done -- Build files have been written to: /Users/kevin/Downloads/test/zephyr/zephyr/samples/tfm_integration/build [1/112] Preparing syscall dependency handling [107/112] Linking C executable zephyr/zephyr_prebuilt.elf Memory region Used Size Region Size %age Used FLASH: 14300 B 223 MB 0.01% SRAM: 4284 B 1 MB 0.41% IDT_LIST: 200 B 2 KB 9.77% [112/112] Linking C executable zephyr/zephyr.elf Starting QEMU (CTRL+C to quit) [Sec Thread] Secure image initializing! [Sec Thread] hello! this is ipc client test sp! [Sec Thread] Connect success! [Sec Thread] Call success! ***** Booting Zephyr OS v1.12.0-rc1-9626-g631c72ca2015 ***** The version of the PSA Framework API is 256. The minor version is 1. Connect success! TFM service support minor version is 1. psa_call is successful! outvec1 is: It is just for IPC call test. outvec2 is: It is just for IPC call test. Hello World! mps2_an521_nonsecure