mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #10364 from kfnta/psa_codegen_refactor
Refactor PSA code generatorspull/10385/head
commit
2641fb38ce
|
@ -5,8 +5,6 @@ This document describes the following scripts:
|
|||
* \_\_init\_\_.py
|
||||
* generate_partition_code.py
|
||||
* mbed_spm_tfm_common.py
|
||||
* generate_mbed_spm_partition_code.py
|
||||
* generate_tfm_partition_code.py
|
||||
* release.py
|
||||
|
||||
## \_\_init\_\_.py
|
||||
|
@ -25,8 +23,6 @@ Mbed OS holds two implementations of PSA:
|
|||
Each implementation requires a set of auto-generated files describing the secure partitions:
|
||||
|
||||
* `generate_partition_code.py` - Generate files for both implementations.
|
||||
* `generate_mbed_spm_partition_code.py` - Generate files for MBED_SPM.
|
||||
* `generate_tfm_partition_code.py` - Generate files for TF-M.
|
||||
* `mbed_spm_tfm_common.py` - Holds common functions for both.
|
||||
|
||||
## Secure image generation
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (c) 2017-2018 ARM Limited
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import itertools
|
||||
import os
|
||||
import sys
|
||||
from os.path import join as path_join
|
||||
from jinja2 import Environment, FileSystemLoader, StrictUndefined
|
||||
|
||||
# Be sure that the tools directory is in the search path
|
||||
ROOT = os.path.abspath(path_join(os.path.dirname(__file__), os.pardir, os.pardir))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from tools.psa.mbed_spm_tfm_common import \
|
||||
Manifest, validate_partition_manifests, manifests_discovery, MBED_OS_ROOT
|
||||
|
||||
__version__ = '1.0'
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
TEMPLATES_DIR = path_join(SCRIPT_DIR, 'mbed_spm', 'templates')
|
||||
MANIFEST_TEMPLATES = [filename for filename in
|
||||
[os.path.join(dp, f) for dp, dn, fn in
|
||||
os.walk(TEMPLATES_DIR) for f in fn if f.endswith('.tpl')]
|
||||
if '_NAME_' in filename]
|
||||
COMMON_TEMPLATES = [filename for filename in
|
||||
[os.path.join(dp, f) for dp, dn, fn in
|
||||
os.walk(TEMPLATES_DIR) for f in fn if f.endswith('.tpl')]
|
||||
if '_NAME_' not in filename]
|
||||
MANIFEST_FILE_PATTERN = '*_psa.json'
|
||||
SPM_CORE_ROOT = path_join(MBED_OS_ROOT, 'components', 'TARGET_PSA')
|
||||
|
||||
|
||||
def generate_source_files(
|
||||
templates,
|
||||
render_args,
|
||||
output_folder,
|
||||
extra_filters=None
|
||||
):
|
||||
"""
|
||||
Generate SPM common C code from manifests using given templates
|
||||
|
||||
:param templates: Dictionary of template and their auto-generated products
|
||||
:param render_args: Dictionary of arguments that should be passed to render
|
||||
:param output_folder: Output directory for file generation
|
||||
:param extra_filters: Dictionary of extra filters to use in the rendering
|
||||
process
|
||||
:return: Path to generated folder containing common generated files
|
||||
"""
|
||||
|
||||
rendered_files = []
|
||||
templates_dirs = list(
|
||||
set([os.path.dirname(path) for path in templates])
|
||||
)
|
||||
template_files = {os.path.basename(t): t for t in templates}
|
||||
|
||||
# Load templates for the code generation.
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(templates_dirs),
|
||||
lstrip_blocks=True,
|
||||
trim_blocks=True,
|
||||
undefined=StrictUndefined
|
||||
)
|
||||
if extra_filters:
|
||||
env.filters.update(extra_filters)
|
||||
|
||||
for tf in template_files:
|
||||
template = env.get_template(tf)
|
||||
rendered_files.append(
|
||||
(templates[template_files[tf]], template.render(**render_args)))
|
||||
rendered_file_dir = os.path.dirname(templates[template_files[tf]])
|
||||
if not os.path.exists(rendered_file_dir):
|
||||
os.makedirs(rendered_file_dir)
|
||||
|
||||
if not os.path.exists(output_folder):
|
||||
os.makedirs(output_folder)
|
||||
|
||||
for fname, data in rendered_files:
|
||||
with open(fname, 'wt') as fh:
|
||||
fh.write(data)
|
||||
|
||||
return output_folder
|
||||
|
||||
|
||||
def generate_partitions_sources(manifest_files, extra_filters=None):
|
||||
"""
|
||||
Process all the given manifest files and generate C code from them
|
||||
|
||||
:param manifest_files: List of manifest files
|
||||
:param extra_filters: Dictionary of extra filters to use in the rendering
|
||||
process
|
||||
:return: List of paths to the generated files
|
||||
"""
|
||||
|
||||
# Construct a list of all the manifests and sids.
|
||||
manifests = []
|
||||
for manifest_file in manifest_files:
|
||||
manifest = Manifest.from_json(manifest_file)
|
||||
manifests.append(manifest)
|
||||
|
||||
generated_folders = set()
|
||||
for manifest in manifests:
|
||||
manifest_output_folder = manifest.autogen_folder
|
||||
|
||||
render_args = {
|
||||
'partition': manifest,
|
||||
'dependent_partitions': manifest.find_dependencies(manifests),
|
||||
'script_ver': __version__
|
||||
}
|
||||
manifest_output_folder = generate_source_files(
|
||||
manifest.templates_to_files(MANIFEST_TEMPLATES,
|
||||
TEMPLATES_DIR,
|
||||
manifest_output_folder),
|
||||
render_args,
|
||||
manifest_output_folder,
|
||||
extra_filters=extra_filters
|
||||
)
|
||||
generated_folders.add(manifest_output_folder)
|
||||
|
||||
return list(generated_folders)
|
||||
|
||||
|
||||
def generate_psa_setup(manifest_files, output_dir, weak_setup, extra_filters=None):
|
||||
"""
|
||||
Process all the given manifest files and generate C setup code from them
|
||||
:param manifest_files: List of manifest files
|
||||
:param output_dir: Output directory for the generated files
|
||||
:param weak_setup: Is the functions/data in the setup file weak
|
||||
(can be overridden by another setup file)
|
||||
:param extra_filters: Dictionary of extra filters to use in the rendering
|
||||
process
|
||||
:return: path to the setup generated files
|
||||
"""
|
||||
autogen_folder = output_dir
|
||||
templates_dict = {
|
||||
t: path_join(autogen_folder,
|
||||
os.path.relpath(os.path.splitext(t)[0], TEMPLATES_DIR))
|
||||
for t in COMMON_TEMPLATES
|
||||
}
|
||||
|
||||
complete_source_list = list(templates_dict.values())
|
||||
|
||||
# Construct lists of all the manifests and mmio_regions.
|
||||
region_list = []
|
||||
manifests = []
|
||||
for manifest_file in manifest_files:
|
||||
manifest_obj = Manifest.from_json(manifest_file)
|
||||
manifests.append(manifest_obj)
|
||||
for region in manifest_obj.mmio_regions:
|
||||
region_list.append(region)
|
||||
complete_source_list.extend(
|
||||
list(manifest_obj.templates_to_files(
|
||||
MANIFEST_TEMPLATES,
|
||||
TEMPLATES_DIR,
|
||||
manifest_obj.autogen_folder).values())
|
||||
)
|
||||
|
||||
# Validate the correctness of the manifest collection.
|
||||
validate_partition_manifests(manifests)
|
||||
|
||||
render_args = {
|
||||
'partitions': manifests,
|
||||
'regions': region_list,
|
||||
'region_pair_list': list(itertools.combinations(region_list, 2)),
|
||||
'weak': weak_setup,
|
||||
'script_ver': __version__
|
||||
}
|
||||
|
||||
return generate_source_files(
|
||||
templates_dict,
|
||||
render_args,
|
||||
autogen_folder,
|
||||
extra_filters=extra_filters
|
||||
)
|
||||
|
||||
|
||||
def generate_psa_code():
|
||||
# Find all manifest files in the mbed-os tree
|
||||
service_manifest_files, test_manifest_files = manifests_discovery(root_dir=MBED_OS_ROOT)
|
||||
|
||||
# Generate partition code for each manifest file
|
||||
generate_partitions_sources(service_manifest_files + test_manifest_files)
|
||||
|
||||
# Generate default system psa setup file (only system partitions)
|
||||
generate_psa_setup(service_manifest_files,
|
||||
SPM_CORE_ROOT, weak_setup=True)
|
||||
|
||||
tests_dict = {}
|
||||
for test_manifest in test_manifest_files:
|
||||
test_dir = os.path.dirname(test_manifest)
|
||||
if test_dir not in tests_dict:
|
||||
tests_dict[test_dir] = [test_manifest]
|
||||
else:
|
||||
tests_dict[test_dir].append(test_manifest)
|
||||
|
||||
for test_dir in tests_dict:
|
||||
generate_psa_setup(service_manifest_files + tests_dict[test_dir],
|
||||
test_dir, weak_setup=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
generate_psa_code()
|
|
@ -15,8 +15,162 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from generate_mbed_spm_partition_code import generate_psa_code
|
||||
from generate_tfm_partition_code import generate_tfm_code
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from os.path import join as path_join
|
||||
|
||||
generate_psa_code()
|
||||
generate_tfm_code()
|
||||
# Be sure that the tools directory is in the search path
|
||||
ROOT = os.path.abspath(path_join(os.path.dirname(__file__), os.pardir, os.pardir))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from tools.psa.mbed_spm_tfm_common import validate_partition_manifests, \
|
||||
manifests_discovery, parse_manifests, generate_source_files, \
|
||||
MBED_OS_ROOT, SERVICES_DIR, TESTS_DIR
|
||||
|
||||
__version__ = '1.0'
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
MANIFEST_FILE_PATTERN = '*_psa.json'
|
||||
PSA_CORE_ROOT = path_join(MBED_OS_ROOT, 'components', 'TARGET_PSA')
|
||||
TFM_TEMPLATES_DESC = path_join(SCRIPT_DIR, 'tfm', 'tfm_generated_file_list.json')
|
||||
MBED_SPM_TEMPLATES_DESC = path_join(SCRIPT_DIR, 'mbed_spm', 'mbed_spm_generated_file_list.json')
|
||||
MBED_SPM_TEMPLATES_DIR = path_join(SCRIPT_DIR, 'mbed_spm', 'templates')
|
||||
|
||||
|
||||
def generate_partitions_sources(manifest_files, extra_filters=None):
|
||||
"""
|
||||
Process all the given manifest files and generate C code from them
|
||||
|
||||
:param manifest_files: List of manifest files
|
||||
:param extra_filters: Dictionary of extra filters to use in the rendering
|
||||
process
|
||||
:return: List of paths to the generated files
|
||||
"""
|
||||
|
||||
# Construct a list of all the manifests and sids.
|
||||
manifests, _ = parse_manifests(manifest_files, 'MBED_SPM')
|
||||
|
||||
with open(MBED_SPM_TEMPLATES_DESC, 'r') as fh:
|
||||
template_data = json.load(fh)
|
||||
manifest_template_list = [path_join(MBED_OS_ROOT, t['template'])
|
||||
for t in template_data['partition']]
|
||||
|
||||
generated_folders = set()
|
||||
for manifest in manifests:
|
||||
manifest_output_folder = manifest.autogen_folder
|
||||
render_args = {
|
||||
'partition': manifest,
|
||||
'dependent_partitions': manifest.find_dependencies(manifests),
|
||||
'script_ver': __version__
|
||||
}
|
||||
|
||||
manifest_output_folder = generate_source_files(
|
||||
manifest.templates_to_files(manifest_template_list,
|
||||
MBED_SPM_TEMPLATES_DIR,
|
||||
manifest_output_folder),
|
||||
render_args,
|
||||
manifest_output_folder,
|
||||
extra_filters=extra_filters
|
||||
)
|
||||
|
||||
generated_folders.add(manifest_output_folder)
|
||||
|
||||
return list(generated_folders)
|
||||
|
||||
|
||||
def generate_psa_setup(manifest_files, output_dir, weak_setup, extra_filters=None):
|
||||
"""
|
||||
Process all the given manifest files and generate C setup code from them
|
||||
:param manifest_files: List of manifest files
|
||||
:param output_dir: Output directory for the generated files
|
||||
:param weak_setup: Is the functions/data in the setup file weak
|
||||
(can be overridden by another setup file)
|
||||
:param extra_filters: Dictionary of extra filters to use in the rendering
|
||||
process
|
||||
:return: path to the setup generated files
|
||||
"""
|
||||
with open(MBED_SPM_TEMPLATES_DESC, 'r') as fh:
|
||||
template_data = json.load(fh)
|
||||
templates_dict = {
|
||||
path_join(MBED_OS_ROOT, t['template']):
|
||||
path_join(output_dir, t['target'])
|
||||
for t in template_data['common']
|
||||
}
|
||||
|
||||
# Construct lists of all the manifests and mmio_regions.
|
||||
manifests, region_list = parse_manifests(manifest_files, 'MBED_SPM')
|
||||
|
||||
# Validate the correctness of the manifest collection.
|
||||
validate_partition_manifests(manifests)
|
||||
|
||||
render_args = {
|
||||
'partitions': manifests,
|
||||
'regions': region_list,
|
||||
'region_pair_list': list(itertools.combinations(region_list, 2)),
|
||||
'weak': weak_setup,
|
||||
'script_ver': __version__
|
||||
}
|
||||
|
||||
return generate_source_files(
|
||||
templates_dict,
|
||||
render_args,
|
||||
output_dir,
|
||||
extra_filters=extra_filters
|
||||
)
|
||||
|
||||
|
||||
def generate_psa_code(service_files, test_files):
|
||||
# Generate partition code for each manifest file
|
||||
generate_partitions_sources(service_files + test_files)
|
||||
|
||||
# Generate default system psa setup file (only system partitions)
|
||||
generate_psa_setup(service_files, PSA_CORE_ROOT, weak_setup=True)
|
||||
|
||||
tests_dict = {}
|
||||
for test_manifest in test_files:
|
||||
test_dir = os.path.dirname(test_manifest)
|
||||
if test_dir not in tests_dict:
|
||||
tests_dict[test_dir] = [test_manifest]
|
||||
else:
|
||||
tests_dict[test_dir].append(test_manifest)
|
||||
|
||||
for test_dir in tests_dict:
|
||||
generate_psa_setup(service_files + tests_dict[test_dir],
|
||||
test_dir, weak_setup=False)
|
||||
|
||||
|
||||
def generate_tfm_code(service_files, test_files):
|
||||
# Construct lists of all the manifests and mmio_regions.
|
||||
service_manifests, service_region_list = parse_manifests(
|
||||
service_files, 'TFM')
|
||||
test_manifests, test_region_list = parse_manifests(
|
||||
test_files, 'TFM')
|
||||
|
||||
# Validate the correctness of the manifest collection.
|
||||
validate_partition_manifests(service_manifests + test_manifests)
|
||||
|
||||
render_args = {
|
||||
'service_partitions': service_manifests,
|
||||
'test_partitions': test_manifests
|
||||
}
|
||||
|
||||
with open(TFM_TEMPLATES_DESC, 'r') as fh:
|
||||
templates_data = json.load(fh)
|
||||
templates_dict = {
|
||||
path_join(MBED_OS_ROOT, t['template']):
|
||||
path_join(MBED_OS_ROOT, t['output']) for t in templates_data
|
||||
}
|
||||
|
||||
generate_source_files(templates_dict, render_args, MBED_OS_ROOT)
|
||||
|
||||
|
||||
def main():
|
||||
services, _ = manifests_discovery(root_dir=SERVICES_DIR)
|
||||
_, tests = manifests_discovery(root_dir=TESTS_DIR)
|
||||
generate_psa_code(services, tests)
|
||||
generate_tfm_code(services, tests)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (c) 2017-2018 ARM Limited
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from os.path import join as path_join
|
||||
from jinja2 import Environment, FileSystemLoader, StrictUndefined
|
||||
|
||||
# Be sure that the tools directory is in the search path
|
||||
ROOT = os.path.abspath(path_join(os.path.dirname(__file__), os.pardir, os.pardir))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from tools.psa.mbed_spm_tfm_common import \
|
||||
Manifest, validate_partition_manifests, manifests_discovery, MBED_OS_ROOT
|
||||
|
||||
__version__ = '1.0'
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
TEMPLATES_LIST_FILE = path_join(SCRIPT_DIR, 'tfm', 'tfm_generated_file_list.json')
|
||||
|
||||
|
||||
def parse_manifests(manifests_files):
|
||||
region_list = []
|
||||
manifests = []
|
||||
for manifest_file in manifests_files:
|
||||
manifest_obj = Manifest.from_json(manifest_file, psa_type='TFM')
|
||||
manifests.append(manifest_obj)
|
||||
for region in manifest_obj.mmio_regions:
|
||||
region_list.append(region)
|
||||
|
||||
return manifests, region_list
|
||||
|
||||
|
||||
def generate_partition_source_files(service_manifest_files, test_manifest_files, extra_filters=None):
|
||||
"""
|
||||
Process all the given manifest files and generate C code from them.
|
||||
|
||||
:param service_manifest_files: List of PSA serices manifest files
|
||||
:param test_manifest_files: List of tests manifest files
|
||||
:param extra_filters: Dictionary of extra filters to use in the rendering
|
||||
process
|
||||
:return: path to the setup generated files
|
||||
"""
|
||||
|
||||
# Construct lists of all the manifests and mmio_regions.
|
||||
service_manifests, service_region_list = parse_manifests(service_manifest_files)
|
||||
test_manifests, test_region_list = parse_manifests(test_manifest_files)
|
||||
|
||||
# Validate the correctness of the manifest collection.
|
||||
validate_partition_manifests(service_manifests + test_manifests)
|
||||
|
||||
render_args = {
|
||||
'service_partitions': service_manifests,
|
||||
'test_partitions': test_manifests
|
||||
}
|
||||
|
||||
# Load templates for the code generation.
|
||||
with open(TEMPLATES_LIST_FILE, 'r') as fh:
|
||||
templates_data = json.load(fh)
|
||||
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(MBED_OS_ROOT),
|
||||
lstrip_blocks=True,
|
||||
trim_blocks=True,
|
||||
undefined=StrictUndefined
|
||||
)
|
||||
|
||||
if extra_filters:
|
||||
env.filters.update(extra_filters)
|
||||
|
||||
# Generate code for each template
|
||||
for tpl in templates_data:
|
||||
template = env.get_template(tpl['template'])
|
||||
data = template.render(**render_args)
|
||||
output_path = os.path.join(MBED_OS_ROOT, tpl['output'])
|
||||
output_folder = os.path.dirname(output_path)
|
||||
|
||||
if not os.path.exists(output_folder):
|
||||
os.makedirs(output_folder)
|
||||
|
||||
with open(output_path, 'wt') as fh:
|
||||
fh.write(data)
|
||||
|
||||
|
||||
def generate_tfm_code():
|
||||
service_manifests, tests_manifests = manifests_discovery(MBED_OS_ROOT)
|
||||
generate_partition_source_files(service_manifests, tests_manifests)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
generate_tfm_code()
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"common": [
|
||||
{
|
||||
"name": "mbed-SPM database",
|
||||
"template": "tools/psa/mbed_spm/templates/TARGET_MBED_SPM/COMPONENT_SPE/psa_setup.c.tpl",
|
||||
"target": "TARGET_MBED_SPM/COMPONENT_SPE/psa_setup.c"
|
||||
}
|
||||
],
|
||||
"partition": [
|
||||
{
|
||||
"name": "Details partition defines and structures",
|
||||
"template": "tools/psa/mbed_spm/templates/COMPONENT_SPE/psa_NAME_partition.h.tpl",
|
||||
"target": "COMPONENT_SPE/psa_NAME_partition.h"
|
||||
},
|
||||
{
|
||||
"name": "Details partition structures and init functions",
|
||||
"template": "tools/psa/mbed_spm/templates/TARGET_MBED_SPM/COMPONENT_SPE/psa_NAME_partition.c.tpl",
|
||||
"target": "TARGET_MBED_SPM/COMPONENT_SPE/psa_NAME_partition.c"
|
||||
},
|
||||
{
|
||||
"name": "Secure Service signals list",
|
||||
"template": "tools/psa/mbed_spm/templates/psa_NAME_ifs.h.tpl",
|
||||
"target": "psa_NAME_ifs.h"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -21,6 +21,7 @@ import json
|
|||
from jsonschema import validate
|
||||
import fnmatch
|
||||
from six import integer_types, string_types
|
||||
from jinja2 import Environment, FileSystemLoader, StrictUndefined
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
MBED_OS_ROOT = os.path.abspath(path_join(SCRIPT_DIR, os.pardir, os.pardir))
|
||||
|
@ -29,7 +30,7 @@ TESTS_DIR = path_join(MBED_OS_ROOT, "TESTS", "psa")
|
|||
MANIFEST_FILE_PATTERN = '*_psa.json'
|
||||
|
||||
|
||||
def assert_int(num):
|
||||
def _assert_int(num):
|
||||
"""
|
||||
Tries to parse an integer num from a given string
|
||||
|
||||
|
@ -74,13 +75,13 @@ class RotService(object):
|
|||
self.id = identifier
|
||||
self.signal = signal
|
||||
|
||||
assert assert_int(identifier)
|
||||
assert _assert_int(identifier)
|
||||
|
||||
assert isinstance(non_secure_clients, bool), \
|
||||
'non_secure_clients parameter must be of boolean type'
|
||||
self.nspe_callable = non_secure_clients
|
||||
|
||||
self.minor_version = assert_int(minor_version)
|
||||
self.minor_version = _assert_int(minor_version)
|
||||
assert self.minor_version > 0, 'minor_version parameter is invalid'
|
||||
|
||||
assert minor_policy in self.MINOR_POLICIES, \
|
||||
|
@ -89,7 +90,7 @@ class RotService(object):
|
|||
|
||||
@property
|
||||
def numeric_id(self):
|
||||
return assert_int(self.id)
|
||||
return _assert_int(self.id)
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
|
@ -131,10 +132,10 @@ class MmioRegion(object):
|
|||
self.size = '(sizeof(*({})))'.format(kwargs['name'])
|
||||
if 'base' in kwargs:
|
||||
self.base = kwargs['base']
|
||||
self.size = assert_int(kwargs['size'])
|
||||
self.size = _assert_int(kwargs['size'])
|
||||
|
||||
assert 'partition_id' in kwargs
|
||||
self.partition_id = assert_int(kwargs['partition_id'])
|
||||
self.partition_id = _assert_int(kwargs['partition_id'])
|
||||
|
||||
assert hasattr(self, 'base')
|
||||
assert hasattr(self, 'size')
|
||||
|
@ -157,7 +158,7 @@ class Irq(object):
|
|||
:param line_num: number of interrupt used by the partition
|
||||
:param signal: IRQ line identifier inside the partition
|
||||
"""
|
||||
self.line_num = assert_int(line_num)
|
||||
self.line_num = _assert_int(line_num)
|
||||
assert isinstance(signal, string_types)
|
||||
self.signal = signal
|
||||
|
||||
|
@ -353,11 +354,11 @@ class Manifest(object):
|
|||
manifest_file=manifest_file,
|
||||
psa_type=psa_type,
|
||||
name=manifest['name'],
|
||||
partition_id=assert_int(manifest['id']),
|
||||
partition_id=_assert_int(manifest['id']),
|
||||
partition_type=manifest['type'],
|
||||
priority=manifest['priority'],
|
||||
heap_size=assert_int(manifest['heap_size']),
|
||||
stack_size=assert_int(manifest['stack_size']),
|
||||
heap_size=_assert_int(manifest['heap_size']),
|
||||
stack_size=_assert_int(manifest['stack_size']),
|
||||
entry_point=manifest['entry_point'],
|
||||
source_files=source_files,
|
||||
mmio_regions=mmio_regions,
|
||||
|
@ -616,3 +617,66 @@ def manifests_discovery(root_dir=SERVICES_DIR):
|
|||
test_manifest_files.update(filter(is_test_manifest, to_add))
|
||||
|
||||
return sorted(list(service_manifest_files)), sorted(list(test_manifest_files))
|
||||
|
||||
|
||||
def parse_manifests(manifests_files, psa_type):
|
||||
region_list = []
|
||||
manifests = []
|
||||
for manifest_file in manifests_files:
|
||||
manifest_obj = Manifest.from_json(manifest_file, psa_type=psa_type)
|
||||
manifests.append(manifest_obj)
|
||||
for region in manifest_obj.mmio_regions:
|
||||
region_list.append(region)
|
||||
|
||||
return manifests, region_list
|
||||
|
||||
|
||||
def generate_source_files(
|
||||
templates,
|
||||
render_args,
|
||||
output_folder,
|
||||
extra_filters=None
|
||||
):
|
||||
"""
|
||||
Generate SPM common C code from manifests using given templates
|
||||
|
||||
:param templates: Dictionary of template and their auto-generated products
|
||||
:param render_args: Dictionary of arguments that should be passed to render
|
||||
:param output_folder: Output directory for file generation
|
||||
:param extra_filters: Dictionary of extra filters to use in the rendering
|
||||
process
|
||||
:return: Path to generated folder containing common generated files
|
||||
"""
|
||||
|
||||
rendered_files = []
|
||||
templates_dirs = list(
|
||||
set([os.path.dirname(path) for path in templates])
|
||||
)
|
||||
template_files = {os.path.basename(t): t for t in templates}
|
||||
|
||||
# Load templates for the code generation.
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(templates_dirs),
|
||||
lstrip_blocks=True,
|
||||
trim_blocks=True,
|
||||
undefined=StrictUndefined
|
||||
)
|
||||
if extra_filters:
|
||||
env.filters.update(extra_filters)
|
||||
|
||||
for tf in template_files:
|
||||
template = env.get_template(tf)
|
||||
rendered_files.append(
|
||||
(templates[template_files[tf]], template.render(**render_args)))
|
||||
rendered_file_dir = os.path.dirname(templates[template_files[tf]])
|
||||
if not os.path.exists(rendered_file_dir):
|
||||
os.makedirs(rendered_file_dir)
|
||||
|
||||
if not os.path.exists(output_folder):
|
||||
os.makedirs(output_folder)
|
||||
|
||||
for fname, data in rendered_files:
|
||||
with open(fname, 'wt') as fh:
|
||||
fh.write(data)
|
||||
|
||||
return output_folder
|
||||
|
|
|
@ -18,17 +18,13 @@ import filecmp
|
|||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import jsonschema.exceptions as jexcep
|
||||
import pytest
|
||||
import jsonschema.exceptions as jexcep
|
||||
from jinja2.defaults import DEFAULT_FILTERS
|
||||
|
||||
from .test_data import *
|
||||
from tools.psa.mbed_spm_tfm_common import *
|
||||
from tools.psa.generate_mbed_spm_partition_code import *
|
||||
from tools.psa.generate_partition_code import *
|
||||
from .test_data import *
|
||||
|
||||
# Imported again as a module for monkey-patching
|
||||
import tools.psa.generate_mbed_spm_partition_code as generate_partition_code
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
@ -369,7 +365,7 @@ def test_validate_partition_manifest(request, temp_test_data, manifests, asserti
|
|||
"""
|
||||
test_name = extract_test_name(request.node.name)
|
||||
jsons = [dump_manifest_to_json(m, '%s_%d' % (test_name, i), temp_test_data['dir']) for i, m in enumerate(manifests)]
|
||||
created_manifests = [Manifest.from_json(json) for json in jsons]
|
||||
created_manifests, _ = parse_manifests(jsons, 'MBED_SPM')
|
||||
|
||||
with pytest.raises(assertion[0], match=assertion[1]):
|
||||
validate_partition_manifests(created_manifests)
|
||||
|
@ -464,11 +460,9 @@ def test_verify_json(verify_json):
|
|||
:param verify_json: The 'verify_json' fixture.
|
||||
:return:
|
||||
"""
|
||||
manifest1 = Manifest.from_json(verify_json['files_list'][0])
|
||||
manifest2 = Manifest.from_json(verify_json['files_list'][1])
|
||||
|
||||
validate_partition_manifests([manifest1, manifest2])
|
||||
assert getattr(manifest1, verify_json['field']) == verify_json['expected']
|
||||
test_manifests, _ = parse_manifests(verify_json['files_list'], 'MBED_SPM')
|
||||
validate_partition_manifests(test_manifests)
|
||||
assert getattr(test_manifests[0], verify_json['field']) == verify_json['expected']
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
|
@ -515,13 +509,13 @@ def test_template_setup(tmpdir_factory):
|
|||
manifest_files = [
|
||||
dump_manifest_to_json(manifest, manifest['name'], test_dir) for
|
||||
manifest in manifests]
|
||||
manifest_objects = [Manifest.from_json(_file) for _file in manifest_files]
|
||||
manifest_objects, regions = parse_manifests(manifest_files, 'MBED_SPM')
|
||||
filters = {
|
||||
'basename': os.path.basename,
|
||||
'find_priority_key': find_priority_key,
|
||||
'find_permission_key': find_permission_key
|
||||
}
|
||||
template_files = [test_dir.join('_NAME_.json.tpl'),
|
||||
template_files = [test_dir.join('_NAME_data.json.tpl'),
|
||||
test_dir.join('common.json.tpl')]
|
||||
for template, _file in [(test_partition_template, template_files[0]),
|
||||
(test_common_template, template_files[1])]:
|
||||
|
@ -539,6 +533,7 @@ def test_template_setup(tmpdir_factory):
|
|||
'manifest_files': manifest_files,
|
||||
'common_files': expected_common_files,
|
||||
'manifests': manifest_objects,
|
||||
'region_list': regions,
|
||||
'filters': filters
|
||||
}
|
||||
|
||||
|
@ -558,8 +553,8 @@ def test_generate_source_files(test_template_setup):
|
|||
common_templates = {
|
||||
t: path_join(test_template_setup['dir'], os.path.basename(os.path.splitext(t)[0])) for t in common_templates
|
||||
}
|
||||
region_list = []
|
||||
|
||||
region_pair_list = list(itertools.combinations(test_template_setup['region_list'], 2))
|
||||
for manifest in test_template_setup['manifests']:
|
||||
generate_source_files(
|
||||
templates=manifest.templates_to_files(partition_templates, test_template_setup['dir'], test_template_setup['dir']),
|
||||
|
@ -570,14 +565,12 @@ def test_generate_source_files(test_template_setup):
|
|||
output_folder=test_template_setup['dir'],
|
||||
extra_filters=test_template_setup['filters']
|
||||
)
|
||||
for region in manifest.mmio_regions:
|
||||
region_list.append(region)
|
||||
|
||||
generate_source_files(
|
||||
common_templates,
|
||||
render_args={
|
||||
'partitions': test_template_setup['manifests'],
|
||||
'region_pair_list': list(itertools.combinations(region_list, 2))
|
||||
'region_pair_list': region_pair_list
|
||||
},
|
||||
output_folder=test_template_setup['dir'],
|
||||
extra_filters=test_template_setup['filters']
|
||||
|
@ -609,15 +602,11 @@ def test_generate_source_files(test_template_setup):
|
|||
with open(input_file) as fh:
|
||||
expected = json.load(fh)
|
||||
else:
|
||||
region_list = [region for manifest in
|
||||
test_template_setup['manifests'] for region in
|
||||
manifest.mmio_regions]
|
||||
expected = {
|
||||
'num_of_partitions': len(test_template_setup['manifests']),
|
||||
'partition_names': [manifest.name for manifest in
|
||||
test_template_setup['manifests']],
|
||||
'num_of_region_pairs': len(
|
||||
list(itertools.combinations(region_list, 2)))
|
||||
'num_of_region_pairs': len(region_pair_list)
|
||||
}
|
||||
assert generated == expected
|
||||
|
||||
|
@ -759,7 +748,6 @@ def test_check_circular_call_dependencies(circular_dependencies):
|
|||
:param circular_dependencies: the 'circular_dependencies' fixture
|
||||
:return:
|
||||
"""
|
||||
|
||||
objects = [Manifest.from_json(_file) for _file in circular_dependencies['files']]
|
||||
|
||||
assert check_circular_call_dependencies(objects) == circular_dependencies['result']
|
||||
objects, _ = parse_manifests(circular_dependencies['files'], 'MBED_SPM')
|
||||
assert check_circular_call_dependencies(objects) == circular_dependencies[
|
||||
'result']
|
||||
|
|
Loading…
Reference in New Issue