Porting PSA targets
This document describes the process of adding new PSA targets to Mbed OS, focusing on target configurations, build and validation.
Before reading this document, please read porting a custom board and porting targets, which provide step-by-step instructions to porting a new target to Mbed OS.
Glossary
- NSPE: Non-Secure Processing Environment.
- PSA: Platform Security Architecture.
- SPE: Secure Processing Environment.
- TF-M: Trusted Firmware M (for M-class devices).
Adding new PSA targets
To help create PSA targets, we have added a few generic targets to targets/targets.json
:
PSA_Target
: Root level PSA target.PSA_V7_M
: Single-core v7-M generic PSA target, which doesn't employ hardware isolation between the NSPE and the SPE, so TF-M is not supported. PSA secure service emulation enables PSA API compatibility.PSA_DUAL_CORE
: Dual-core generic PSA target. A dual-core PSA target has at least two cores that are either Armv7-M or Armv6-M. One core will be used for the SPE and another for the NSPE. Hardware isolation between the cores enables PSA compliance. On dual-core targets, TF-M runs on the SPE and provides PSA services, and Mbed OS runs on the NSPE.PSA_V8_M
: Armv8-M generic PSA target, which employs hardware to isolate the NSPE from the SPE. TF-M runs on the SPE and provides PSA services, and Mbed OS runs on the NSPE.
NSPE generic targets
SPE binaries are generated by TF-M build tools, not Mbed-OS build tools. Therefore, when adding a new PSA target to Mbed OS, you don't need to define an SPE target; it's enough to define an NSPE target. Therefore, for dual-core (PSA_DUAL_CORE
) and Armv8-M (PSA_V8_M
), we have defined only PSA NSPE generic targets.
Inheritance
The Mbed OS build tools have limited support for multiple inheritance. Because of this, a PSA target must inherit from the generic PSA target corresponding to the new target's architecture (one of PSA_V7_M
, PSA_DUAL_CORE
and PSA_V8_M
) or from one of its family targets, but cannot inherit from both the generic and family targets at once. We cover family inheritance cases in each target section in this document.
Note: The examples in this document are taken from targets/targets.json
.
Example of a single-core Armv7-M PSA target's inheritance:
"K64F": {
"inherits": ["PSA_V7_M"]
}
Adding single-core (non-TF-M) PSA targets
Mbed OS's PSA service emulation provides PSA compatibility for single-core PSA targets which do not support TF-M.
The following example shows a PSA-enabled single-core target, K64F
:
"K64F": {
"supported_form_factors": [
"ARDUINO"
],
"components_add": [
"SD",
"FLASHIAP"
],
"core": "Cortex-M4F",
"supported_toolchains": [
"ARM",
"GCC_ARM",
"IAR"
],
"extra_labels_add": [
"Freescale",
"MCUXpresso_MCUS",
"KSDK2_MCUS",
"FRDM",
"KPSDK_MCUS",
"KPSDK_CODE",
"MCU_K64F",
"Freescale_EMAC"
],
"is_disk_virtual": true,
"macros_add": [
"CPU_MK64FN1M0VMD12",
"FSL_RTOS_MBED",
"MBED_SPLIT_HEAP",
"MBED_TICKLESS"
],
"inherits": [
"PSA_V7_M"
],
"detect_code": [
"0240"
],
"device_has_add": [
"USTICKER",
"LPTICKER",
"RTC",
"CRC",
"ANALOGIN",
"ANALOGOUT",
"EMAC",
"I2C",
"I2CSLAVE",
"INTERRUPTIN",
"PORTIN",
"PORTINOUT",
"PORTOUT",
"PWMOUT",
"RESET_REASON",
"SERIAL",
"SERIAL_FC",
"SERIAL_ASYNCH",
"SLEEP",
"SPI",
"SPI_ASYNCH",
"SPISLAVE",
"STDIO_MESSAGES",
"TRNG",
"FLASH",
"USBDEVICE",
"WATCHDOG"
],
"release_versions": [
"2",
"5"
],
"device_name": "MK64FN1M0xxx12",
"bootloader_supported": true,
"overrides": {
"network-default-interface-type": "ETHERNET"
},
"supported_c_libs": {
"arm": [
"std",
"small"
],
"gcc_arm": [
"std",
"small"
],
"iar": [
"std"
]
}
}
Note the config options macros_add
, extra_labels_add
and device_has_add
. To add or remove macros
, extra_labels
or target capabilities, a PSA target definition must use [macros/extra_labels/device_has]_add
or [macros/extra_labels/device_has]_remove
(not macros
, extra_labels
or device_has
).
To add or remove a feature, use feature_
[add/remove].
As a second example, here is a single-core Armv7-M PSA target that inherits from one of its family targets:
"GD32_F450ZI": {
"inherits": [
"GD32_Target"
]
}
In this case, you must add the following additional attributes:
"features_add": [
"PSA"
],
"extra_labels_add": [
"MBED_PSA_SRV"
]
Adding TF-M (dual-core or Armv8-M) PSA targets
An Mbed OS (NSPE) target that supports TF-M must contain the following attributes (in addition to other target attributes defined in porting a custom board and porting targets):
-
inherits
: PSA generic targetPSA_DUAL_CORE
orPSA_V8_M
, unless the target has to inherit from one of its family targets. -
extra_labels
:TARGET_
[label] paths to enable.TFM_LATEST
: If the current version of TF-M (that Mbed OS is integrated with) is supported by the target. The current version is indicated in mbed-os-tf-m-regression-tests.TFM_V
[major]_
[minor]: If a legacy release of TF-M is supported by the target.
-
macros_add
: C/C++ macros that are globally set during compilation.BL2
: If the TF-M bootloader is supported by the target.MCUBOOT_IMAGE_NUMBER=2
: If the secure and non-secure images are in two separate bootloader slots.
-
tfm_target_name
: Target name in TF-M. -
tfm_bootloader_supported
: If the TF-M bootloader is supported by the target.The supported values are
true
andfalse
. -
tfm_supported_toolchains
: Supported TF-M toolchains.The supported values are
ARMCLANG
andGNUARM
. -
tfm_default_toolchain
: Default TF-M toolchain.The supported values are
ARMCLANG
andGNUARM
. -
tfm_delivery_dir
: The directory to which TF-M binaries will be copied. -
TFM_OUTPUT_EXT
: Optional attribute that indicates the output extension of the TF-M secure binary. -
post_binary_hook
:function
: The target's post binary hook ([class].[method]) intools/targets/__init__.py
for image signing, required if the TF-M bootloader support is supported.
-
secure_image_filename
: The file name of the TF-M secure binary, to be signed by the post binary hook.
Note: When inherits
is used, some of attributes are set by the PSA generic target.
The following example shows a PSA-enabled Armv8-M PSA target, ARM_MUSCA_S1
:
"ARM_MUSCA_S1": {
"inherits": [
"PSA_V8_M"
],
"default_toolchain": "ARMC6",
"features_add": [
"EXPERIMENTAL_API"
],
"forced_reset_timeout": 20,
"release_versions": [
"5"
],
"core": "Cortex-M33-NS",
"supported_toolchains": [
"ARMC6",
"GCC_ARM"
],
"device_has_add": [
"INTERRUPTIN",
"I2C",
"I2CSLAVE",
"LPTICKER",
"SERIAL",
"SLEEP",
"USTICKER"
],
"macros_add": [
"__STARTUP_CLEAR_BSS",
"MBED_FAULT_HANDLER_DISABLED",
"CMSIS_NVIC_VIRTUAL",
"LPTICKER_DELAY_TICKS=3",
"MBED_MPU_CUSTOM",
"BL2",
"MCUBOOT_IMAGE_NUMBER=2"
],
"extra_labels_add": [
"ARM_SSG",
"MUSCA_S1"
],
"post_binary_hook": {
"function": "ArmMuscaS1Code.binary_hook"
},
"secure_image_filename": "tfm_s.bin",
"tfm_target_name": "musca_s1",
"tfm_bootloader_supported": true,
"tfm_default_toolchain": "ARMCLANG",
"tfm_supported_toolchains": [
"ARMCLANG",
"GNUARM"
],
"tfm_delivery_dir": "TARGET_ARM_SSG/TARGET_MUSCA_S1",
"detect_code": [
"5009"
]
}
Please note the config options features_add
, macros_add
, extra_labels_add
and device_has_add
. To add or remove features
, macros
, extra_labels
or target capabilities, a PSA target definition must use
[features/macros/extra_labels/device_has]_add
or [features/macros/extra_labels/device_has]_remove
(not features
, macros
, extra_labels
or device_has
).
By default, a TF-M build generates a bin
file. If the target requires a hex
file, you need to add the attribute "TFM_OUTPUT_EXT": "hex"
to the target definition. The build script will convert bin
to hex
, then copy the hex
to tfm_delivery_dir
. You must also update secure_image_filename
to match the new file extension.
If a PSA target cannot inherit from PSA_V8_M
or PSA_DUAL_CORE
because it has to inherit from one of its family targets, you must declare PSA and TF-M attributes manually. For example,
"features_add": [
"PSA"
],
"extra_labels_add": [
"TFM",
"TFM_LATEST",
"TFM_V8M"
]
(Please adjust the TF-M version and target architecture accordingly.)
Build and validation
The mbed-os-tf-m-regression-tests repository contains build scripts, TF-M regression tests and PSA API compliance tests. Please follow instructions there to build and validate your TF-M target.
Building TF-M and creating an Mbed OS pull request
Note: Please ensure that both regression tests and PSA API compliance tests pass before creating an Mbed OS pull request.
To build TF-M and create an Mbed OS pull request:
-
Switch to the
mbed-os-tf-m-regression-tests
directory. -
Add your target to
tfm_ns_import.yaml
. You can take the existing targetARM_MUSCA_S1
as an example and adjust the target name. -
Run:
python3 build_tfm.py -m <new target> -t <toolchain> --commit
The command builds TF-M with the config
CoreIPC
, copies the TF-M binary to the location defined by the target attributetfm_delivery_dir
, and commits the changes to Mbed OS.Tip: When you run the Python script
build_tfm.py
without any options, TF-M is built for all supported targets and the secure binary (TF-M) for each target is copied to the location defined by the target attributetfm_delivery_dir
. When you use the--commit
option, a new Mbed OS commit is created with the new or modified TF-M binaries andfeatures/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/VERSION.txt
. -
Switch to the
mbed-os
directory and check the latest commit. -
In the directory of your target, create or update
CMakeLists.txt
to define how CMake builds your target. Make sure it linkss_veneers.o
to your target and callsmbed_post_build_tfm_sign_image()
which generates a ready-to-flash image containing the bootloader + signed TF-M secure binary + signed Mbed OS application.You can take a look at
targets/TARGET_ARM_SSG/TARGET_MUSCA_S1/CMakeLists.txt
as an example. -
Switch back to the
mbed-os-tf-m-regression-tests
directory, and followREADME.md
to build and run all tests manually.Ensure the test results are consistent with what you get from the vanilla TF-M tests (i.e. without Mbed OS integration). Some tests may be expected to fail.
Once you have the expected results, you can add them to
test/logs/<new target>/
to enable automated testing. The logs should be minimal and based on regular expressions, seetest/logs/ARM_MUSCA_S1/
for example. -
If everything looks good, push the changes to your forks of Mbed OS and mbed-os-tf-m-regression-tests and create pull requests against our official repositories.
Tip: See the contributing guide for more information about pull requests.
Further reading
For more information, see: