mirror of https://github.com/ARMmbed/mbed-os.git
Python script automate tf-m build build process
The python script (tools/psa/build_tfm.py) automates tf-m build process for a particular target or all supported tf-m targets and copies generated binary to a predefined location. Updated documentation describing steps to add single v7-m and dual v7-M targets and building tf-m using python script. Added following attributes to dual v7-M and v8-M SPE generic target, * inherits: PSA generic target PSA_DUAL_V7_M_SPE * tfm_target_name: Target name in TF-M * tfm_bootloader_supported: If TF-M bootloader is supported by the target. Values supported are "true" and "false" * tfm_default_toolchain: Default TF-M toolchain supported. Values supported are "ARMCLANG" and "GNUARM" * tfm_supported_toolchains: Supported TF-M toolchains. Values supported are "ARMCLANG" and "GNUARM" * delivery_dir: The directory to which TF-M binary will be copied to Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com>pull/12402/head
parent
e7f2d62e16
commit
6405b44ff6
|
@ -0,0 +1 @@
|
|||
dualcpu_l2_v01-18-g11d373ee8eb6
|
|
@ -1,15 +1,19 @@
|
|||
# Supporting PSA in Mbed OS
|
||||
|
||||
This document is still a work in progress. It describes the process of adding new PSA targets to Mbed OS. It also outlines the new directory structure created to support PSA on single v7-M, dual v7-M and single v8-M.
|
||||
This document is still a work in progress. It describes the process of adding new PSA targets to Mbed OS and building [TF-M](https://git.trustedfirmware.org/trusted-firmware-m.git/tree/?h=feature-twincpu) for dual v7-M and single v8-M SPE. It also outlines the new directory structure created to support PSA on single v7-M, dual v7-M and single v8-M.
|
||||
|
||||
## TODO
|
||||
* Adding dual v7-M targets
|
||||
*Note*
|
||||
PSA - Platform Security Architecture
|
||||
TF-M - Trusted Firmware M
|
||||
SPE - Secure Processing Environment
|
||||
NSPE - Non-Secure Processing Environment
|
||||
|
||||
# TODO
|
||||
* Adding v8-M targets
|
||||
* Building TF-M
|
||||
* Running PSA compliance tests
|
||||
|
||||
## Adding new PSA targets
|
||||
To help with the creation of new PSA targets, couple of generic PSA targets have been added to `targets/targets.json`.
|
||||
# Adding new PSA targets
|
||||
To help with the creation of new PSA targets, couple of generic targets have been added to `targets/targets.json`.
|
||||
* `PSA_Target` (Root level PSA target)
|
||||
* `PSA_V7_M_NSPE` (Single v7-M NSPE generic target)
|
||||
* `PSA_V7_M_SPE` (Single v7-M SPE generic target)
|
||||
|
@ -18,16 +22,32 @@ To help with the creation of new PSA targets, couple of generic PSA targets have
|
|||
* `PSA_V8_M_NSPE` (v8-M NSPE generic target)
|
||||
* `PSA_V8_M_SPE` (v8-M SPE generic target)
|
||||
|
||||
The new PSA targets **MUST** `inherit` from one of these targets depending on the architecture:
|
||||
A Single v7-M target doesn't support hardware separation to isolate NSPE from SPE. Therefore for single v7-M targets only NSPE target is defined. The PSA API compliance is achieved with the help of emulation of PSA secure services.
|
||||
|
||||
Example:
|
||||
A Dual v7-M target will have at least two Armv7-M cores to isolate NSPE from SPE. On dual v7-M targets, TF-M will be running on SPE providing PSA services. Therefore, it is **MANDATORY** to define both SPE and NSPE target for dual v7-M targets.
|
||||
|
||||
A Armv8-M target supports hardware separation to isolate NSPE from SPE. On v8-M targets, TF-M will be running on SPE providing PSA services. Therefore, it is **MANDATORY** to define both SPE and NSPE target for v8-M targets.
|
||||
|
||||
The new PSA targets **MUST** `inherit` from one of the generic PSA targets depending on the architecture. Also, in case of dual v7-M and v8-M targets, SPE and NSPE targets **MUST** inherit from the respective SPE and NSPE PSA generic targets.
|
||||
|
||||
Example single v7-M:
|
||||
```json
|
||||
"K64F": {
|
||||
"inherits": ["PSA_V7_M_NSPE", "Target"],
|
||||
}
|
||||
```
|
||||
|
||||
In addition, the new PSA target **MUST** `inherit` from `Target` which defines default target config options. The only exception is, if the new PSA target is inheriting from another generic target which inherits from `Target`.
|
||||
Example dual v7-M:
|
||||
```json
|
||||
"CY8CPROTO_064_SB_S": {
|
||||
"inherits": ["PSA_DUAL_V7_M_SPE"],
|
||||
},
|
||||
"CY8CPROTO_064_SB": {
|
||||
"inherits": ["PSA_DUAL_V7_M_NSPE", "MCU_PSOC6_M4"],
|
||||
}
|
||||
```
|
||||
|
||||
In addition, the new PSA NSPE target **MUST** `inherit` from `Target` which defines default target config options. The only exception is, if the new PSA target is inheriting from another generic target which inherits from `Target`.
|
||||
|
||||
Example:
|
||||
```json
|
||||
|
@ -40,8 +60,8 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### Adding single v7-M targets
|
||||
The PSA on single v7-M is supported with the help of Mbed OS PSA services. The following is taken from `targets/targets.json` and shows a PSA enabled target, `K64F`.
|
||||
## Adding single v7-M targets
|
||||
A target can ge categorized as a single v7-M target if it only has a single Armv7-M core. The PSA on single v7-M is supported with the help of emulated PSA services implemented in Mbed OS. The following is taken from `targets/targets.json` and shows a PSA enabled single v7-M target, `K64F`.
|
||||
|
||||
```json
|
||||
"K64F": {
|
||||
|
@ -104,11 +124,72 @@ The PSA on single v7-M is supported with the help of Mbed OS PSA services. The f
|
|||
Please pay attention to config options `extra_labels_add` and `device_has_add`. If needed then a PSA target definition **MUST** use [extra_labels/device_has]`_add` or [extra_labels/device_has]`_remove` (not `extra_labels` or `device_has`) to add/remove either extra_labels or target capabilities. Also, use `[feature_]`add/remove to add/remove a feature.
|
||||
Check [extra_labels](https://os.mbed.com/docs/mbed-os/v5.14/reference/adding-and-configuring-targets.html), [device_has](https://os.mbed.com/docs/mbed-os/v5.14/reference/adding-and-configuring-targets.html) and [features](https://os.mbed.com/docs/mbed-os/v5.14/reference/adding-and-configuring-targets.html) for more information.
|
||||
|
||||
### Adding dual v7-M targets
|
||||
## Adding dual v7-M targets
|
||||
A target can ge categorized as a dual v7-M target if it has at least two Armv7-M cores. On dual v7-M targets, TF-M will be running on SPE providing PSA services. Therefore, it is **MANDATORY** to define both SPE and NSPE target for dual v7-M targets.
|
||||
|
||||
### Adding v8-M targets
|
||||
The SPE target **MUST** contain following attributes,
|
||||
|
||||
## Enabling PSA at application level
|
||||
* inherits: PSA generic target PSA_DUAL_V7_M_SPE
|
||||
* tfm_target_name: Target name in TF-M
|
||||
* tfm_bootloader_supported: If TF-M bootloader is supported by the target. Values supported are "true" and "false"
|
||||
* tfm_default_toolchain: Default TF-M toolchain supported. Values supported are "ARMCLANG" and "GNUARM"
|
||||
* tfm_supported_toolchains: Supported TF-M toolchains. Values supported are "ARMCLANG" and "GNUARM"
|
||||
* delivery_dir: The directory to which TF-M binary will be copied to
|
||||
|
||||
The following is taken from `targets/targets.json` and shows a PSA enabled dual v7-M target, `PSoC64`,
|
||||
|
||||
```json
|
||||
"CY8CPROTO_064_SB_S": {
|
||||
"inherits": [
|
||||
"PSA_DUAL_V7_M_SPE"
|
||||
],
|
||||
"tfm_target_name": "psoc64",
|
||||
"tfm_bootloader_supported": false,
|
||||
"tfm_default_toolchain": "ARMCLANG",
|
||||
"tfm_supported_toolchains": [
|
||||
"ARMCLANG",
|
||||
"GNUARM"
|
||||
],
|
||||
"delivery_dir": "TARGET_Cypress/TARGET_PSOC6/TARGET_CY8CPROTO_064_SB/prebuilt"
|
||||
},
|
||||
"CY8CPROTO_064_SB": {
|
||||
"inherits": [
|
||||
"PSA_DUAL_V7_M_NSPE",
|
||||
"MCU_PSOC6_M4"
|
||||
],
|
||||
"components_remove": [
|
||||
"QSPIF"
|
||||
],
|
||||
"device_has_remove": [
|
||||
"QSPI"
|
||||
],
|
||||
"extra_labels_add": [
|
||||
"PSOC6_01",
|
||||
"MXCRYPTO_01"
|
||||
],
|
||||
"macros_add": [
|
||||
"CYB06447BZI_D54",
|
||||
"PSOC6_DYNSRM_DISABLE=1",
|
||||
"CY_CFG_SYSCLK_WCO_ENABLED=1",
|
||||
"SEMAPHORE"
|
||||
],
|
||||
"detect_code": [
|
||||
"1907"
|
||||
],
|
||||
"forced_reset_timeout": 5,
|
||||
"reset_method": "default",
|
||||
"post_binary_hook": {
|
||||
"function": "PSOC6Code.sign_image"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
Please pay attention to config options `extra_labels_add` and `device_has_remove`. If needed then a PSA target definition **MUST** use [extra_labels/device_has]`_add` or [extra_labels/device_has]`_remove` (not `extra_labels` or `device_has`) to add/remove either extra_labels or target capabilities. Also, use `[feature_]`add/remove to add/remove a feature.
|
||||
Check [extra_labels](https://os.mbed.com/docs/mbed-os/v5.14/reference/adding-and-configuring-targets.html), [device_has](https://os.mbed.com/docs/mbed-os/v5.14/reference/adding-and-configuring-targets.html) and [features](https://os.mbed.com/docs/mbed-os/v5.14/reference/adding-and-configuring-targets.html) for more information.
|
||||
|
||||
## Adding v8-M targets
|
||||
|
||||
# Enabling PSA at application level
|
||||
Having an entropy source is crucial for Mbed TLS and Mbed Crypto. The [document](https://os.mbed.com/docs/mbed-os/v5.14/porting/entropy-sources.html) talks about entropy and how to add an entropy source. Sometimes a target might not have a True Random Number Generator (TRNG), in that case the target will be configured as a non-PSA target in `targets/targets.json`. In that scenario, if an application wants to use that target as a PAS target then it is the responsibility of application to provide an entropy source and mark that target as PSA target at application level. The config option [target_overrides](https://os.mbed.com/docs/mbed-os/v5.14/reference/configuration.html) can be used to enable PSA for a target.
|
||||
|
||||
example mbed_app.json:
|
||||
|
@ -120,8 +201,36 @@ example mbed_app.json:
|
|||
}
|
||||
```
|
||||
|
||||
# Building TF-M
|
||||
On dual v7-M and v8-M targets, TF-M will be running on SPE providing PSA services. A python script `tools/psa/build_tfm.py` automates building TF-M and copying the binary to predefined location defined by attribute `delivery_dir`.
|
||||
|
||||
## New directory structure
|
||||
Usage:
|
||||
```console
|
||||
python3 tools/psa/build_tfm.py
|
||||
```
|
||||
Supported options:
|
||||
```console
|
||||
usage: build_tfm.py [-h] [-m {CY8CPROTO_064_SB_S}] [-t {ARMCLANG,GNUARM}] [-d]
|
||||
[-l] [--clone] [--commit] [--clean-build] [-v]
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-m {CY8CPROTO_064_SB_S}, --mcu {CY8CPROTO_064_SB_S}
|
||||
Build for the given MCU
|
||||
-t {ARMCLANG,GNUARM}, --toolchain {ARMCLANG,GNUARM}
|
||||
Build for the given tool chain (default is
|
||||
tfm_default_toolchain)
|
||||
-d, --debug Set build profile to debug
|
||||
-l, --list Print supported TF-M secure targets
|
||||
--clone Clone TF-M git repo and its dependencies
|
||||
--commit Create a git commit for each platform
|
||||
--clean-build Remove cmake build directory
|
||||
-v, --verbose Verbose output
|
||||
```
|
||||
|
||||
If the python script is invoked without any options then TF-M will be built for all the supported targets and the binary will be copied to predefined location defined by attribute `delivery_dir`.
|
||||
|
||||
# New directory structure
|
||||
|
||||
```console
|
||||
features/FEATURE_PSA/
|
||||
|
@ -160,50 +269,6 @@ features/FEATURE_PSA/
|
|||
│ ├── test_s003
|
||||
│ ├── test_s002
|
||||
│ └── test_s001
|
||||
├── compliance_crypto
|
||||
│ ├── test_c043
|
||||
│ ├── test_c042
|
||||
│ ├── test_c041
|
||||
│ ├── test_c040
|
||||
│ ├── test_c039
|
||||
│ ├── test_c038
|
||||
│ ├── test_c037
|
||||
│ ├── test_c036
|
||||
│ ├── test_c035
|
||||
│ ├── test_c034
|
||||
│ ├── test_c033
|
||||
│ ├── test_c032
|
||||
│ ├── test_c031
|
||||
│ ├── test_c030
|
||||
│ ├── test_c029
|
||||
│ ├── test_c028
|
||||
│ ├── test_c027
|
||||
│ ├── test_c026
|
||||
│ ├── test_c025
|
||||
│ ├── test_c024
|
||||
│ ├── test_c023
|
||||
│ ├── test_c022
|
||||
│ ├── test_c021
|
||||
│ ├── test_c020
|
||||
│ ├── test_c019
|
||||
│ ├── test_c018
|
||||
│ ├── test_c017
|
||||
│ ├── test_c016
|
||||
│ ├── test_c015
|
||||
│ ├── test_c014
|
||||
│ ├── test_c013
|
||||
│ ├── test_c012
|
||||
│ ├── test_c011
|
||||
│ ├── test_c010
|
||||
│ ├── test_c009
|
||||
│ ├── test_c008
|
||||
│ ├── test_c007
|
||||
│ ├── test_c006
|
||||
│ ├── test_c005
|
||||
│ ├── test_c004
|
||||
│ ├── test_c003
|
||||
│ ├── test_c002
|
||||
│ └── test_c001
|
||||
└── compliance_attestation
|
||||
└── test_a001
|
||||
```
|
||||
```
|
||||
|
|
Binary file not shown.
|
@ -119,6 +119,11 @@
|
|||
"inherits": [
|
||||
"PSA_Target"
|
||||
],
|
||||
"tfm_target_name": "",
|
||||
"tfm_bootloader_supported": "",
|
||||
"tfm_default_toolchain": "ARMCLANG",
|
||||
"tfm_supported_toolchains": null,
|
||||
"delivery_dir": "",
|
||||
"public": false
|
||||
},
|
||||
"PSA_V8_M_NSPE": {
|
||||
|
@ -138,6 +143,11 @@
|
|||
"inherits": [
|
||||
"PSA_Target"
|
||||
],
|
||||
"tfm_target_name": "",
|
||||
"tfm_bootloader_supported": "",
|
||||
"tfm_default_toolchain": "ARMCLANG",
|
||||
"tfm_supported_toolchains": null,
|
||||
"delivery_dir": "",
|
||||
"public": false
|
||||
},
|
||||
"CM4_UARM": {
|
||||
|
@ -12861,8 +12871,22 @@
|
|||
],
|
||||
"bootloader_supported": false
|
||||
},
|
||||
"CY8CPROTO_064_SB_S": {
|
||||
"inherits": [
|
||||
"PSA_DUAL_V7_M_SPE"
|
||||
],
|
||||
"tfm_target_name": "psoc64",
|
||||
"tfm_bootloader_supported": false,
|
||||
"tfm_default_toolchain": "ARMCLANG",
|
||||
"tfm_supported_toolchains": [
|
||||
"ARMCLANG",
|
||||
"GNUARM"
|
||||
],
|
||||
"delivery_dir": "TARGET_Cypress/TARGET_PSOC6/TARGET_CY8CPROTO_064_SB/prebuilt"
|
||||
},
|
||||
"CY8CPROTO_064_SB": {
|
||||
"inherits": [
|
||||
"PSA_DUAL_V7_M_NSPE",
|
||||
"MCU_PSOC6_M4"
|
||||
],
|
||||
"components_remove": [
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Copyright (c) 2019 ARM Limited. All rights reserved.
|
||||
|
||||
|
@ -18,22 +18,24 @@ limitations under the License.
|
|||
"""
|
||||
|
||||
import os
|
||||
from os.path import join, abspath, dirname, isdir
|
||||
from os.path import join, abspath, dirname, isdir, relpath
|
||||
import argparse
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger('TF-M-Builder')
|
||||
ROOT = abspath(join(dirname(__file__), os.pardir, os.pardir))
|
||||
sys.path.insert(0, ROOT)
|
||||
from tools.targets import Target, TARGET_MAP, TARGET_NAMES
|
||||
|
||||
logging.basicConfig(level=logging.INFO,
|
||||
format='[%(name)s] %(asctime)s: %(message)s.',
|
||||
datefmt='%H:%M:%S')
|
||||
logger = logging.getLogger('TF-M-Builder')
|
||||
|
||||
ROOT = abspath(join(dirname(__file__), os.pardir, os.pardir))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
TF_M_BUILD_DIR = join(ROOT, os.pardir, 'tfm_build_dir')
|
||||
VERSION_FILE_PATH = join(ROOT, 'features/FEATURE_PSA/FEATURE_TFM')
|
||||
TF_M_BUILD_DIR = abspath(join(ROOT, os.pardir, 'tfm_build_dir'))
|
||||
VERSION_FILE_PATH = join(ROOT, 'features/FEATURE_PSA/TARGET_TFM')
|
||||
|
||||
dependencies = {
|
||||
"trusted-firmware-m":
|
||||
|
@ -46,22 +48,37 @@ dependencies = {
|
|||
"CMSIS_5": ['https://github.com/ARM-software/CMSIS_5.git', '5.5.0'],
|
||||
}
|
||||
|
||||
def is_cmake_installed():
|
||||
"""
|
||||
Check if cmake is installed
|
||||
"""
|
||||
command = ['cmake', '--version']
|
||||
return(run_cmd_and_return_errorcode(command))
|
||||
|
||||
def is_git_installed():
|
||||
"""
|
||||
Check if git is installed
|
||||
"""
|
||||
command = ['git', '--version']
|
||||
try:
|
||||
with open(os.devnull, 'w') as fnull:
|
||||
return subprocess.call(command, stdout=fnull, stderr=fnull)
|
||||
except OSError as e:
|
||||
return e.errno
|
||||
return(run_cmd_and_return_errorcode(command))
|
||||
|
||||
def is_git_lfs_installed():
|
||||
"""
|
||||
Check if git-lfs is installed
|
||||
"""
|
||||
command = ['git-lfs', '--version']
|
||||
return(run_cmd_and_return_errorcode(command))
|
||||
|
||||
def run_cmd_and_return_errorcode(command):
|
||||
"""
|
||||
Run the command in the sytem and return errorcode.
|
||||
Commands are passed as a list of tokens.
|
||||
E.g. The command 'git remote -v' would be passed in as:
|
||||
['git', 'remote', '-v']
|
||||
|
||||
:param command: System command as a list of tokens
|
||||
"""
|
||||
logger.debug('[Exec] %s', ' '.join(command))
|
||||
try:
|
||||
with open(os.devnull, 'w') as fnull:
|
||||
return subprocess.call(command, stdout=fnull, stderr=fnull)
|
||||
|
@ -88,7 +105,7 @@ def run_cmd_and_return_output(command):
|
|||
clean_up_cloned_repos()
|
||||
return output.decode("utf-8")
|
||||
|
||||
def detect_and_write_tfm_version(tfm_dir):
|
||||
def detect_and_write_tfm_version(tfm_dir, commit):
|
||||
"""
|
||||
Identify the version of TF-M and write it to VERSION.txt
|
||||
:param tfm_dir: The filesystem path where TF-M repo is cloned
|
||||
|
@ -102,9 +119,12 @@ def detect_and_write_tfm_version(tfm_dir):
|
|||
with open(join(VERSION_FILE_PATH, 'VERSION.txt'), 'w') as f:
|
||||
f.write(tfm_version)
|
||||
|
||||
if commit:
|
||||
commit_changes(VERSION_FILE_PATH)
|
||||
|
||||
def check_repo_version(name, deps):
|
||||
"""
|
||||
Compare the version of cloned and expected and exit if they dont match
|
||||
Compare the version of cloned and expected and exit if they don't match
|
||||
:param name: Name of the git repository
|
||||
:param deps: Dictionary containing dependency details
|
||||
"""
|
||||
|
@ -142,7 +162,7 @@ def check_and_clone_repo(name, deps):
|
|||
logger.info('%s repo exists, checking git version...', name)
|
||||
check_repo_version(name, deps)
|
||||
|
||||
def clone_tfm_repo():
|
||||
def clone_tfm_repo(commit):
|
||||
"""
|
||||
Clone TF-M git repos and it's dependencies
|
||||
"""
|
||||
|
@ -150,7 +170,8 @@ def clone_tfm_repo():
|
|||
check_and_clone_repo('mbedtls', dependencies)
|
||||
check_and_clone_repo('mbed-crypto', dependencies)
|
||||
check_and_clone_repo('CMSIS_5', dependencies)
|
||||
detect_and_write_tfm_version(join(TF_M_BUILD_DIR, 'trusted-firmware-m'))
|
||||
detect_and_write_tfm_version(join(TF_M_BUILD_DIR, 'trusted-firmware-m'),
|
||||
commit)
|
||||
|
||||
def clean_up_cloned_repos():
|
||||
"""
|
||||
|
@ -160,22 +181,301 @@ def clean_up_cloned_repos():
|
|||
shutil.rmtree(TF_M_BUILD_DIR)
|
||||
except OSError as e:
|
||||
logger.error('Unable to cleanup cloned repos')
|
||||
logger.error('"%s" occured', e.strerror)
|
||||
logger.error('"%s" occurred', e.strerror)
|
||||
|
||||
def get_tfm_secure_targets():
|
||||
"""
|
||||
Creates a list of TF-M secure targets.
|
||||
|
||||
:return: List of TF-M secure targets.
|
||||
"""
|
||||
return [str(t) for t in TARGET_NAMES if
|
||||
Target.get_target(t).is_TFM_target]
|
||||
|
||||
def get_target_info(target, toolchain=None):
|
||||
"""
|
||||
Creates a TF-M target tuple with default toolchain and
|
||||
artifact delivery directory.
|
||||
|
||||
:param target: Target name.
|
||||
:param toolchain: Toolchain
|
||||
:return: tuple (target, toolchain, delivery directory).
|
||||
"""
|
||||
if toolchain:
|
||||
if not TARGET_MAP[target].tfm_supported_toolchains:
|
||||
msg = "Supported Toolchains is not configured for target %s" % (
|
||||
TARGET_MAP[target].name)
|
||||
raise Exception(msg)
|
||||
elif toolchain not in TARGET_MAP[target].tfm_supported_toolchains:
|
||||
msg = "Toolchain %s is not supported by %s" % (toolchain,
|
||||
TARGET_MAP[target].name)
|
||||
raise Exception(msg)
|
||||
tc = toolchain
|
||||
else:
|
||||
tc = TARGET_MAP[target].tfm_default_toolchain
|
||||
|
||||
delivery_dir = join(ROOT, 'targets',
|
||||
TARGET_MAP[target].delivery_dir)
|
||||
|
||||
if not os.path.exists(delivery_dir):
|
||||
msg = "Delivery directory (delivery_dir) missing for %s" % target
|
||||
raise FileNotFoundError(msg)
|
||||
|
||||
bl_sup = True if TARGET_MAP[target].tfm_bootloader_supported else False
|
||||
return tuple([TARGET_MAP[target].name,
|
||||
TARGET_MAP[target].tfm_target_name,
|
||||
tc,
|
||||
delivery_dir,
|
||||
bl_sup])
|
||||
|
||||
def get_mbed_supported_tfm_targets():
|
||||
tfm_secure_targets = get_tfm_secure_targets()
|
||||
logger.debug("Found the following TF-M targets: {}".format(
|
||||
', '.join(tfm_secure_targets)))
|
||||
|
||||
return [get_target_info(t) for t in tfm_secure_targets]
|
||||
|
||||
def commit_changes(directory, target=None, toolchain=None):
|
||||
"""
|
||||
Check for changes in `directory` and if any then commit them
|
||||
:param directory: path to be checked for changes
|
||||
:param target: Target name
|
||||
:param toolchain: Toolchain name
|
||||
"""
|
||||
# Use --intent-to-add option of git status to identify un-tracked files
|
||||
cmd = ['git', '-C', ROOT, 'status', 'N', directory]
|
||||
run_cmd_and_return_errorcode(cmd)
|
||||
|
||||
cmd = ['git', '-C', ROOT, 'diff', '--exit-code', '--quiet', directory]
|
||||
changes_made = run_cmd_and_return_errorcode(cmd)
|
||||
|
||||
if changes_made:
|
||||
if target:
|
||||
logger.info("Change in image for %s has been detected" % target)
|
||||
else:
|
||||
logger.info("Change detected in directory %s" % directory)
|
||||
cmd = ['git', '-C', ROOT, 'add', relpath(directory, ROOT)]
|
||||
run_cmd_and_return_errorcode(cmd)
|
||||
|
||||
if target:
|
||||
logger.info("Committing image for %s" % target)
|
||||
msg = '--message="Updated secure binary for %s (%s)"' % (target,
|
||||
toolchain)
|
||||
else:
|
||||
logger.info("Committing changes in directory %s" % directory)
|
||||
msg = '--message="Updated directory %s "' % directory
|
||||
|
||||
cmd = ['git', '-C', ROOT, 'commit', msg]
|
||||
run_cmd_and_return_errorcode(cmd)
|
||||
else:
|
||||
if target:
|
||||
logger.info("No changes detected in %s, skipping commit" % target)
|
||||
else:
|
||||
logger.info("No changes detected in %s, skipping commit" %
|
||||
relpath(directory, ROOT))
|
||||
|
||||
def run_cmake_build(configure, cmake_build_dir, bl_supported= None,
|
||||
tfm_target=None, tfm_toolchain=None, debug=False):
|
||||
|
||||
if configure:
|
||||
cmake_cmd = ['cmake', '-GUnix Makefiles']
|
||||
cmake_cmd.append('-DPROJ_CONFIG=' + (join(TF_M_BUILD_DIR,
|
||||
'trusted-firmware-m', 'configs/ConfigCoreIPC.cmake')))
|
||||
cmake_cmd.append('-DTARGET_PLATFORM=' + tfm_target)
|
||||
cmake_cmd.append('-DCOMPILER=' + tfm_toolchain)
|
||||
if debug:
|
||||
cmake_cmd.append('-DCMAKE_BUILD_TYPE=Debug')
|
||||
else:
|
||||
cmake_cmd.append('-DCMAKE_BUILD_TYPE=Release')
|
||||
if not bl_supported:
|
||||
cmake_cmd.append('-DBL2=False')
|
||||
cmake_cmd.append('..')
|
||||
else:
|
||||
cmake_cmd = ['cmake', '--build', '.', '--', 'install']
|
||||
|
||||
proc = subprocess.Popen(cmake_cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, cwd=cmake_build_dir)
|
||||
for line in iter(proc.stdout.readline, b''):
|
||||
logger.debug(line.decode("utf-8").strip('\n'))
|
||||
|
||||
std_out, std_err = proc.communicate()
|
||||
|
||||
if proc.returncode:
|
||||
logger.info(std_err.decode("utf-8"))
|
||||
return proc.returncode
|
||||
|
||||
def get_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument("-m", "--mcu",
|
||||
help="Build for the given MCU",
|
||||
default=None,
|
||||
choices=get_tfm_secure_targets())
|
||||
hmsg = "Build for the given tool chain (default is tfm_default_toolchain)"
|
||||
parser.add_argument("-t", "--toolchain",
|
||||
help=hmsg,
|
||||
default=None,
|
||||
choices=["ARMCLANG", "GNUARM"])
|
||||
|
||||
parser.add_argument("-d", "--debug",
|
||||
help="Set build profile to debug",
|
||||
action="store_true",
|
||||
default=False)
|
||||
|
||||
parser.add_argument('-l', '--list',
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Print supported TF-M secure targets")
|
||||
|
||||
parser.add_argument("--clone",
|
||||
help="Clone TF-M git repo and its dependencies",
|
||||
action="store_true",
|
||||
default=False)
|
||||
|
||||
parser.add_argument("--commit",
|
||||
help="Create a git commit for each platform",
|
||||
action="store_true",
|
||||
default=False)
|
||||
|
||||
parser.add_argument("--clean-build",
|
||||
help="Remove cmake build directory",
|
||||
action="store_true",
|
||||
default=False)
|
||||
|
||||
parser.add_argument("-v", "--verbose",
|
||||
help="Verbose output",
|
||||
action="store_true",
|
||||
default=False)
|
||||
|
||||
return parser
|
||||
|
||||
def clean_build_directory():
|
||||
cmake_build_dir = join(TF_M_BUILD_DIR, 'trusted-firmware-m', 'cmake_build')
|
||||
if isdir(cmake_build_dir):
|
||||
logger.info("Removing cmake build directory %s" %
|
||||
relpath(cmake_build_dir))
|
||||
shutil.rmtree(cmake_build_dir)
|
||||
|
||||
def main():
|
||||
"""
|
||||
Build Trusted Firmware M (TF-M) image for mbed-os supported TF-M targets.
|
||||
Current version of the script only clones TF-M git repo and dependencies
|
||||
and creates a VERSION.txt file under 'features/FEATURE_PSA/FEATURE_TFM'
|
||||
Build Trusted Firmware M (TF-M) image for mbed-os supported TF-M targets
|
||||
"""
|
||||
|
||||
parser = get_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.clean_build:
|
||||
clean_build_directory()
|
||||
return
|
||||
|
||||
if args.verbose:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
if args.list:
|
||||
logger.info("Supported TF-M platforms are: {}".format(
|
||||
', '.join([t for t in get_tfm_secure_targets()])))
|
||||
return
|
||||
|
||||
if not isdir(TF_M_BUILD_DIR):
|
||||
os.mkdir(TF_M_BUILD_DIR)
|
||||
clone_tfm_repo()
|
||||
|
||||
clone_tfm_repo(args.commit)
|
||||
if args.clone:
|
||||
return
|
||||
|
||||
cmake_build_dir = join(TF_M_BUILD_DIR, 'trusted-firmware-m', 'cmake_build')
|
||||
if not isdir(cmake_build_dir):
|
||||
os.mkdir(cmake_build_dir)
|
||||
|
||||
debug = False
|
||||
if args.mcu:
|
||||
tgt = None
|
||||
if args.toolchain:
|
||||
msg = "Building TF-M for target %s using toolchain %s" % (args.mcu,
|
||||
args.toolchain)
|
||||
logger.info(msg)
|
||||
tgt = get_target_info(args.mcu, args.toolchain)
|
||||
else:
|
||||
tgt = get_target_info(args.mcu)
|
||||
msg = "Building TF-M for target %s using default toolchain %s" % (
|
||||
args.mcu, tgt[2])
|
||||
logger.info(msg)
|
||||
|
||||
if args.debug:
|
||||
debug = True
|
||||
|
||||
retcode = run_cmake_build(True, cmake_build_dir, tgt[4], tgt[1],
|
||||
tgt[2], debug)
|
||||
if retcode:
|
||||
msg = "Cmake configure failed for target %s using toolchain %s" % (
|
||||
tgt[0], tgt[2])
|
||||
logger.critical(msg)
|
||||
sys.exit(1)
|
||||
|
||||
retcode = run_cmake_build(False, cmake_build_dir)
|
||||
if retcode:
|
||||
msg = "Cmake build failed for target %s using toolchain %s" % (
|
||||
tgt[0], tgt[2])
|
||||
logger.critical(msg)
|
||||
sys.exit(1)
|
||||
|
||||
output_dir = None
|
||||
if(tgt[3].endswith('/')):
|
||||
output_dir = tgt[3]
|
||||
else:
|
||||
output_dir = tgt[3] + '/'
|
||||
tfm_secure_bin = join(cmake_build_dir, 'install', 'outputs', tgt[1],
|
||||
'tfm_s.bin')
|
||||
logger.info("Copying %s to %s" % (relpath(tfm_secure_bin, ROOT),
|
||||
relpath(output_dir, ROOT)))
|
||||
shutil.copy2(tfm_secure_bin, output_dir)
|
||||
|
||||
if args.commit:
|
||||
commit_changes(tgt[3], tgt[0], tgt[2])
|
||||
else:
|
||||
for tgt in get_mbed_supported_tfm_targets():
|
||||
msg = "Building TF-M for target %s using default toolchain %s" % (
|
||||
tgt[0], tgt[2])
|
||||
logger.info(msg)
|
||||
|
||||
if args.debug:
|
||||
debug = True
|
||||
|
||||
retcode = run_cmake_build(True, cmake_build_dir, tgt[4], tgt[1],
|
||||
tgt[2], debug)
|
||||
if retcode:
|
||||
msg = "Cmake configure failed for target %s with toolchain %s" % (
|
||||
tgt[0], tgt[2])
|
||||
logger.critical(msg)
|
||||
sys.exit(1)
|
||||
retcode = run_cmake_build(False, cmake_build_dir)
|
||||
if retcode:
|
||||
msg = "Cmake build failed for target %s using toolchain %s" % (
|
||||
tgt[0], tgt[2])
|
||||
logger.critical(msg)
|
||||
sys.exit(1)
|
||||
|
||||
output_dir = None
|
||||
if(tgt[3].endswith('/')):
|
||||
output_dir = tgt[3]
|
||||
else:
|
||||
output_dir = tgt[3] + '/'
|
||||
|
||||
tfm_secure_bin = join(cmake_build_dir, 'install', 'outputs',
|
||||
tgt[1], 'tfm_s.bin')
|
||||
logger.info("Copying %s to %s" % (relpath(tfm_secure_bin, ROOT),
|
||||
relpath(output_dir, ROOT)))
|
||||
shutil.copy2(tfm_secure_bin, output_dir)
|
||||
|
||||
if args.commit:
|
||||
commit_changes(tgt[3], tgt[0], tgt[2])
|
||||
|
||||
if __name__ == '__main__':
|
||||
if is_git_installed() != 0:
|
||||
logger.error('"git" is not installed. Exiting...')
|
||||
elif is_git_lfs_installed() != 0:
|
||||
logger.error('"git-lfs" is not installed. Exiting...')
|
||||
elif is_cmake_installed() != 0:
|
||||
logger.error('"cmake" is not installed. Exiting...')
|
||||
else:
|
||||
main()
|
||||
|
|
|
@ -418,8 +418,8 @@ class Target(namedtuple(
|
|||
return 'NSPE_Target' in self.labels
|
||||
|
||||
@property
|
||||
def is_PSA_target(self):
|
||||
return self.is_PSA_secure_target or self.is_PSA_non_secure_target
|
||||
def is_TFM_target(self):
|
||||
return getattr(self, 'tfm_target_name', False)
|
||||
|
||||
def get_post_build_hook(self, toolchain_labels):
|
||||
"""Initialize the post-build hooks for a toolchain. For now, this
|
||||
|
|
Loading…
Reference in New Issue