Skip to content

Commit 8c5ba91

Browse files
alzixAlexander Zilberkant
authored andcommitted
Update PSA code generator
Unify TF-M and Mbed-SPM code generators: - Unify SPM initialization logic: - All partitions are registered at once - Test partitions are guarded by #ifndef - Introduce single template list - Beatify template files and add "Autogen-do not modify" notice Prepare for integration with mbed-os build system: - Generate all the files in a single place Simplify tools/psa/release.py script
1 parent ab01bea commit 8c5ba91

24 files changed

+686
-846
lines changed
Lines changed: 5 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2019 ARM Limited
1+
/* Copyright (c) 2017-2018 ARM Limited
22
*
33
* SPDX-License-Identifier: Apache-2.0
44
*
@@ -15,68 +15,9 @@
1515
* limitations under the License.
1616
*/
1717

18-
/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
18+
#ifndef __SID_H__
19+
#define __SID_H__
1920

20-
/******** ATTEST_SRV ********/
21-
#define PSA_ATTEST_GET_TOKEN_ID 0x00000F10
22-
#define PSA_ATTEST_GET_TOKEN_SIZE_ID 0x00000F11
23-
#define PSA_ATTEST_INJECT_KEY_ID 0x00000F12
24-
25-
/******** CRYPTO_SRV ********/
26-
#define PSA_CRYPTO_INIT_ID 0x00000F00
27-
#define PSA_MAC_ID 0x00000F01
28-
#define PSA_HASH_ID 0x00000F02
29-
#define PSA_ASYMMETRIC_ID 0x00000F03
30-
#define PSA_SYMMETRIC_ID 0x00000F04
31-
#define PSA_AEAD_ID 0x00000F05
32-
#define PSA_KEY_MNG_ID 0x00000F06
33-
#define PSA_RNG_ID 0x00000F07
34-
#define PSA_CRYPTO_FREE_ID 0x00000F08
35-
#define PSA_GENERATOR_ID 0x00000F09
36-
#define PSA_ENTROPY_ID 0x00000F0A
37-
38-
/******** PLATFORM ********/
39-
#define PSA_PLATFORM_LC_GET 0x00011000
40-
#define PSA_PLATFORM_LC_SET 0x00011001
41-
#define PSA_PLATFORM_SYSTEM_RESET 0x00011002
42-
43-
/******** ITS ********/
44-
#define PSA_ITS_GET 0x00011A00
45-
#define PSA_ITS_SET 0x00011A01
46-
#define PSA_ITS_INFO 0x00011A02
47-
#define PSA_ITS_REMOVE 0x00011A03
48-
#define PSA_ITS_RESET 0x00011A04
49-
50-
51-
52-
/******** CRYPTO_ACL_TEST ********/
53-
#define CRYPTO_CREATE_PERSISTENT_KEY 0x00000200
54-
#define CRYPTO_GENERATE_KEY 0x00000201
55-
#define CRYPTO_OPEN_PERSISTENT_KEY 0x00000202
56-
#define CRYPTO_CLOSE_KEY 0x00000203
57-
#define CRYPTO_SET_KEY_POLICY 0x00000204
58-
#define CRYPTO_DESTROY_KEY 0x00000205
59-
#define CRYPTO_GET_KEY_INFO 0x00000206
60-
#define CRYPTO_GET_KEY_POLICY 0x00000207
61-
#define CRYPTO_IMPORT_KEY 0x00000208
62-
63-
64-
/******** CLIENT_TESTS_PART1 ********/
65-
#define CLIENT_TESTS_PART1_ROT_SRV1 0x00001A05
66-
#define CLIENT_TESTS_PART1_DROP_CONN 0x00001A06
67-
#define CLIENT_TESTS_PART1_SECURE_CLIENTS_ONLY 0x00001A07
68-
69-
70-
/******** SERVER_TESTS_PART1 ********/
71-
#define SERVER_TESTS_PART1_CONTROL 0x00001A01
72-
#define SERVER_TESTS_PART1_TEST 0x00001A02
73-
74-
75-
/******** SERVER_TESTS_PART2 ********/
76-
#define SERVER_TESTS_PART2_ROT_SRV_REVERSE 0x00001A03
77-
#define SERVER_TESTS_PART2_ROT_SRV_DB_TST 0x00001A04
78-
79-
80-
/******** SMOKE_TESTS_PART1 ********/
81-
#define SMOKE_TESTS_PART1_ROT_SRV1 0x00001A00
21+
#include "autogen_sid.h"
8222

23+
#endif // __SID_H__

tools/psa/__init__.py

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,65 @@
1515
# See the License for the specific language governing permissions and
1616
# limitations under the License.
1717

18-
from os.path import basename, splitext
18+
import os
19+
import shutil
20+
1921
from tools.resources import FileType
22+
from tools.settings import ROOT
23+
from .generate_partition_code import manifests_discovery, generate_spm_code
24+
2025

2126

22-
def find_secure_image(notify, resources, ns_image_path, configured_s_image_filename, image_type):
27+
def find_secure_image(notify, resources, ns_image_path,
28+
configured_s_image_filename, image_type):
2329
""" Find secure image. """
2430
if configured_s_image_filename is None:
2531
return None
2632

27-
assert ns_image_path and configured_s_image_filename, 'ns_image_path and configured_s_image_path are mandatory'
28-
assert image_type in [FileType.BIN, FileType.HEX], 'image_type must be of type BIN or HEX'
33+
assert ns_image_path and configured_s_image_filename, \
34+
'ns_image_path and configured_s_image_path are mandatory'
35+
assert image_type in [FileType.BIN, FileType.HEX], \
36+
'image_type must be of type BIN or HEX'
2937

3038
image_files = resources.get_file_paths(image_type)
3139
assert image_files, 'No image files found for this target'
3240

33-
secure_image = next((f for f in image_files if basename(f) == configured_s_image_filename), None)
3441
secure_image = next(
35-
(f for f in image_files if splitext(basename(f))[0] == splitext(basename(ns_image_path))[0]),
42+
(f for f in image_files if
43+
os.path.basename(f) == configured_s_image_filename), None)
44+
secure_image = next(
45+
(f for f in image_files if
46+
os.path.splitext(os.path.basename(f))[0] ==
47+
os.path.splitext(os.path.basename(ns_image_path))[0]),
3648
secure_image
3749
)
3850

3951
if secure_image:
4052
notify.debug("Secure image file found: %s." % secure_image)
4153
else:
42-
notify.debug("Secure image file %s not found. Aborting." % configured_s_image_filename)
54+
notify.debug("Secure image file %s not found. Aborting."
55+
% configured_s_image_filename)
4356
raise Exception("Required secure image not found.")
4457

4558
return secure_image
59+
60+
61+
def _get_psa_autogen_dir():
62+
return os.path.join(ROOT, 'PSA_AUTOGEN')
63+
64+
65+
def clean_psa_autogen():
66+
psa_out_dir = _get_psa_autogen_dir()
67+
68+
if os.path.isdir(psa_out_dir):
69+
shutil.rmtree(psa_out_dir)
70+
71+
72+
def generate_psa_sources(source_dirs, ignore_paths):
73+
services, apps = manifests_discovery(root_dirs=source_dirs,
74+
ignore_paths=ignore_paths + ['.git'])
75+
assert len(services + apps), 'PSA manifest discovery failed'
76+
psa_out_dir = _get_psa_autogen_dir()
77+
78+
generate_spm_code(services, apps, psa_out_dir)
79+
return psa_out_dir

tools/psa/generate_partition_code.py

Lines changed: 69 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1515
# See the License for the specific language governing permissions and
1616
# limitations under the License.
17-
17+
import argparse
1818
import itertools
1919
import json
2020
import os
@@ -27,149 +27,102 @@
2727

2828
from tools.psa.mbed_spm_tfm_common import validate_partition_manifests, \
2929
manifests_discovery, parse_manifests, generate_source_files, \
30-
MBED_OS_ROOT, SERVICES_DIR, TESTS_DIR
30+
MBED_OS_ROOT
3131

32-
__version__ = '1.0'
32+
__version__ = '1.1'
3333
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
3434
MANIFEST_FILE_PATTERN = '*_psa.json'
3535
PSA_CORE_ROOT = path_join(MBED_OS_ROOT, 'components', 'TARGET_PSA')
36-
TFM_TEMPLATES_DESC = path_join(SCRIPT_DIR, 'tfm', 'tfm_generated_file_list.json')
37-
MBED_SPM_TEMPLATES_DESC = path_join(SCRIPT_DIR, 'mbed_spm', 'mbed_spm_generated_file_list.json')
38-
MBED_SPM_TEMPLATES_DIR = path_join(SCRIPT_DIR, 'mbed_spm', 'templates')
39-
40-
41-
def generate_partitions_sources(manifest_files, extra_filters=None):
42-
"""
43-
Process all the given manifest files and generate C code from them
44-
45-
:param manifest_files: List of manifest files
46-
:param extra_filters: Dictionary of extra filters to use in the rendering
47-
process
48-
:return: List of paths to the generated files
49-
"""
50-
51-
# Construct a list of all the manifests and sids.
52-
manifests, _ = parse_manifests(manifest_files, 'MBED_SPM')
53-
54-
with open(MBED_SPM_TEMPLATES_DESC, 'r') as fh:
55-
template_data = json.load(fh)
56-
manifest_template_list = [path_join(MBED_OS_ROOT, t['template'])
57-
for t in template_data['partition']]
58-
59-
generated_folders = set()
60-
for manifest in manifests:
61-
manifest_output_folder = manifest.autogen_folder
62-
render_args = {
63-
'partition': manifest,
64-
'dependent_partitions': manifest.find_dependencies(manifests),
65-
'script_ver': __version__
66-
}
36+
TEMPLATES_DESC = path_join(SCRIPT_DIR, 'spm_template_file_list.json')
37+
38+
39+
def _get_timestamp(f):
40+
return os.path.getmtime(f) if os.path.isfile(f) else 0
6741

68-
manifest_output_folder = generate_source_files(
69-
manifest.templates_to_files(manifest_template_list,
70-
MBED_SPM_TEMPLATES_DIR,
71-
manifest_output_folder),
72-
render_args,
73-
manifest_output_folder,
74-
extra_filters=extra_filters
75-
)
76-
77-
generated_folders.add(manifest_output_folder)
78-
79-
return list(generated_folders)
80-
81-
82-
def generate_psa_setup(manifest_files, output_dir, weak_setup, extra_filters=None):
83-
"""
84-
Process all the given manifest files and generate C setup code from them
85-
:param manifest_files: List of manifest files
86-
:param output_dir: Output directory for the generated files
87-
:param weak_setup: Is the functions/data in the setup file weak
88-
(can be overridden by another setup file)
89-
:param extra_filters: Dictionary of extra filters to use in the rendering
90-
process
91-
:return: path to the setup generated files
92-
"""
93-
with open(MBED_SPM_TEMPLATES_DESC, 'r') as fh:
94-
template_data = json.load(fh)
42+
43+
def is_up_to_date(manifest_files, out_files):
44+
manifest_timestamp = max(_get_timestamp(f) for f in manifest_files)
45+
out_timestamps = min(_get_timestamp(f) for f in out_files)
46+
return manifest_timestamp <= out_timestamps
47+
48+
49+
def generate_spm_code(service_files, app_files, output_dir):
50+
with open(TEMPLATES_DESC, 'r') as fh:
51+
templates_data = json.load(fh)
9552
templates_dict = {
9653
path_join(MBED_OS_ROOT, t['template']):
97-
path_join(output_dir, t['target'])
98-
for t in template_data['common']
54+
path_join(output_dir, t['output']) for t in templates_data
9955
}
10056

57+
if is_up_to_date(service_files + app_files, list(templates_dict.values())):
58+
return
59+
10160
# Construct lists of all the manifests and mmio_regions.
102-
manifests, region_list = parse_manifests(manifest_files, 'MBED_SPM')
61+
service_manifests, service_region_list = parse_manifests(service_files)
62+
test_manifests, test_region_list = parse_manifests(app_files)
10363

10464
# Validate the correctness of the manifest collection.
105-
validate_partition_manifests(manifests)
65+
validate_partition_manifests(service_manifests + test_manifests)
66+
67+
region_list = service_region_list + test_region_list
10668

10769
render_args = {
108-
'partitions': manifests,
70+
'service_partitions': service_manifests,
71+
'test_partitions': test_manifests,
72+
'script_ver': __version__,
10973
'regions': region_list,
11074
'region_pair_list': list(itertools.combinations(region_list, 2)),
111-
'weak': weak_setup,
112-
'script_ver': __version__
11375
}
11476

115-
return generate_source_files(
116-
templates_dict,
117-
render_args,
118-
output_dir,
119-
extra_filters=extra_filters
120-
)
121-
122-
123-
def generate_psa_code(service_files, test_files):
124-
# Generate partition code for each manifest file
125-
generate_partitions_sources(service_files + test_files)
126-
127-
# Generate default system psa setup file (only system partitions)
128-
generate_psa_setup(service_files, PSA_CORE_ROOT, weak_setup=True)
77+
generate_source_files(templates_dict, render_args)
12978

130-
tests_dict = {}
131-
for test_manifest in test_files:
132-
test_dir = os.path.dirname(test_manifest)
133-
if test_dir not in tests_dict:
134-
tests_dict[test_dir] = [test_manifest]
135-
else:
136-
tests_dict[test_dir].append(test_manifest)
13779

138-
for test_dir in tests_dict:
139-
generate_psa_setup(service_files + tests_dict[test_dir],
140-
test_dir, weak_setup=False)
80+
class AppendReadableDir(argparse.Action):
81+
def __call__(self, parser, namespace, values, option_string=None):
82+
prosp_dir = os.path.abspath(values)
83+
if not os.path.isdir(prosp_dir):
84+
raise argparse.ArgumentTypeError("{} is missing".format(prosp_dir))
85+
if not os.access(prosp_dir, os.R_OK):
86+
raise argparse.ArgumentTypeError(
87+
"{} is not a accessible for read".format(prosp_dir))
88+
if not getattr(namespace, self.dest):
89+
setattr(namespace, self.dest, [])
90+
getattr(namespace, self.dest).append(prosp_dir)
14191

14292

143-
def generate_tfm_code(service_files, test_files):
144-
# Construct lists of all the manifests and mmio_regions.
145-
service_manifests, service_region_list = parse_manifests(
146-
service_files, 'TFM')
147-
test_manifests, test_region_list = parse_manifests(
148-
test_files, 'TFM')
93+
def get_parser():
94+
parser = argparse.ArgumentParser(
95+
description='PSA SPM code generator',
96+
formatter_class=argparse.ArgumentDefaultsHelpFormatter
97+
)
98+
parser.add_argument(
99+
'-u', '--user-app',
100+
action=AppendReadableDir,
101+
default=[ROOT],
102+
help='Root directory for recursive PSA manifest scan. Use for adding '
103+
'application specific secure partitions. Can be supplied more '
104+
'than once',
105+
metavar='DIR'
106+
)
149107

150-
# Validate the correctness of the manifest collection.
151-
validate_partition_manifests(service_manifests + test_manifests)
108+
parser.add_argument(
109+
'-o', '--output-dir',
110+
default=ROOT,
111+
help='Root directory for generating the sources',
112+
metavar='DIR'
113+
)
152114

153-
render_args = {
154-
'service_partitions': service_manifests,
155-
'test_partitions': test_manifests
156-
}
115+
return parser
157116

158-
with open(TFM_TEMPLATES_DESC, 'r') as fh:
159-
templates_data = json.load(fh)
160-
templates_dict = {
161-
path_join(MBED_OS_ROOT, t['template']):
162-
path_join(MBED_OS_ROOT, t['output']) for t in templates_data
163-
}
164117

165-
generate_source_files(templates_dict, render_args, MBED_OS_ROOT)
118+
def main():
119+
parser = get_parser()
120+
args = parser.parse_args()
166121

122+
services, apps = manifests_discovery(root_dirs=args.user_app,
123+
ignore_paths=['BUILD', '.git'])
167124

168-
def main():
169-
services, _ = manifests_discovery(root_dir=SERVICES_DIR)
170-
_, tests = manifests_discovery(root_dir=TESTS_DIR)
171-
generate_psa_code(services, tests)
172-
generate_tfm_code(services, tests)
125+
generate_spm_code(services, apps, args.output_dir)
173126

174127

175128
if __name__ == '__main__':

0 commit comments

Comments
 (0)