blob: 4548ec0349b403c7f4e5bb80d964a7786f302c0f [file] [log] [blame]
Miklos Balint470919c2018-05-22 17:51:29 +02001#-------------------------------------------------------------------------------
Jamie Foxb15418a2024-01-18 11:10:20 +00002# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
Chris Brandf1d6b6f2022-07-22 11:49:01 -07003# Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company)
4# or an affiliate of Cypress Semiconductor Corporation. All rights reserved.
Miklos Balint470919c2018-05-22 17:51:29 +02005#
6# SPDX-License-Identifier: BSD-3-Clause
7#
8#-------------------------------------------------------------------------------
9
10import os
Mate Toth-Pal36f21842018-11-08 16:12:51 +010011import io
Kevin Pengce99e5d2021-11-09 18:06:53 +080012import re
Shawn Shana9ad1e02019-08-07 15:49:48 +080013import sys
14import argparse
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -050015import logging
Ken Liu1f345b02020-05-30 21:11:05 +080016from jinja2 import Environment, BaseLoader, select_autoescape, TemplateNotFound
Miklos Balint470919c2018-05-22 17:51:29 +020017
18try:
19 import yaml
20except ImportError as e:
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -050021 logging.error (str(e) + " To install it, type:")
22 logging.error ("pip install PyYAML")
Miklos Balint470919c2018-05-22 17:51:29 +020023 exit(1)
24
Edison Ai48b2d9e2019-06-24 14:39:45 +080025donotedit_warning = \
Sherry Zhangf58f2bd2022-01-10 17:21:11 +080026 ' WARNING: This is an auto-generated file. Do not edit! '
Kevin Peng655f2392019-11-27 16:33:02 +080027
Kevin Pengce99e5d2021-11-09 18:06:53 +080028TFM_ROOT_DIR = os.path.join(sys.path[0], '..')
Kevin Peng655f2392019-11-27 16:33:02 +080029OUT_DIR = None # The root directory that files are generated to
Edison Ai48b2d9e2019-06-24 14:39:45 +080030
Sherry Zhang87e6d2e2021-12-27 14:48:59 +080031# PID[0, TFM_PID_BASE - 1] are reserved for TF-M SPM and test usages
Kevin Pengce99e5d2021-11-09 18:06:53 +080032TFM_PID_BASE = 256
33
Ruiqi Jiang71d361c2021-06-23 17:45:55 +010034# variable for checking for duplicated sid
35sid_list = []
chesun012345aa52023-04-18 17:31:53 +080036
Jason Guo8a45a682023-08-23 11:22:37 +080037# Manifest attributes defined by FF-M
38ffm_manifest_attributes = \
39 ['psa_framework_version', 'name', 'type', 'priority', 'model', 'entry_point', 'stack_size', \
40 'description', 'entry_init', 'heap_size', 'mmio_regions', 'services', 'irqs', 'dependencies',\
41 # TF-M extension of PSA attributes for mailbox client support.
42 'client_id_base', 'client_id_limit']
43
44# Manifest attributes defined by FF-M within "service" attribute
45ffm_manifest_services_attributes = \
46 ['name', 'sid', 'non_secure_clients', 'description', 'version', 'version_policy', \
47 'connection_based', 'stateless_handle', 'mm_iovec']
48
49# Manifest attributes defined by FF-M within "mmio_regions" attribute
50ffm_manifest_mmio_regions_attributes = ['name', 'base', 'size', 'permission']
51
52# Manifest attributes defined by FF-M within "irqs" attribute
53ffm_manifest_irqs_attributes = ['source', 'signal', 'name', 'handling', 'description',\
54 # TF-M extension of PSA attributes for mailbox client support.
55 'client_id_base', 'client_id_limit']
chesun012345aa52023-04-18 17:31:53 +080056
Mate Toth-Pal36f21842018-11-08 16:12:51 +010057class TemplateLoader(BaseLoader):
58 """
59 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020060
Mate Toth-Pal36f21842018-11-08 16:12:51 +010061 An instance of this class is passed to the template engine. It is
62 responsible for reading the template file
63 """
64 def __init__(self):
65 pass
Miklos Balint470919c2018-05-22 17:51:29 +020066
Mate Toth-Pal36f21842018-11-08 16:12:51 +010067 def get_source(self, environment, template):
68 """
69 This function reads the template files.
70 For detailed documentation see:
71 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
72
73 Please note that this function always return 'false' as 'uptodate'
74 value, so the output file will always be generated.
75 """
76 if not os.path.isfile(template):
77 raise TemplateNotFound(template)
78 with open(template) as f:
79 source = f.read()
80 return source, template, False
81
Kevin Pengfb1761b2022-05-12 12:11:31 +080082def parse_configurations(file_paths):
83 """
84 Parses the given config files and return a dict whose key-values are build
85 configurations and their values.
86
87 Valid configurations should be in the format of:
88 "#define VAR [...]" in a single line.
89 The value of the config is optional.
90 """
91 configurations = {}
92
93 lines = []
94 for file in file_paths:
95 with open(file, 'r') as config_file:
96 lines += config_file.readlines()
97
98 for line in lines:
99 if not line.startswith('#define'):
100 continue
101
102 line = line.rstrip('\r\n')
103 line_items = line.split(maxsplit=2)
104 if len(line_items) == 3:
105 configurations[line_items[1]] = line_items[2]
106 elif len(line_items) == 2:
107 configurations[line_items[1]] = ''
108
109 logging.debug(configurations)
110
111 return configurations
112
Kevin Peng5c3fee72022-02-16 22:25:22 +0800113def manifest_validation(manifest, pid):
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800114 """
115 This function validates FF-M compliance for partition manifest, and sets
116 default values for optional attributes.
Kevin Pengce99e5d2021-11-09 18:06:53 +0800117 The validation is skipped for TF-M specific Partitions (PID < TFM_PID_BASE).
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800118 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800119
Kevin Peng5c3fee72022-02-16 22:25:22 +0800120 service_list = manifest.get('services', [])
121 irq_list = manifest.get('irqs', [])
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800122
Kevin Peng5c3fee72022-02-16 22:25:22 +0800123 # "psa_framework_version" validation
124 if manifest['psa_framework_version'] not in [1.0, 1.1]:
125 raise Exception('Invalid psa_framework_version of {}'.format(manifest['name']))
126
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700127 # "type" validation
Kevin Peng5c3fee72022-02-16 22:25:22 +0800128 if manifest['type'] not in ['PSA-ROT', 'APPLICATION-ROT']:
129 raise Exception('Invalid type of {}'.format(manifest['name']))
130
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700131 # "priority" validation
132 if manifest['priority'] not in ['HIGH', 'NORMAL', 'LOW']:
133 raise Exception('Invalid priority of {}'.format(manifest['name']))
134
Chris Brandc422cdd2022-07-21 13:32:47 -0700135 if 'ns_agent' not in manifest:
136 manifest['ns_agent'] = False
137
Kevin Peng5c3fee72022-02-16 22:25:22 +0800138 # Every PSA Partition must have at least either a secure service or an IRQ
Kevin Pengce99e5d2021-11-09 18:06:53 +0800139 if (pid == None or pid >= TFM_PID_BASE) \
Kevin Peng8849b6a2021-11-09 14:17:35 +0800140 and len(service_list) == 0 and len(irq_list) == 0:
141 raise Exception('{} must declare at least either a secure service or an IRQ!'
Kevin Peng5c3fee72022-02-16 22:25:22 +0800142 .format(manifest['name']))
143
144 if manifest['psa_framework_version'] == 1.0:
145 # For 1.0 Partition, the model is IPC
146 manifest['model'] = 'IPC'
147
148 # "model" validation:
149 model = manifest.get('model', None)
150 if model == None:
151 raise Exception('{} is missing the "model" attribute'.format(manifest['name']))
152
153 # Assign a unified 'entry' for templates
154 if model == 'IPC':
155 # entry_point is mandatory for IPC Partitions
156 if 'entry_point' not in manifest.keys():
157 raise Exception('{} is missing the "entry_point" attribute'.format(manifest['name']))
158 manifest['entry'] = manifest['entry_point']
159 elif model == 'SFN':
160 if 'entry_init' in manifest.keys():
161 manifest['entry'] = manifest['entry_init']
162 else:
163 manifest['entry'] = 0
164 else:
165 raise Exception('Invalid "model" of {}'.format(manifest['name']))
Kevin Peng8849b6a2021-11-09 14:17:35 +0800166
167 # Service FF-M manifest validation
168 for service in service_list:
Kevin Peng5c3fee72022-02-16 22:25:22 +0800169 if manifest['psa_framework_version'] == 1.0:
170 service['connection_based'] = True
171 elif 'connection_based' not in service:
172 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
173
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800174 if 'version' not in service.keys():
175 service['version'] = 1
176 if 'version_policy' not in service.keys():
Kevin Peng5bc82d22021-10-19 11:18:40 +0800177 service['version_policy'] = 'STRICT'
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800178
Kevin Peng5bc82d22021-10-19 11:18:40 +0800179 # SID duplication check
180 if service['sid'] in sid_list:
181 raise Exception('Service ID: {} has duplications!'.format(service['sid']))
182 else:
183 sid_list.append(service['sid'])
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100184
Kevin Peng5c3fee72022-02-16 22:25:22 +0800185 return manifest
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800186
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800187def check_circular_dependency(partitions, service_partition_map):
188 """
189 This function detects if there is any circular partition dependency chain.
190 If a circular dependency is detected, the script exits with error.
191
192 Inputs:
193 - partitions: dict of partition manifests
194 - service_partition_map: map between services and their owner Partitions
195 """
196
197 dependency_table = {}
198 for partition in partitions:
199 manifest = partition['manifest']
200 dependencies = manifest['dependencies'].copy() \
201 if 'dependencies' in manifest else []
202 dependencies += manifest['weak_dependencies'].copy() \
203 if 'weak_dependencies' in manifest else []
204 dependency_table[manifest['name']] = {
205 'dependencies': [service_partition_map[dependency]
206 for dependency in dependencies
207 if dependency in service_partition_map],
208 'validated': False
209 }
210
211 for partition in dependency_table.keys():
212 validate_dependency_chain(partition, dependency_table, [])
213
214def validate_dependency_chain(partition,
215 dependency_table,
216 dependency_chain):
217 """
218 Recursively validate if the given partition and its dependencies
219 have a circular dependency with the given dependency_chain.
220 Exit with error code once any circular is detected.
221
222 Inputs:
223 - partition: next partition to be checked
224 - dependency_table: dict of partitions and their dependencies
225 - dependency_chain: list of dependencies in current chain
226 """
227
228 dependency_chain.append(partition)
229 if partition in dependency_chain[:-1]:
230 logging.error(
231 'Circular dependency exists in chain: {}'.format(
232 ', '.join(dependency_chain)))
233 exit(1)
234 for dependency in dependency_table[partition]['dependencies']:
235 if dependency_table[dependency]['validated']:
236 continue
237 validate_dependency_chain(dependency, dependency_table, dependency_chain)
238 dependency_table[partition]['validated'] = True
239
chesun012345aa52023-04-18 17:31:53 +0800240def manifest_attribute_check(manifest, manifest_item):
241 """
Jason Guo8a45a682023-08-23 11:22:37 +0800242 Check whether there is any invalid attribute in manifests.
243 Non-FF-M compliant attributes are allowed provided that they are explicitly registered in
244 manifest lists. And they are only allowed in the top-level attributes.
245
246 Note:
247 This method only checks the existence of invalid attributes.
248 It does not validate the values.
249 Those are done in manifest_validation().
250
251 The main purposes of this method are:
252 1. Make sure developers are aware of using Non-FF-M attributes.
253 2. Detect typos on optional attributes.
chesun012345aa52023-04-18 17:31:53 +0800254
255 Inputs:
256 - manifest: next manifest to be checked
257 - manifest_item: the manifest items in manifest lists
258 """
Jason Guo8a45a682023-08-23 11:22:37 +0800259
260 # Top-level attributes check
chesun012345aa52023-04-18 17:31:53 +0800261 allowed_attributes = ffm_manifest_attributes + manifest_item.get('non_ffm_attributes', [])
262 for keyword in manifest.keys():
263 if keyword not in allowed_attributes:
Jason Guo8a45a682023-08-23 11:22:37 +0800264 logging.error('The Non-FFM attribute "{}" is used by "{}" without registration.'
265 .format(keyword, manifest['name']))
chesun012345aa52023-04-18 17:31:53 +0800266 exit(1)
267
Jason Guo8a45a682023-08-23 11:22:37 +0800268 # "services" attribute check
269 services = manifest.get('services', [])
270 for srv in services:
271 for attr in srv.keys():
272 if attr not in ffm_manifest_services_attributes:
273 logging.error('Invalid attribute "{}" used by "{}" in "services".'
274 .format(attr, manifest['name']))
275 exit(1)
276
277 # "mmio_regions" attribute check
278 mmio_regions = manifest.get('mmio_regions', [])
279 for reg in mmio_regions:
280 for attr in reg.keys():
281 if attr not in ffm_manifest_mmio_regions_attributes:
282 logging.error('Invalid attribute "{}" used by "{}" in "mmio_regions".'
283 .format(attr, manifest['name']))
284 exit(1)
285
286 # "irqs" attribute check
287 irqs = manifest.get('irqs', [])
288 for irq in irqs:
289 for attr in irq.keys():
290 if attr not in ffm_manifest_irqs_attributes:
291 logging.error('Invalid attribute "{}" used by "{}" in "irqs".'
292 .format(attr, manifest['name']))
293 exit(1)
294
Kevin Pengfb1761b2022-05-12 12:11:31 +0800295def process_partition_manifests(manifest_lists, configs):
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100296 """
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800297 Parse the input manifest lists, check if manifest settings are valid,
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700298 generate the data base for generated files
Kevin Peng655f2392019-11-27 16:33:02 +0800299 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100300
301 Parameters
302 ----------
Kevin Peng65064c52021-10-27 17:12:17 +0800303 manifest_lists:
Kevin Pengfb1761b2022-05-12 12:11:31 +0800304 A list of Secure Partition manifest lists
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100305
306 Returns
307 -------
Kevin Peng5bc82d22021-10-19 11:18:40 +0800308 The manifest data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +0800309 """
Kevin Peng655f2392019-11-27 16:33:02 +0800310
Kevin Peng5bc82d22021-10-19 11:18:40 +0800311 context = {}
312
Ken Liu861b0782021-05-22 13:15:08 +0800313 partition_list = []
Kevin Peng65064c52021-10-27 17:12:17 +0800314 all_manifests = []
Kevin Peng56b0ea62021-10-18 11:32:57 +0800315 pid_list = []
316 no_pid_manifest_idx = []
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800317 service_partition_map = {}
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800318 partition_statistics = {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800319 'connection_based_srv_num': 0,
Kevin Peng47c26ec2022-03-11 11:49:52 +0800320 'ipc_partitions': [],
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800321 'mmio_region_num': 0,
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800322 'flih_num': 0,
323 'slih_num': 0
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800324 }
Kevin Peng9f1a7542022-02-07 16:32:27 +0800325 config_impl = {
326 'CONFIG_TFM_SPM_BACKEND_SFN' : '0',
327 'CONFIG_TFM_SPM_BACKEND_IPC' : '0',
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800328 'CONFIG_TFM_CONNECTION_BASED_SERVICE_API' : '0',
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800329 'CONFIG_TFM_MMIO_REGION_ENABLE' : '0',
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800330 'CONFIG_TFM_FLIH_API' : '0',
331 'CONFIG_TFM_SLIH_API' : '0'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800332 }
chesun0122abf0a2023-10-17 13:42:16 +0800333 priority_map = {
334 'LOWEST' : '00',
335 'LOW' : '01',
336 'NORMAL' : '02',
337 'HIGH' : '03',
338 'HIGHEST' : '04'
339 }
Kevin Peng655f2392019-11-27 16:33:02 +0800340
Kevin Pengfb1761b2022-05-12 12:11:31 +0800341 isolation_level = int(configs['TFM_ISOLATION_LEVEL'], base = 10)
342 backend = configs['CONFIG_TFM_SPM_BACKEND']
343
Kevin Peng65064c52021-10-27 17:12:17 +0800344 # Get all the manifests information as a dictionary
345 for i, item in enumerate(manifest_lists):
Kevin Pengfb1761b2022-05-12 12:11:31 +0800346 if not os.path.isfile(item):
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500347 logging.error('Manifest list item [{}] must be a file'.format(i))
Kevin Peng65064c52021-10-27 17:12:17 +0800348 exit(1)
Kevin Peng655f2392019-11-27 16:33:02 +0800349
Kevin Peng65064c52021-10-27 17:12:17 +0800350 # The manifest list file generated by configure_file()
351 with open(item) as manifest_list_yaml_file:
352 manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
353 for dict in manifest_dic:
Raef Coles052e8712023-11-02 15:29:40 +0000354 # Replace environment variables in the manifest path.
355 expanded_path = os.path.expandvars(dict['manifest']).replace('\\', '/')
356
357 # If the manifest exists relative to the manifest list, then use
358 # that. Else, either interpret it as an absolute path or one
359 # relative to the current working directory
360 path_relative_to_manifest_list = os.path.join(os.path.dirname(item), # path of manifest list
361 expanded_path)
362 if os.path.isfile(path_relative_to_manifest_list):
363 manifest_path = path_relative_to_manifest_list
364 else:
365 manifest_path = expanded_path
Kevin Pengfb1761b2022-05-12 12:11:31 +0800366 dict['manifest'] = manifest_path
Kevin Peng65064c52021-10-27 17:12:17 +0800367 all_manifests.append(dict)
368
Anton Komlev52920712024-05-16 13:45:46 +0100369 logging.info("----------- Secure Partitions ------------------------")
Chris Brand4b69fcf2022-06-06 09:37:49 -0700370
Kevin Peng65064c52021-10-27 17:12:17 +0800371 # Parse the manifests
372 for i, manifest_item in enumerate(all_manifests):
Kevin Pengfb1761b2022-05-12 12:11:31 +0800373 valid_enabled_conditions = ['1', 'on', 'true', 'enabled']
374 valid_disabled_conditions = ['0', 'off', 'false', 'disabled', '']
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800375 is_enabled = ''
376
377 if 'conditional' in manifest_item.keys():
Kevin Pengfb1761b2022-05-12 12:11:31 +0800378 if manifest_item['conditional'] not in configs.keys():
379 logging.error('Configuration "{}" is not defined!'.format(manifest_item['conditional']))
380 exit(1)
381 is_enabled = configs[manifest_item['conditional']].lower()
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800382 else:
Kevin Pengfb1761b2022-05-12 12:11:31 +0800383 # Partitions without 'conditional' is always on
384 is_enabled = '1'
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800385
386 if is_enabled in valid_disabled_conditions:
BohdanHunko6cea95d2022-08-16 15:33:51 +0300387 logging.info(" {:40s} OFF".format(manifest_item['description']))
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800388 continue
Chris Brand4b69fcf2022-06-06 09:37:49 -0700389 elif is_enabled in valid_enabled_conditions:
BohdanHunko6cea95d2022-08-16 15:33:51 +0300390 logging.info(" {:40s} ON".format(manifest_item['description']))
Chris Brand4b69fcf2022-06-06 09:37:49 -0700391 else:
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800392 raise Exception('Invalid "conditional" attribute: "{}" for {}. '
393 'Please set to one of {} or {}, case-insensitive.'\
394 .format(manifest_item['conditional'],
BohdanHunko6cea95d2022-08-16 15:33:51 +0300395 manifest_item['description'],
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800396 valid_enabled_conditions, valid_disabled_conditions))
397
Xinyu Zhangc46ee1f2021-04-01 10:10:43 +0800398 # Check if partition ID is manually set
399 if 'pid' not in manifest_item.keys():
400 no_pid_manifest_idx.append(i)
Kevin Peng8849b6a2021-11-09 14:17:35 +0800401 pid = None
Kevin Peng56b0ea62021-10-18 11:32:57 +0800402 else:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800403 pid = manifest_item['pid']
404
405 # Check if partition ID is duplicated
406 if pid in pid_list:
Antonio de Angelisbaa27642022-05-25 11:07:12 +0100407 raise Exception('PID No. {} has already been used!'.format(pid))
Kevin Peng8849b6a2021-11-09 14:17:35 +0800408 else:
409 pid_list.append(pid)
Xinyu Zhang19504a52021-03-31 16:26:20 +0800410
Kevin Pengfb1761b2022-05-12 12:11:31 +0800411 manifest_path = manifest_item['manifest']
Kevin Peng5bc82d22021-10-19 11:18:40 +0800412 with open(manifest_path) as manifest_file:
Kevin Pengec0e5ce2022-02-17 13:48:51 +0800413 manifest = yaml.safe_load(manifest_file)
chesun0122abf0a2023-10-17 13:42:16 +0800414 # Check manifest attribute validity
chesun012345aa52023-04-18 17:31:53 +0800415 manifest_attribute_check(manifest, manifest_item)
416
Kevin Pengec0e5ce2022-02-17 13:48:51 +0800417 if manifest.get('model', None) == 'dual':
418 # If a Partition supports both models, it can set the "model" to "backend".
419 # The actual model used follows the backend being used.
420 manifest['model'] = backend
421 manifest = manifest_validation(manifest, pid)
Kevin Peng655f2392019-11-27 16:33:02 +0800422
chesun0122abf0a2023-10-17 13:42:16 +0800423 # Priority mapping
424 numbered_priority = priority_map[manifest['priority']]
425
Jamie Foxb15418a2024-01-18 11:10:20 +0000426 if (pid == None or pid >= TFM_PID_BASE) and not manifest['ns_agent']:
427 # Count the number of IPC/SFN partitions (excluding TF-M internal
428 # and agent partitions)
Kevin Peng47c26ec2022-03-11 11:49:52 +0800429 if manifest['model'] == 'IPC':
430 partition_statistics['ipc_partitions'].append(manifest['name'])
Mingyang Suneab7eae2021-09-30 13:06:52 +0800431
Kevin Peng5c3fee72022-02-16 22:25:22 +0800432 # Set initial value to -1 to make (srv_idx + 1) reflect the correct
433 # number (0) when there are no services.
434 srv_idx = -1
435 for srv_idx, service in enumerate(manifest.get('services', [])):
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800436 service_partition_map[service['name']] = manifest['name']
Kevin Peng5c3fee72022-02-16 22:25:22 +0800437 if manifest['model'] == 'IPC':
438 # Assign signal value, the first 4 bits are reserved by FF-M
439 service['signal_value'] = (1 << (srv_idx + 4))
440 else:
441 # Signals of SFN Partitions are SPM internal only, does not
442 # need to reserve 4 bits.
443 service['signal_value'] = (1 << srv_idx)
444 if service['connection_based']:
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800445 partition_statistics['connection_based_srv_num'] += 1
Kevin Peng5c3fee72022-02-16 22:25:22 +0800446 logging.debug('{} has {} services'.format(manifest['name'], srv_idx +1))
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800447
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800448 # Calculate the number of mmio region
449 mmio_region_list = manifest.get('mmio_regions', [])
450 partition_statistics['mmio_region_num'] += len(mmio_region_list)
451
Kevin Peng5c3fee72022-02-16 22:25:22 +0800452 # Set initial value to -1 to make (irq + 1) reflect the correct
453 # number (0) when there are no irqs.
454 irq_idx = -1
455 for irq_idx, irq in enumerate(manifest.get('irqs', [])):
456 # Assign signal value, from the most significant bit
457 irq['signal_value'] = (1 << (31 - irq_idx))
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800458 if irq.get('handling', None) == 'FLIH':
459 partition_statistics['flih_num'] += 1
460 else:
461 partition_statistics['slih_num'] += 1
Kevin Peng5c3fee72022-02-16 22:25:22 +0800462 logging.debug('{} has {} IRQS'.format(manifest['name'], irq_idx +1))
463
464 if ((srv_idx + 1) + (irq_idx + 1)) > 28:
465 raise Exception('Total number of Services and IRQs of {} exceeds the limit (28)'
466 .format(manifest['name']))
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800467
Kevin Peng65064c52021-10-27 17:12:17 +0800468 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800469
Kevin Peng4fade072021-10-26 17:57:50 +0800470 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800471 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800472 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800473 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800474
Kevin Peng5bc82d22021-10-19 11:18:40 +0800475 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
476 '{}.h'.format(manifest_out_basename))\
477 .replace('\\', '/')
478 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
479 'intermedia_{}.c'.format(manifest_out_basename))\
480 .replace('\\', '/')
481 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
482 'load_info_{}.c'.format(manifest_out_basename))\
483 .replace('\\', '/')
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800484 output_dir = os.path.join(OUT_DIR, output_path).replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800485
Kevin Peng5bc82d22021-10-19 11:18:40 +0800486 partition_list.append({'manifest': manifest, 'attr': manifest_item,
487 'manifest_out_basename': manifest_out_basename,
488 'header_file': manifest_head_file,
489 'intermedia_file': intermedia_file,
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800490 'loadinfo_file': load_info_file,
chesun0122abf0a2023-10-17 13:42:16 +0800491 'output_dir': output_dir,
492 'numbered_priority': numbered_priority})
Ken Liu861b0782021-05-22 13:15:08 +0800493
Anton Komlev52920712024-05-16 13:45:46 +0100494 logging.info("------------------------------------------------------")
Chris Brand4b69fcf2022-06-06 09:37:49 -0700495
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800496 check_circular_dependency(partition_list, service_partition_map)
497
Kevin Peng56b0ea62021-10-18 11:32:57 +0800498 # Automatically assign PIDs for partitions without 'pid' attribute
Kevin Pengce99e5d2021-11-09 18:06:53 +0800499 pid = max(pid_list, default = TFM_PID_BASE - 1)
Kevin Peng56b0ea62021-10-18 11:32:57 +0800500 for idx in no_pid_manifest_idx:
Kevin Pengc424eec2021-06-25 17:26:11 +0800501 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800502 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800503 pid_list.append(pid)
504
Kevin Peng9f1a7542022-02-07 16:32:27 +0800505 # Set up configurations
Kevin Peng76c0c162022-02-09 22:49:06 +0800506 if backend == 'SFN':
Kevin Peng47c26ec2022-03-11 11:49:52 +0800507 if len(partition_statistics['ipc_partitions']) > 0:
508 logging.error('SFN backend does not support IPC Partitions:')
509 logging.error(partition_statistics['ipc_partitions'])
Kevin Peng9f1a7542022-02-07 16:32:27 +0800510 exit(1)
Kevin Peng76c0c162022-02-09 22:49:06 +0800511
512 if isolation_level > 1:
513 logging.error('SFN backend does not support high isolation levels.')
514 exit(1)
515
Kevin Peng9f1a7542022-02-07 16:32:27 +0800516 config_impl['CONFIG_TFM_SPM_BACKEND_SFN'] = '1'
Kevin Peng76c0c162022-02-09 22:49:06 +0800517 elif backend == 'IPC':
Kevin Peng9f1a7542022-02-07 16:32:27 +0800518 config_impl['CONFIG_TFM_SPM_BACKEND_IPC'] = '1'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800519
520 if partition_statistics['connection_based_srv_num'] > 0:
521 config_impl['CONFIG_TFM_CONNECTION_BASED_SERVICE_API'] = 1
522
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800523 if partition_statistics['mmio_region_num'] > 0:
524 config_impl['CONFIG_TFM_MMIO_REGION_ENABLE'] = 1
525
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800526 if partition_statistics['flih_num'] > 0:
527 config_impl['CONFIG_TFM_FLIH_API'] = 1
Joakim Anderssoneec5cd32022-06-10 12:02:07 +0200528 if partition_statistics['slih_num'] > 0:
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800529 config_impl['CONFIG_TFM_SLIH_API'] = 1
530
Kevin Peng5bc82d22021-10-19 11:18:40 +0800531 context['partitions'] = partition_list
Kevin Peng9f1a7542022-02-07 16:32:27 +0800532 context['config_impl'] = config_impl
Kevin Pengce99e5d2021-11-09 18:06:53 +0800533 context['stateless_services'] = process_stateless_services(partition_list)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100534
Kevin Peng5bc82d22021-10-19 11:18:40 +0800535 return context
Ken Liu861b0782021-05-22 13:15:08 +0800536
537def gen_per_partition_files(context):
538 """
539 Generate per-partition files
540
541 Parameters
542 ----------
543 context:
544 context contains partition infos
545 """
546
Kevin Peng5bc82d22021-10-19 11:18:40 +0800547 partition_context = {}
Sherry Zhangf58f2bd2022-01-10 17:21:11 +0800548 partition_context['utilities'] = context['utilities']
Sherry Zhangf865c4e2022-03-23 13:53:38 +0800549 partition_context['config_impl'] = context['config_impl']
Ken Liu861b0782021-05-22 13:15:08 +0800550
Kevin Peng5bc82d22021-10-19 11:18:40 +0800551 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
552 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
553 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800554
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500555 logging.info ("Start to generate partition files:")
Ken Liu861b0782021-05-22 13:15:08 +0800556
557 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800558 partition_context['manifest'] = one_partition['manifest']
559 partition_context['attr'] = one_partition['attr']
560 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
chesun0122abf0a2023-10-17 13:42:16 +0800561 partition_context['numbered_priority'] = one_partition['numbered_priority']
Ken Liu861b0782021-05-22 13:15:08 +0800562
BohdanHunko6cea95d2022-08-16 15:33:51 +0300563 logging.info ('Generating {} in {}'.format(one_partition['attr']['description'],
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800564 one_partition['output_dir']))
Ken Liu861b0782021-05-22 13:15:08 +0800565 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800566 if not os.path.exists(outfile_path):
567 os.makedirs(outfile_path)
568
Kevin Peng5bc82d22021-10-19 11:18:40 +0800569 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
570 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800571 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800572
Ken Liu861b0782021-05-22 13:15:08 +0800573 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800574 if not os.path.exists(intermediafile_path):
575 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800576 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
577 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800578 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800579
Ken Liu861b0782021-05-22 13:15:08 +0800580 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800581 if not os.path.exists(infofile_path):
582 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800583 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
584 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800585 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800586
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500587 logging.info ("Per-partition files done:")
Mingyang Sunf6a78572021-04-02 16:51:05 +0800588
Ken Liu861b0782021-05-22 13:15:08 +0800589def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800590 """
591 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800592
593 Parameters
594 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100595 gen_file_lists:
596 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800597 """
Kevin Peng655f2392019-11-27 16:33:02 +0800598 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800599
Raef Colesf42f0882020-07-10 10:01:58 +0100600 for f in gen_file_lists:
601 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800602 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800603 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800604
Kevin Peng655f2392019-11-27 16:33:02 +0800605 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000606 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800607 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000608 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800609 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800610
Kevin Peng4fade072021-10-26 17:57:50 +0800611 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800612
Ken Liu861b0782021-05-22 13:15:08 +0800613 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800614 if not os.path.exists(outfile_path):
615 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800616
Kevin Peng655f2392019-11-27 16:33:02 +0800617 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800618
Kevin Peng5bc82d22021-10-19 11:18:40 +0800619 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800620 outfile.write(template.render(context))
621 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800622
Kevin Pengce99e5d2021-11-09 18:06:53 +0800623def process_stateless_services(partitions):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800624 """
625 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800626 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800627 Valid stateless handle in service will be converted to an index. If the
628 stateless handle is set as "auto", or not set, framework will allocate a
629 valid index for the service.
630 Framework puts each service into a reordered stateless service list at
631 position of "index". Other unused positions are left None.
Ken Liu50948382022-10-27 12:45:53 +0800632
633 Keep the variable names start with upper case 'STATIC_HANDLE_' the same
634 as the preprocessors in C sources. This could easier the upcomping
635 modification when developer searches these definitions for modification.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800636 """
Kevin Pengce99e5d2021-11-09 18:06:53 +0800637
Kevin Pengc05319d2021-04-22 22:59:35 +0800638 collected_stateless_services = []
Ken Liu50948382022-10-27 12:45:53 +0800639 STATIC_HANDLE_NUM_LIMIT = 32
Mingyang Suna1ca6112021-01-11 11:34:59 +0800640
641 # Collect all stateless services first.
642 for partition in partitions:
643 # Skip the FF-M 1.0 partitions
644 if partition['manifest']['psa_framework_version'] < 1.1:
645 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800646
647 service_list = partition['manifest'].get('services', [])
648
649 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800650 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800651 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800652
Kevin Pengc05319d2021-04-22 22:59:35 +0800653 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800654 return []
655
Ken Liu50948382022-10-27 12:45:53 +0800656 if len(collected_stateless_services) > STATIC_HANDLE_NUM_LIMIT:
657 raise Exception('Stateless service numbers range exceed {number}.'.format(number=STATIC_HANDLE_NUM_LIMIT))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800658
659 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800660 Allocate an empty stateless service list to store services.
661 Use "handle - 1" as the index for service, since handle value starts from
662 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800663 """
Ken Liu50948382022-10-27 12:45:53 +0800664 reordered_stateless_services = [None] * STATIC_HANDLE_NUM_LIMIT
Kevin Pengc05319d2021-04-22 22:59:35 +0800665 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800666
Kevin Pengc05319d2021-04-22 22:59:35 +0800667 for service in collected_stateless_services:
668 # If not set, it is "auto" by default
669 if 'stateless_handle' not in service:
670 auto_alloc_services.append(service)
671 continue
672
Mingyang Sun4ecea992021-03-30 17:56:26 +0800673 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800674
Mingyang Sun4ecea992021-03-30 17:56:26 +0800675 # Fill in service list with specified stateless handle, otherwise skip
676 if isinstance(service_handle, int):
Ken Liu50948382022-10-27 12:45:53 +0800677 if service_handle < 1 or service_handle > STATIC_HANDLE_NUM_LIMIT:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800678 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800679 # Convert handle index to reordered service list index
680 service_handle = service_handle - 1
681
682 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800683 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800684 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800685 elif service_handle == 'auto':
686 auto_alloc_services.append(service)
687 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800688 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800689
Xinyu Zhangb2d4ed42023-02-14 11:43:16 +0800690 STATIC_HANDLE_IDX_BIT_WIDTH = 5
Kevin Pengce99e5d2021-11-09 18:06:53 +0800691 STATIC_HANDLE_IDX_MASK = (1 << STATIC_HANDLE_IDX_BIT_WIDTH) - 1
Ken Liu50948382022-10-27 12:45:53 +0800692 STATIC_HANDLE_INDICATOR_OFFSET = 30
693 STATIC_HANDLE_VER_OFFSET = 8
694 STATIC_HANDLE_VER_BIT_WIDTH = 8
Kevin Pengce99e5d2021-11-09 18:06:53 +0800695 STATIC_HANDLE_VER_MASK = (1 << STATIC_HANDLE_VER_BIT_WIDTH) - 1
696
Mingyang Sun4ecea992021-03-30 17:56:26 +0800697 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu50948382022-10-27 12:45:53 +0800698 for i in range(0, STATIC_HANDLE_NUM_LIMIT):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800699 service = reordered_stateless_services[i]
700
Kevin Pengc05319d2021-04-22 22:59:35 +0800701 if service == None and len(auto_alloc_services) > 0:
702 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800703
Mingyang Sun453ad402021-03-17 17:58:33 +0800704 """
705 Encode stateless flag and version into stateless handle
Mingyang Sun453ad402021-03-17 17:58:33 +0800706 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800707 stateless_handle_value = 0
708 if service != None:
Kevin Pengce99e5d2021-11-09 18:06:53 +0800709 stateless_index = (i & STATIC_HANDLE_IDX_MASK)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800710 stateless_handle_value |= stateless_index
Kevin Pengce99e5d2021-11-09 18:06:53 +0800711 stateless_handle_value |= (1 << STATIC_HANDLE_INDICATOR_OFFSET)
712 stateless_version = (service['version'] & STATIC_HANDLE_VER_MASK) << STATIC_HANDLE_VER_OFFSET
Mingyang Sun453ad402021-03-17 17:58:33 +0800713 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800714 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800715 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800716
Mingyang Sun4ecea992021-03-30 17:56:26 +0800717 reordered_stateless_services[i] = service
718
719 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800720
Kevin Peng655f2392019-11-27 16:33:02 +0800721def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000722 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
Juha Ylinenbc261272024-06-19 13:00:00 +0300723 epilog='Note that environment variables in template files will be replaced with their values',
724 allow_abbrev=False)
Raef Coles558487a2020-10-29 13:09:44 +0000725
Kevin Peng655f2392019-11-27 16:33:02 +0800726 parser.add_argument('-o', '--outdir'
727 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800728 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800729 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800730 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800731
Kevin Peng5bc82d22021-10-19 11:18:40 +0800732 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100733 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800734 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100735 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800736 , metavar='manifest list'
737 , help='A list of Secure Partition manifest lists and their original paths.\n\
738 The manifest lists might be processed by CMake and\n\
739 the path might be different to the original one\n\
740 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800741
742 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100743 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800744 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100745 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800746 , metavar='file-list'
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700747 , help='These files describe the file list to generate')
Kevin Peng9f1a7542022-02-07 16:32:27 +0800748
Kevin Pengfb1761b2022-05-12 12:11:31 +0800749 parser.add_argument('-c', '--config-files'
750 , nargs='+'
751 , dest='config_files'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800752 , required=True
Kevin Pengfb1761b2022-05-12 12:11:31 +0800753 , metavar='config-files'
754 , help='A header file contains build configurations')
Kevin Peng9f1a7542022-02-07 16:32:27 +0800755
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500756 parser.add_argument('-q', '--quiet'
757 , dest='quiet'
758 , required=False
759 , default=False
760 , action='store_true'
761 , help='Reduce log messages')
Kevin Peng655f2392019-11-27 16:33:02 +0800762
763 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800764
Kevin Peng655f2392019-11-27 16:33:02 +0800765 return args
766
767ENV = Environment(
768 loader = TemplateLoader(),
769 autoescape = select_autoescape(['html', 'xml']),
770 lstrip_blocks = True,
771 trim_blocks = True,
772 keep_trailing_newline = True
773 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100774
Miklos Balint470919c2018-05-22 17:51:29 +0200775def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100776 """
777 The entry point of the script.
778
779 Generates the output files based on the templates and the manifests.
780 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800781
Kevin Peng655f2392019-11-27 16:33:02 +0800782 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800783
Kevin Peng655f2392019-11-27 16:33:02 +0800784 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800785
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500786 logging.basicConfig(format='%(message)s'
787 , level=logging.WARNING if args.quiet else logging.INFO)
788
Kevin Peng5bc82d22021-10-19 11:18:40 +0800789 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800790
Kevin Peng5bc82d22021-10-19 11:18:40 +0800791 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
792 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800793
Shawn Shana9ad1e02019-08-07 15:49:48 +0800794 """
Kevin Peng655f2392019-11-27 16:33:02 +0800795 Relative path to TF-M root folder is supported in the manifests
796 and default value of manifest list and generated file list are relative to TF-M root folder as well,
797 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800798 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800799 The script is located in <TF-M root folder>/tools, so sys.path[0]<location of the script>/.. is TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800800 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800801 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800802
Kevin Peng76c0c162022-02-09 22:49:06 +0800803 context = process_partition_manifests(manifest_lists,
Kevin Pengfb1761b2022-05-12 12:11:31 +0800804 parse_configurations(args.config_files))
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100805
Edison Ai6e3f2a32019-06-11 15:29:05 +0800806 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800807 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200808
Kevin Peng655f2392019-11-27 16:33:02 +0800809 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800810
Ken Liu861b0782021-05-22 13:15:08 +0800811 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800812 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200813
Kevin Peng5bc82d22021-10-19 11:18:40 +0800814if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200815 main()