Skip to content

Commit ba24cb2

Browse files
authored
Merge pull request #10010 from kfnta/psa_tools_docs_update
Update PSA tools
2 parents e0c7e08 + f534caa commit ba24cb2

File tree

2 files changed

+166
-53
lines changed

2 files changed

+166
-53
lines changed

tools/psa/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,18 @@ Each implementation requires a set of autogenerated files describing the secure
3434
`release.py` is the script assigned with compiling the secure images:
3535

3636
```
37-
usage: release.py [-h] [-m MCU]
37+
usage: release.py [-h] [-m MCU] [-d] [--commit]
3838
3939
optional arguments:
4040
-h, --help show this help message and exit
4141
-m MCU, --mcu MCU build for the given MCU
42+
-d, --debug set build profile to debug
43+
--commit create a git commit for each platform
4244
```
4345

44-
When `MCU ` is not specified, the script compiles all the images for all the targets.
46+
* When `MCU ` is not specified, the script compiles all the images for all the targets.
47+
* When `-d/--debug` is not specified, the script compiles the images using the release profile.
48+
* When `--commit` is not specified, the script will not commit the images to git.
4549

4650
This script should be run in following scenarios:
4751

tools/psa/release.py

Lines changed: 160 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,148 +21,257 @@
2121
import shutil
2222
from argparse import ArgumentParser
2323

24-
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
24+
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),
25+
os.pardir, os.pardir))
2526
sys.path.insert(0, ROOT)
2627
from tools.targets import Target, TARGET_MAP, TARGET_NAMES
2728

2829
MAKE_PY_LOCATTION = os.path.join(ROOT, 'tools', 'make.py')
2930
TEST_PY_LOCATTION = os.path.join(ROOT, 'tools', 'test.py')
30-
MBED_PSA_TESTS = '*psa-spm*,*psa-crypto_access_control'
3131
TFM_MBED_APP = os.path.join(ROOT, 'tools', 'psa', 'tfm', 'mbed_app.json')
32+
MBED_PSA_TESTS = '*psa-spm*,*psa-crypto_access_control'
3233
TFM_TESTS = {
3334
'*psa-spm_smoke': ['USE_PSA_TEST_PARTITIONS', 'USE_SMOKE_TESTS_PART1'],
3435
'*psa-spm_client': ['USE_PSA_TEST_PARTITIONS', 'USE_CLIENT_TESTS_PART1'],
35-
'*psa-spm_server': ['USE_PSA_TEST_PARTITIONS', 'USE_SERVER_TESTS_PART1', 'USE_SERVER_TESTS_PART2'],
36-
'*psa-crypto_access_control': ['USE_PSA_TEST_PARTITIONS', 'USE_CRYPTO_ACL_TEST']
36+
'*psa-spm_server': ['USE_PSA_TEST_PARTITIONS', 'USE_SERVER_TESTS_PART1',
37+
'USE_SERVER_TESTS_PART2'],
38+
'*psa-crypto_access_control': ['USE_PSA_TEST_PARTITIONS',
39+
'USE_CRYPTO_ACL_TEST']
3740
}
3841

3942

40-
def _psa_backend(target_name):
41-
return 'TFM' if 'TFM' in Target.get_target(target_name).labels else 'MBED_SPM'
43+
def _psa_backend(target):
44+
"""
45+
Returns a target PSA backend.
46+
47+
:param target: Target name as in targets.json
48+
:return: PSA backend as string (TFM/MBED_SPM)
49+
"""
50+
return 'TFM' if 'TFM' in Target.get_target(target).labels else 'MBED_SPM'
51+
52+
53+
def _get_target_info(target):
54+
"""
55+
Creates a PSA target tuple with default toolchain and
56+
artifact delivery directory.
57+
58+
:param target: Target name.
59+
:return: tuple (target, toolchain, delivery directory).
60+
"""
61+
delivery_dir = os.path.join(ROOT, 'targets',
62+
TARGET_MAP[target].delivery_dir)
63+
64+
if not os.path.exists(delivery_dir):
65+
raise Exception("{} does not have delivery_dir".format(target))
66+
67+
return tuple([TARGET_MAP[target].name,
68+
TARGET_MAP[target].default_toolchain,
69+
delivery_dir])
4270

4371

44-
def get_mbed_official_psa_release():
72+
def get_mbed_official_psa_release(target=None):
73+
"""
74+
Creates a list of PSA targets with default toolchain and
75+
artifact delivery directory.
76+
77+
:param target: Ask for specific target, None for all targets.
78+
:return: List of tuples (target, toolchain, delivery directory).
79+
"""
4580
psa_targets_release_list = []
46-
psa_secure_targets = [t for t in TARGET_NAMES if Target.get_target(t).is_PSA_secure_target]
47-
for t in psa_secure_targets:
48-
psa_targets_release_list.append(
49-
tuple(
50-
[
51-
TARGET_MAP[t].name,
52-
TARGET_MAP[t].default_toolchain
53-
]
54-
)
55-
)
81+
psa_secure_targets = [t for t in TARGET_NAMES if
82+
Target.get_target(t).is_PSA_secure_target]
83+
if target is not None:
84+
if target not in psa_secure_targets:
85+
raise Exception("{} is not a PSA secure target".format(target))
86+
psa_targets_release_list.append(_get_target_info(target))
87+
else:
88+
for t in psa_secure_targets:
89+
psa_targets_release_list.append(_get_target_info(target))
5690

5791
return psa_targets_release_list
5892

5993

6094
def create_mbed_ignore(build_dir):
95+
"""
96+
Creates a .mbedignore file in a given directory.
97+
98+
:param build_dir: Directory to create .mbedignore file.
99+
"""
61100
with open(os.path.join(build_dir, '.mbedignore'), 'w') as f:
62101
f.write('*\n')
63102

64103

65104
def build_mbed_spm_platform(target, toolchain, profile='release'):
66-
subprocess.call([
105+
"""
106+
Builds Secure images for MBED-SPM target.
107+
108+
:param target: target to be built.
109+
:param toolchain: toolchain to be used.
110+
:param profile: build profile.
111+
"""
112+
subprocess.check_call([
67113
sys.executable, '-u', TEST_PY_LOCATTION,
68114
'--greentea',
69115
'--profile', profile,
70116
'-t', toolchain,
71117
'-m', target,
72118
'--source', ROOT,
73119
'--build', os.path.join(ROOT, 'BUILD', 'tests', target),
74-
'--test-spec', os.path.join(ROOT, 'BUILD', 'tests', target, 'test_spec.json'),
75-
'--build-data', os.path.join(ROOT, 'BUILD', 'tests', target, 'build_data.json'),
120+
'--test-spec', os.path.join(ROOT, 'BUILD', 'tests',
121+
target, 'test_spec.json'),
122+
'--build-data', os.path.join(ROOT, 'BUILD', 'tests',
123+
target, 'build_data.json'),
76124
'-n', MBED_PSA_TESTS
77-
])
125+
], stdout=subprocess.PIPE)
78126

79-
subprocess.call([
127+
subprocess.check_call([
80128
sys.executable, '-u', MAKE_PY_LOCATTION,
81129
'-t', toolchain,
82130
'-m', target,
83131
'--profile', profile,
84132
'--source', ROOT,
85133
'--build', os.path.join(ROOT, 'BUILD', target),
86134
'--artifact-name', 'psa_release_1.0'
87-
])
135+
], stdout=subprocess.PIPE)
88136

89137

90138
def _tfm_test_defines(test):
139+
"""
140+
Creates a define list to enable test partitions on TF-M.
141+
142+
:param test: Test name.
143+
:return: List of defines with a leading -D.
144+
"""
91145
return ['-D{}'.format(define) for define in TFM_TESTS[test]]
92146

93147

94148
def build_tfm_platform(target, toolchain, profile='release'):
149+
"""
150+
Builds Secure images for TF-M target.
151+
152+
:param target: target to be built.
153+
:param toolchain: toolchain to be used.
154+
:param profile: build profile.
155+
"""
95156
for test in TFM_TESTS.keys():
96-
subprocess.call([
157+
subprocess.check_call([
97158
sys.executable, '-u', TEST_PY_LOCATTION,
98159
'--greentea',
99160
'--profile', profile,
100161
'-t', toolchain,
101162
'-m', target,
102163
'--source', ROOT,
103164
'--build', os.path.join(ROOT, 'BUILD', 'tests', target),
104-
'--test-spec', os.path.join(ROOT, 'BUILD', 'tests', target, 'test_spec.json'),
105-
'--build-data', os.path.join(ROOT, 'BUILD', 'tests', target, 'build_data.json'),
106-
'--app-config', TFM_MBED_APP, '-n', test] + _tfm_test_defines(test))
107-
108-
subprocess.call([
165+
'--test-spec', os.path.join(ROOT, 'BUILD', 'tests',
166+
target, 'test_spec.json'),
167+
'--build-data', os.path.join(ROOT, 'BUILD', 'tests',
168+
target, 'build_data.json'),
169+
'--app-config', TFM_MBED_APP, '-n', test] + _tfm_test_defines(test),
170+
stdout=subprocess.PIPE)
171+
172+
subprocess.check_call([
109173
sys.executable, '-u', MAKE_PY_LOCATTION,
110174
'-t', toolchain,
111175
'-m', target,
112176
'--profile', profile,
113177
'--source', ROOT,
114178
'--build', os.path.join(ROOT, 'BUILD', target),
115179
'--app-config', TFM_MBED_APP
116-
])
117-
118-
119-
def build_psa_platform(target, toolchain, debug=False):
180+
], stdout=subprocess.PIPE)
181+
182+
183+
def commit_binaries(target, delivery_dir):
184+
"""
185+
Commits changes in secure binaries.
186+
187+
:param target: Target name.
188+
:param delivery_dir: Secure images should be moved to this folder
189+
by the build system.
190+
"""
191+
changes_made = subprocess.call([
192+
'git',
193+
'-C', ROOT,
194+
'diff', '--exit-code',
195+
delivery_dir
196+
], stdout=subprocess.PIPE)
197+
198+
if changes_made:
199+
subprocess.check_call([
200+
'git',
201+
'-C', ROOT,
202+
'add', os.path.relpath(delivery_dir, ROOT)
203+
], stdout=subprocess.PIPE)
204+
205+
commit_message = '-m\"Update secure binaries for {}\"'.format(target)
206+
subprocess.check_call([
207+
'git',
208+
'-C', ROOT,
209+
'commit',
210+
commit_message
211+
], stdout=subprocess.PIPE)
212+
213+
214+
def build_psa_platform(target, toolchain, delivery_dir, debug=False,
215+
git_commit=False):
216+
"""
217+
Calls the correct build function and commits if requested.
218+
219+
:param target: Target name.
220+
:param toolchain: Toolchain to be used.
221+
:param delivery_dir: Artifact directory, where images should be placed.
222+
:param debug: Build with debug profile.
223+
:param git_commit: Commit the changes.
224+
"""
120225
profile = 'debug' if debug else 'release'
121226
if _psa_backend(target) is 'TFM':
122227
build_tfm_platform(target, toolchain, profile)
123228
else:
124229
build_mbed_spm_platform(target, toolchain, profile)
125230

231+
if git_commit:
232+
commit_binaries(target, delivery_dir)
233+
126234

127235
def get_parser():
128236
parser = ArgumentParser()
129237
parser.add_argument("-m", "--mcu",
130238
help="build for the given MCU",
131-
default='*',
239+
default=None,
132240
metavar="MCU")
133241

134242
parser.add_argument("-d", "--debug",
135-
help="build for the given MCU",
243+
help="set build profile to debug",
136244
action="store_true",
137245
default=False)
138246

139-
return parser
140-
141-
142-
def filter_target(mcu):
143-
def filter_func(t):
144-
return t[0] == mcu
247+
parser.add_argument("--commit",
248+
help="create a git commit for each platform",
249+
action="store_true",
250+
default=False)
145251

146-
return filter_func
252+
return parser
147253

148254

149-
def main():
150-
parser = get_parser()
151-
options = parser.parse_args()
255+
def prep_build_dir():
256+
"""
257+
Creates a clean BUILD directory
258+
"""
152259
build_dir = os.path.join(ROOT, 'BUILD')
153260
if os.path.exists(build_dir):
154261
shutil.rmtree(build_dir)
155262

156263
os.makedirs(build_dir)
157264
create_mbed_ignore(build_dir)
158-
target_filter_function = None
159-
psa_platforms_list = get_mbed_official_psa_release()
160265

161-
if options.mcu is not '*':
162-
target_filter_function = filter_target(options.mcu)
163266

164-
for target, toolchain in filter(target_filter_function, psa_platforms_list):
165-
build_psa_platform(target, toolchain, options.debug)
267+
def main():
268+
parser = get_parser()
269+
options = parser.parse_args()
270+
prep_build_dir()
271+
psa_platforms_list = get_mbed_official_psa_release(options.mcu)
272+
273+
for target, tc, directory in psa_platforms_list:
274+
build_psa_platform(target, tc, directory, options.debug, options.commit)
166275

167276

168277
if __name__ == '__main__':

0 commit comments

Comments
 (0)