diff --git a/components/TARGET_PSA/TARGET_TFM/tf-m-integration.md b/components/TARGET_PSA/TARGET_TFM/tf-m-integration.md index 089a46075b..f3b4f54556 100644 --- a/components/TARGET_PSA/TARGET_TFM/tf-m-integration.md +++ b/components/TARGET_PSA/TARGET_TFM/tf-m-integration.md @@ -26,12 +26,12 @@ TF-M is built as bare-metal in a secure target, in order to build a secure targe ## Build hooks Mbed-OS testing tools are designed to work with a single image (`.bin` or `.hex`). -When building mbed-os for ARMv8-M targets two images are created. One for normal world(NW) and one for TrustZone(TZ). +When building mbed-os for TF-M targets two images are created. One for normal world(NW) and one for TrustZone(TZ). Mbed-OS build system provides `post_binary_hook` that allows executing arbitrary Python script for merging NW and TZ images. Typically `post_binary_hook` is added to NW target and assumes TZ target images as a prerequisite. -## Porting ARMv8-M targets +## Porting TF-M targets -Typically firmware for ARMv8-M targets consist of 2 or more images: normal world and TrustZone image. More images can be present in case boot loaders are used. +Typically firmware for TF-M targets consist of 2 or more images: normal world and TrustZone image. More images can be present in case boot loaders are used. Two images must be built and linked separately. TrustZone image must be built first. There may be code and/or header files sharing between the two targets. diff --git a/targets/targets.json b/targets/targets.json index b2625f4870..d98b1b40f1 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -1,6 +1,7 @@ { "Target": { "core": null, + "trustzone": false, "default_toolchain": "ARM", "supported_toolchains": null, "extra_labels": [], @@ -8042,6 +8043,7 @@ "MBED_TZ_DEFAULT_ACCESS=1", "LPTICKER_DELAY_TICKS=3" ], + "trustzone": true, "is_disk_virtual": true, "supported_toolchains": ["ARMC6"], "config": { diff --git a/tools/build_api.py b/tools/build_api.py index 2632b15e41..d4b94e24ed 100755 --- a/tools/build_api.py +++ b/tools/build_api.py @@ -601,10 +601,7 @@ def build_project(src_paths, build_path, target, toolchain_name, if into_dir: copy_when_different(res[0], into_dir) if not extra_artifacts: - if ( - CORE_ARCH[toolchain.target.core] == 8 and - not toolchain.target.core.endswith("NS") - ): + if toolchain.target.is_TrustZone_secure_target: cmse_lib = join(dirname(res[0]), "cmse_lib.o") copy_when_different(cmse_lib, into_dir) else: diff --git a/tools/targets/__init__.py b/tools/targets/__init__.py index 251e31bbb3..14eec1740b 100644 --- a/tools/targets/__init__.py +++ b/tools/targets/__init__.py @@ -379,6 +379,32 @@ class Target(namedtuple( labels = (names + CORE_LABELS[self.core] + self.extra_labels) return labels + @property + def core_without_NS(self): + if self.core.endswith('-NS'): + return self.core[:-3] + else: + return self.core + + # Mechanism for specifying TrustZone is subject to change - see + # discussion on https://github.com/ARMmbed/mbed-os/issues/9460 + # In the interim, we follow heuristics that support existing + # documentation for ARMv8-M TF-M integration (check the "TFM" label), + # plus an extra "trustzone" flag set by M2351, and looking at the "-NS" + # suffix. This now permits non-TrustZone ARMv8 builds if + # having trustzone = false (default), no TFM flag, and no -NS suffix. + @property + def is_TrustZone_secure_target(self): + return (getattr(self, 'trustzone', False) or 'TFM' in self.labels) and not self.core.endswith('-NS') + + @property + def is_TrustZone_non_secure_target(self): + return self.core.endswith('-NS') + + @property + def is_TrustZone_target(self): + return self.is_TrustZone_secure_target or self.is_TrustZone_non_secure_target + @property def is_PSA_secure_target(self): return 'SPE_Target' in self.labels diff --git a/tools/toolchains/arm.py b/tools/toolchains/arm.py index 5fa1f70516..82fff6fd67 100644 --- a/tools/toolchains/arm.py +++ b/tools/toolchains/arm.py @@ -25,7 +25,6 @@ from tempfile import mkstemp from shutil import rmtree from distutils.version import LooseVersion -from tools.targets import CORE_ARCH from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS from tools.utils import mkdir, NotSupportedException, run_cmd from tools.resources import FileRef @@ -521,25 +520,25 @@ class ARMC6(ARM_STD): if "--library_type=microlib" not in self.flags['asm']: self.flags['asm'].append("--library_type=microlib") - core = target.core - if CORE_ARCH[target.core] == 8: - if ((not target.core.endswith("-NS")) and - kwargs.get('build_dir', False)): - # Create Secure library + if target.is_TrustZone_secure_target: + if kwargs.get('build_dir', False): + # Output secure import library build_dir = kwargs['build_dir'] secure_file = join(build_dir, "cmse_lib.o") self.flags["ld"] += ["--import_cmse_lib_out=%s" % secure_file] - # Add linking time preprocessor macro DOMAIN_NS - if target.core.endswith("-NS"): - define_string = self.make_ld_define("DOMAIN_NS", "0x1") - self.flags["ld"].append(define_string) - core = target.core[:-3] - else: - # Add secure build flag - self.flags['cxx'].append("-mcmse") - self.flags['c'].append("-mcmse") + # Enable compiler security extensions + self.flags['cxx'].append("-mcmse") + self.flags['c'].append("-mcmse") + if target.is_TrustZone_non_secure_target: + # Add linking time preprocessor macro DOMAIN_NS + # (DOMAIN_NS is passed to compiler and assembler via CORTEX_SYMBOLS + # in mbedToolchain.get_symbols) + define_string = self.make_ld_define("DOMAIN_NS", "0x1") + self.flags["ld"].append(define_string) + + core = target.core_without_NS cpu = { "Cortex-M0+": "cortex-m0plus", "Cortex-M4F": "cortex-m4", diff --git a/tools/toolchains/gcc.py b/tools/toolchains/gcc.py index 1ec3b4cb83..29651e6737 100644 --- a/tools/toolchains/gcc.py +++ b/tools/toolchains/gcc.py @@ -20,7 +20,6 @@ from os import getenv from distutils.spawn import find_executable from distutils.version import LooseVersion -from tools.targets import CORE_ARCH from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS from tools.utils import run_cmd @@ -59,20 +58,23 @@ class GCC(mbedToolchain): self.flags["common"].append("-DMBED_RTOS_SINGLE_THREAD") self.flags["ld"].append("--specs=nano.specs") - core = target.core self.cpu = [] - if CORE_ARCH[target.core] == 8: - # Add linking time preprocessor macro DOMAIN_NS - if target.core.endswith("-NS"): - self.flags["ld"].append("-DDOMAIN_NS=1") - core = target.core[:-3] - else: - self.cpu.append("-mcmse") - self.flags["ld"].extend([ - "-Wl,--cmse-implib", - "-Wl,--out-implib=%s" % join(build_dir, "cmse_lib.o") - ]) + if target.is_TrustZone_secure_target: + # Enable compiler security extensions + self.cpu.append("-mcmse") + # Output secure import library + self.flags["ld"].extend([ + "-Wl,--cmse-implib", + "-Wl,--out-implib=%s" % join(build_dir, "cmse_lib.o") + ]) + if target.is_TrustZone_non_secure_target: + # Add linking time preprocessor macro DOMAIN_NS + # (DOMAIN_NS is passed to compiler and assembler via CORTEX_SYMBOLS + # in mbedToolchain.get_symbols) + self.flags["ld"].append("-DDOMAIN_NS=1") + + core = target.core_without_NS cpu = { "Cortex-M0+": "cortex-m0plus", "Cortex-M4F": "cortex-m4", diff --git a/tools/toolchains/iar.py b/tools/toolchains/iar.py index bec91e37d5..b2a5d4d8fc 100644 --- a/tools/toolchains/iar.py +++ b/tools/toolchains/iar.py @@ -19,7 +19,6 @@ from os import remove from os.path import join, splitext, exists from distutils.version import LooseVersion -from tools.targets import CORE_ARCH from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS from tools.utils import run_cmd @@ -54,20 +53,23 @@ class IAR(mbedToolchain): build_dir=build_dir, build_profile=build_profile ) - core = target.core - if CORE_ARCH[target.core] == 8: - # Add linking time preprocessor macro DOMAIN_NS - if target.core.endswith("-NS"): - define_string = self.make_ld_define("DOMAIN_NS", "0x1") - self.flags["ld"].append(define_string) - core = target.core[:-3] - else: - # Create Secure library - self.flags["asm"] += ["--cmse"] - self.flags["common"] += ["--cmse"] - secure_file = join(build_dir, "cmse_lib.o") - self.flags["ld"] += ["--import_cmse_lib_out=%s" % secure_file] + if target.is_TrustZone_secure_target: + # Enable compiler security extensions + self.flags["asm"] += ["--cmse"] + self.flags["common"] += ["--cmse"] + # Output secure import library + secure_file = join(build_dir, "cmse_lib.o") + self.flags["ld"] += ["--import_cmse_lib_out=%s" % secure_file] + + if target.is_TrustZone_non_secure_target: + # Add linking time preprocessor macro DOMAIN_NS + # (DOMAIN_NS is passed to compiler and assembler via CORTEX_SYMBOLS + # in mbedToolchain.get_symbols) + define_string = self.make_ld_define("DOMAIN_NS", "0x1") + self.flags["ld"].append(define_string) + + core = target.core_without_NS cpu = { "Cortex-M7F": "Cortex-M7.fp.sp", "Cortex-M7FD": "Cortex-M7.fp.dp",