Permit non-TrustZone ARMv8 build

Change the heuristic for selection of CMSE in the tools python, so that
a non-TrustZone ARMv8 build can happen.

Ideally we would have more direct flagging in the targets, but this
refines the heuristic so the necessary behaviour can be easily
achieved.

* DOMAIN_NS=1 is based purely on the `-NS` suffix on the core name.

* Enabling CMSE in the compiler and outputting a secure import library
  is now enabled when the core doesn't have an `-NS` suffix by either
  the target label `TFM` being present or the flag `trustzone` being set.

This covers the existing ARMv8-M behaviour - TF-M builds have the TFM
label, as per its documentation; M2351 secure builds have no explicit
flagging, so we ensure that the M2351_NS target has the trustzone flag
set, and the out-of-tree secure target inherits that.
pull/10520/head
Kevin Bracey 2019-05-02 13:26:49 +03:00
parent d30d772047
commit 65e0887ef3
7 changed files with 77 additions and 49 deletions

View File

@ -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.

View File

@ -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": {

View File

@ -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:

View File

@ -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

View File

@ -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",

View File

@ -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",

View File

@ -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",