Skip to content

Trusted Firmware-M

Overview

Trusted Firmware-M (TF-M) implements the Secure Processing Environment (SPE) for Armv8-M, Armv8.1-M architectures (e.g. the Cortex-M33, Cortex-M23, Cortex-M55, Cortex-M85 processors) or dual-core platforms. It is the platform security architecture reference implementation aligning with PSA Certified guidelines, enabling chips, Real Time Operating Systems and devices to become PSA Certified.

A software stack running Trusted Firmware-M consists of three exectuable binaries:

  • the bootloader, known as BL2
  • the secure firmware, which is the Trusted Firmware
  • the non-secure firmware, which is the user application

The non-secure firmware can make API calls (such as cryptography, protected storage, etc.) to the secure firmware via a library known as the NS (non-secure) interface.

Fetching

In your application's CMakeLists.txt, list trusted-firmware-m in IOTSDK_FETCH_LIST, alongside any other components you need to fetch:

set(IOTSDK_FETCH_LIST
    ...
    trusted-firmware-m
)

💡 This must be done before your application's CMakeLists.txt adds the Open IoT SDK.

Configuration

You also need to specify a list of Trusted Firmware-M configuration options in TFM_CMAKE_ARGS, for example:

set(TFM_CMAKE_ARGS
    -D TFM_PLATFORM=arm/mps3/an552
)

💡 You must always set TFM_PLATFORM according to your target platform, which is arm/mps3/an552 (for Corstone-300) in the above snippet. The official list of platforms is documented in the TF-M Platforms webpage.

Additionally, your application may require more options to be set depending on what features it needs:

This must be done before your application's CMakeLists.txt adds the Open IoT SDK.

💡 For our reference platforms, Corstone-300 and Corstone-310, you can find their TFM_PLATFORM values in templates/platforms.cmake as corstone-300-TFM_PLATFORM and corstone-310-TFM_PLATFORM respectively.

Build dependency

Trusted Firmware-M must be built before your application, because your application depends on the NS interface (described in the Overview section) and the BL2 signing scripts, both of which are generated as parts of the Trusted Firmware-M build process. To ensure the order is correct, call add_dependencies() in your CMakeLists.txt:

add_dependencies(my_application trusted-firmware-m-build)

💡 Replace my_application with the actual name of your application executable.

Linking

You need to link your application against one of the following libraries:

  • tfm-ns-interface-bare-metal, if your application is single-threaded
  • tfm-ns-interface-cmsis-rtos, if your application threads are based on the CMSIS-RTOS v2 API
  • tfm-ns-interface-threadx, if your application threads are based on AzureRTOS ThreadX

Image signing

Your non-secure application image must be signed using the signing script from Trusted Firmware-M. In the signed image, the exectuable binary is prepended with a header area containing information such as the image size, version, checksum, signature, etc. The bootloader uses this information to validate the image during the boot process.

To sign your application image, you can include the module SignTfmImage from the Open IoT SDK and call the helper function iotsdk_tf_m_sign_image() in your CMakeLists.txt:

list(APPEND CMAKE_MODULE_PATH ${open-iot-sdk_SOURCE_DIR}/components/trusted-firmware-m)
include(SignTfmImage)

iotsdk_tf_m_sign_image(my_application 0.0.0)

This will generate a signed image, my_application_signed.bin, in your build directory.

💡 Replace my_application with the actual name of your application executable. Replace 0.0.0 with a version of your choice.

Optionally, you can merge the bootloader, the secure image and the non-secure application image into a single .elf image to ease loading of the code onto the target. To do this:

iotsdk_tf_m_merge_images(my_application 0x10000000 0x11000000 0x01060000)

This will generate a merged image, my_application_merged.elf, in your build directory.

💡 Replace my_application with the actual name of your application executable. Replace the three addresses with the actual ROM addresses of the bootloader, secure image and non-secure image.

💡 For our reference platforms, Corstone-300 and Corstone-310, you can find their ROM addresses in templates/platforms.cmake as corstone-300-TFM_ADDRESSES and corstone-310-TFM_ADDRESSES respectively.

💡 If you would like to create an integration test with htrun, then you must create a merged image and pass it to htrun which does not support loading more than one image.

Running

After building your application, you have two options for running it on an FVP or AVH. Take FVP_Corstone_SSE-300_Ethos-U55 for example:

  • Load the bootloader .elf image, signed secure .bin image and signed non-secure .bin image separately:

    FVP_Corstone_SSE-300_Ethos-U55 -a __build/bl2.elf \
        --data __build/_deps/trusted-firmware-m-build/bin/tfm_s_signed.bin@0x11000000 \
        --data __build/my_application_signed.bin@0x01060000
    

    💡 The memory locations for tfm_s_signed.bin and my_application_signed.bin will change depending on which platform is being used.

  • Load the merged .elf image, if you have called iotsdk_tf_m_merge_images() during image signing.

    FVP_Corstone_SSE-300_Ethos-U55 -a __build/my_application_merged.elf
    

To run it on an FPGA board, consult the application notes for the FPGA image. Generally, an FPGA board only allows you to load the images as separate files instead of a merged file.

Examples

To see the full context of the information in the sections above, you are advised to take a look at the Open IoT SDK examples for Trusted Firmware-M.

Documentation

For more details of how to use Trusted Firmware-M, see its official documentation.