This article is a guideline to support secure project on Arm®-Cortex®-M33 core contained in the STM32MP25. The STM32MP25 support is provided in the release v1.16.0 of STM32CubeIDE.
It relies onto the project trusted-firmware-m, It can be used from Linux® workstation.
This article focus on how to build secure firmware - trusted firmware-m together with nonsecure firmware and debug them.
1. Prerequisites[edit source]
1.1. Hardware prerequisites[edit source]
- STM32MP257F-EV1 Rev C,
- Linux® console,
- Ethernet (or Ethernet over USB) for connection of PC workstation to Linux® Arm®-Cortex®-A .
For more information, refer to Getting started/STM32MP2 boards/STM32MP257x-EV1/Let's start/Unpack the STM32MP257x-EV1 board.
1.2. Software prerequisites[edit source]
- Starter Package installed and STM32MP25 Evaluation board is booted with the Starter Package. Please refer to Populate the target and boot the image
- STM32CubeIDE v1.16.0, available from st.com installed,
- Install build environment and python dependencies for TF-M as described in How to configure TF-M prerequisites chapter.
- Install python libraries needed by OP-TEE signature python script
pip install pyelftools pip install pycryptodomex
Information |
The project created has the name MP2 on the screenshots and texts , dont forgot to make needed updates with your project. |
2. Create CM33_trusted-firmware-m project[edit source]
CM33_trusted-firmware-m project need to be created uder CM33
Create MP2 project with TZ=1 using MP257F-EV1 board
2.1. MP2 stm32cube project with STM32CubeIDE with TZ=1[edit source]
MP2 stm32cube project is created from STM32CubeIDE using menu:
File > New STM32 Project...
Then, select Board selector MP2 MP257F-EV1... Next stm32cube Finish
Right clic on ProjectName_CM33 > Create a STM32 Cmake Project using existing Cmake sources
Then, set Import source using Directory... to the trusted-firmware-m selecting:
Note that trusted-firmware-m project is need to be cloned available from STM32Cube repository on local disk or from {{***************}.
Resulting project structure under CM33 contains three projects:
- Device Tree, contain the tf-m device tree from STM32CubeMX,
- MP2_CM33_NonSecure, HAL-based project addressing non-secure part of application,
- MP2_CM33_trusted-firmware-m, pre-set STM32CubeIDE CMake project for TF-M, with link to sources: trusted-firmware-m pointing to cloned from :
Projects/STM32MP257F-EV1/Applications/TFM/TFM_Protected_Storage .
- STM32CubeIDE debug information for CMake project
2.2. MP2_CM33_trusted-firmware-m - final setup[edit source]
The only missing element is the access to trusted-firmware-m project source files.
As depicted here after, trusted-firmware-m link inside STM32CubeIDE project point to a path that has to be populated:
To populate it please follow Install Sources chapter from How to configure TF-M article.
Now you can refresh STM32CubeIDE project and view sources.
CMake trusted-firmware-m project need to defice CMake setting for:
- STM32MP257F-EV1 board - CMake project usage setting
-DTFM_PLATFORM=stm/stm32mp257f_ev1 -DTFM_TOOLCHAIN_FILE=toolchain_GNUARM.cmake -DTFM_PROFILE=profile_medium -DCMAKE_BUILD_TYPE=debug -DDTS_BOARD=arm/stm/stm32mp257f-ev1-revB_s.dts -DDTS_EXT_DIR=/MP2_CM33/DeviceTree/MP2/tf-m -DNS=OFF
3. Build[edit source]
Now it is possible to build MP2_CM33_trusted-firmware-m:
Note that a post-build :
Note that a post-build command is must be defined by used :
there are three options need to be updated on post build command :
- workspace_loc workspace_loc:/MP2_CM33_trusted-firmware-m/trusted-firmware-m/config_default/bin/tfm_s.elf
- Key /local/home/username/STM32CubeIDE/workspace_1.16.0/MP2/CA35/optee_os-3.19.0/optee-os-stm32mp-3.19.0-stm32mp-r2/keys/default.pem
- python /local/home/username/STM32CubeIDE/workspace_1.16.0/MP2/CA35/optee_os-3.19.0/optee-os-stm32mp-3.19.0-stm32mp-r2/scripts/sign_rproc_fw.py
In order to get key and python script user must install OpenSTlinux sources plugin , SDK on disk , then import optee project and compile it's targets .
arm-none-eabi-objcopy -S ${workspace_loc:/MP2_CM33_trusted-firmware-m/trusted-firmware-m/config_default/bin/tfm_s.elf} tfm_s_stripped.elf; arm-none-eabi-objcopy -S ${BuildArtifactFileBaseName}.elf ${BuildArtifactFileBaseName}_stripped.elf; python /local/home/username/STM32CubeIDE/workspace_1.16.0/MP2/CA35/optee_os-3.19.0/optee-os-stm32mp-3.19.0-stm32mp-r2/scripts/sign_rproc_fw.py --in ${BuildArtifactFileBaseName}_stripped.elf --in tfm_s_stripped.elf --out ${BuildArtifactFileBaseName}_tfm_s_sign.bin --key /local/home/username/STM32CubeIDE/workspace_1.16.0/MP2/CA35/optee_os-3.19.0/optee-os-stm32mp-3.19.0-stm32mp-r2/keys/default.pem --plat-tlv BOOTADDR 0x80000000 --plat-tlv BOOTSEC 0x1
Note that a post-build command is used to generated the bin object from the two sub-project elf:
- MP2_CM33_NonSecure_stripped.elf
- MP2_CM33_trusted-firmware-m/trusted-firmware-m/config_default/bin/tfm_s.elf
Select MP2_CM33_NonSecure project. This project has only one build configuration CA35TDCID_m33_ns_tfm_s_sign.
Build can be done using standard Eclipse "Build icon", it will generate MP2_CM33_NonSecure_tfm_s_sign.bin, visible after a project refresh.
4. Debugging[edit source]
4.1. Prerequisite to debug[edit source]
Target is to debug in "production mode".
STM32MP257F-EV1 must be up and running, and connected to the workstation via network & console.
SD-Card has been initialized with Starter Package version 24-06-26.
The Cortex-M33 Secure and non secure firmware image are encapsulated and signed. The resulting binary file "MP2_CM33_NonSecure_tfm_s_sign.bin" has to be loaded by OP-TEE. To check OP-TEE security capabilities of the board, execute following command, into Linux console:
cat /sys/class/remoteproc/remoteproc0/fw_format
that should return "TEE".
Before using production mode debug, proxy network must be adjusted, for that refer to How to set up proxy and P2P Ethernet connection with STM32CubeIDE.
Target Status on the bottom right must show a green light, refer to How_to_use_the_Target_Status_widget_in_STM32CubeIDE.
4.2. Loading .bin object[edit source]
The generated ".bin" object has to be downloaded to STM32MP257F-EV1 and loaded via remoteproc framework.
This is done thanks to a "Run Configuration" set in Production Mode.
In order to successfully load .bin we need to remove the fw_corte_m.sh
-root@stm32mp2:/usr/local/projects/MP2_CM33_NonSecure# ls -l total 3 -rw-rw-r-- 1 root root 368 Mar 3 14:51 README -rwxrwxr-x 1 root root 750 Mar 3 14:51 fw_cortex_m4.sh drwxr-xr-x 3 root root 1024 Mar 3 14:50 lib root@stm32mp2:/usr/local/projects/MP2_CM33_NonSecure# rm -rf * root@stm32mp2:/usr/local/projects/MP2_CM33_NonSecure#
4.2.1. Run configuration setup[edit source]
Select MP2_CM33_NonSecure project and right click on Run As > Run Configurations...
Double click onSTM32 C/C++ Application to create a configuration.
- In "main" tab:
- "Workspace..." button allows to select ".bin" file
- In "Debugger" tab:
- "Load mode" should be "thru Linux core" (Production mode)
- and for limitation reason, "GDB Connection Settings" should be "Connect to remote GDB server".
It is recommended to enrich the default "Run Configuration" name with for example (Run Cfg - Load).
This is to distinguish from Debug Configuration.
4.2.2. Run[edit source]
Make run with this configuration in order transfer .bin and load it.
Here is the transfer pop up:
Open a console inside STM32CubeIDE in order to check that firmware has been loaded and is running on Arm®-Cortex®-M33:
- cat /sys/class/remoteproc/remoteproc0/firmware
- cat /sys/class/remoteproc/remoteproc0/state
In case of problem follow chapter How to trace and debug the framework from Linux remoteproc framework overview article.
4.3. Debugging Secure and Non Secure firmware[edit source]
For debugging those firmwares the debug configuration has to reference both secure and non secure ELF files.
4.3.1. Debug configuration setup[edit source]
Select MP2_CM33_NonSecure project and right click on Debug As > C/C++ STM32 Application
This menu creates a debug configuration for the selected project.
It is recommended to enrich the default "Debug Configuration" name with for example (Debug Cfg). This is to distinguish from Run Configuration.
In "Startup" tab
- edit NonSecure elf and unset Download
- Add TF-M elf definition with "Add" menu, and:
- program path to: trusted-firmware-m/config_default/bin/tfm_s.elf,
- disable "Download"
- give "ARM.exidx" file offset "0x9c40". The file offset address is retrieved from tfm-s.elf:
- program path to: trusted-firmware-m/config_default/bin/tfm_s.elf,
readelf -a tfm_s.elf | grep "Unwind section '.ARM.exidx' at offset" Unwind section '.ARM.exidx' at offset 0x9c40 contains 1 entry:
- or
objdump -hw ./config_default/bin/tfm_s.elf | grep ".ARM.exidx" 17 .ARM.exidx 00000008 80008c40 80008c40 00009c40 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
Information |
A way to control entry point of debug session could be to add a debug loop. In picture hereafter a debug loop has been added at the begining of tfm_hal_platform_init() MP2_CM33_trusted-firmware-m/trusted-firmware-m/platform/ext/target/stm/common/stm32mp2/secure/tfm_hal_platform.c. Debug session will start inside this debug loop and changing i variable to 0 it will be possible to step into tfm initialization code. |
4.3.2. Debug[edit source]
Launching the debug configuration, it is recommended to select Switch to the Confirm Perspective Switch in order to enter "Debug Eclipse perspective". Then thanks to "Suspend" icon, the control of Arm®-Cortex®-M33 execution can be taken. First instructions are while loop onto a volatile variable, this allows to take control from code start.