This guide walks you through building and running QEMU emulation using the Teaclave TrustZone SDK.
We provide a Docker image with prebuilt QEMU and OP-TEE images to streamline the entire Trusted Application (TA) development workflow. The image allows developers to build TAs and emulate a guest virtual machine (VM) that includes both the Normal World and Secure World environments.
Terminal A (Main development terminal):
# Pull the pre-built development environment $ docker pull teaclave/teaclave-trustzone-emulator-nostd-optee-4.5.0-expand-memory:latest # Clone the repository $ git clone https://github.com/apache/teaclave-trustzone-sdk.git && \ cd teaclave-trustzone-sdk # Launch the development container $ docker run -it --rm \ --name teaclave_dev_env \ -v $(pwd):/root/teaclave_sdk_src \ -w /root/teaclave_sdk_src \ teaclave/teaclave-trustzone-emulator-nostd-optee-4.5.0-expand-memory:latest
Still in Terminal A (inside the Docker container):
# Build the Hello World example (both CA and TA) make -C examples/hello_world-rs/
Under the hood, the Makefile builds both the Trusted Application (TA) and the Host Application separately. After a successful build, you'll find the resulting binaries in the hello_world-rs
directory:
TA=ta/target/aarch64-unknown-linux-gnu/release/133af0ca-bdab-11eb-9130-43bf7873bf67.ta HOST_APP=host/target/aarch64-unknown-linux-gnu/release/hello_world-rs
After building the Hello World example, the next step is to make the compiled artifacts accessible to the emulator.
There are two approaches to do this. You can choose either based on your preference:
make emulate
to build and sync in one stepsync_to_emulator
We provide a helper command called sync_to_emulator
, which simplifies the process of syncing the build outputs to the emulation environment. Run the following commands inside the container:
sync_to_emulator --ta $TA sync_to_emulator --host $HOST_APP
Run sync_to_emulator -h
for more usage options.
For convenience during daily development, the sync invocation can be integrated into the Makefile. In the hello_world-rs
example, an emulate
target is provided. This helps automatically build the artifacts and sync them to the emulator in one step:
make -C examples/hello_world-rs/ emulate
The emulation workflow requires three additional terminals to monitor various aspects of the system:
Built-in commands are provided in the Docker image. These commands are located in /opt/teaclave/bin/
and are included in the default user's $PATH.
You may use bash -l
or the full path when executing with docker exec.
Terminal B (Guest VM Shell):
# Connect to the guest VM shell for running commands inside the emulated environment $ docker exec -it teaclave_dev_env bash -l -c listen_on_guest_vm_shell # Alternative: Use full path $ docker exec -it teaclave_dev_env /opt/teaclave/bin/listen_on_guest_vm_shell
Terminal C (Secure World Output Monitor):
# Monitor Trusted Application output logs in real-time $ docker exec -it teaclave_dev_env bash -l -c listen_on_secure_world_log # Alternative: Use full path $ docker exec -it teaclave_dev_env /opt/teaclave/bin/listen_on_secure_world_log
After the listeners are set up, we can start the QEMU emulator.
Terminal D (QEMU Control):
# Launch QEMU emulator with debug output and connect to monitoring ports $ docker exec -it teaclave_dev_env bash -l -c "LISTEN_MODE=ON start_qemuv8"
⏳ Wait for the QEMU environment to fully boot... You should see boot messages in Terminal D and the guest VM shell prompt in Terminal B.
After QEMU in Terminal D successfully launches, switch to Terminal B, which provides shell access to the guest VM's normal world.
Terminal B (Inside Guest VM): From this shell, you'll find that the artifacts synced in Step 3 are already available in the current working directory. Additionally, the ta/
and plugin/
subdirectories are automatically mounted to be used by TEE OS during TA execution and plugin loading.
For more details on the mount configuration, refer to the listen_on_guest_vm_shell
command in the development environment.
# tree . |-- host | `-- hello_world-rs |-- plugin `-- ta `-- 133af0ca-bdab-11eb-9130-43bf7873bf67.ta 3 directories, 2 files
This makes it especially convenient for iterative development and frequent code updates.
Now we are ready to interact with the TA from normal world shell.
# Execute the Hello World Client Application $ ./host/hello_world-rs
The secure world logs, including TA debug messages, are displayed in Terminal C.
During active development and debugging, you can leave Terminals B, C, and D open to avoid restarting them each time. Simply return to Terminal A, and repeat Step 2 (build) and Step 3 (sync) to rebuild and update the artifacts. Once synced, switch to Terminal B to re-run the client application. This setup streamlines iterative development and testing.
By following this guide, you can emulate and debug Trusted Applications using our pre-configured Docker-based development environment.
Together, these terminals provide a complete and efficient workflow for TrustZone development and emulation.
The setup scripts and built-in commands can be found in /opt/teaclave/
. Please refer to the Dockerfile in the SDK source repository for more information about how we set up the development environment.