blob: 97c8e0c3e86dc4c712fb48df039a094cc256565f [file] [log] [blame]
Miklos Balint470919c2018-05-22 17:51:29 +02001#-------------------------------------------------------------------------------
Xinyu Zhang90f08dc2022-01-12 15:55:17 +08002# Copyright (c) 2018-2022, 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
37# Summary of manifest attributes defined by FFM for use in the Secure Partition manifest file.
38ffm_manifest_attributes = ['psa_framework_version', 'name', 'type', 'priority', 'model', 'entry_point', \
39'stack_size', 'description', 'entry_init', 'heap_size', 'mmio_regions', 'services', 'irqs', 'dependencies']
40
Mate Toth-Pal36f21842018-11-08 16:12:51 +010041class TemplateLoader(BaseLoader):
42 """
43 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020044
Mate Toth-Pal36f21842018-11-08 16:12:51 +010045 An instance of this class is passed to the template engine. It is
46 responsible for reading the template file
47 """
48 def __init__(self):
49 pass
Miklos Balint470919c2018-05-22 17:51:29 +020050
Mate Toth-Pal36f21842018-11-08 16:12:51 +010051 def get_source(self, environment, template):
52 """
53 This function reads the template files.
54 For detailed documentation see:
55 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
56
57 Please note that this function always return 'false' as 'uptodate'
58 value, so the output file will always be generated.
59 """
60 if not os.path.isfile(template):
61 raise TemplateNotFound(template)
62 with open(template) as f:
63 source = f.read()
64 return source, template, False
65
Kevin Pengfb1761b2022-05-12 12:11:31 +080066def parse_configurations(file_paths):
67 """
68 Parses the given config files and return a dict whose key-values are build
69 configurations and their values.
70
71 Valid configurations should be in the format of:
72 "#define VAR [...]" in a single line.
73 The value of the config is optional.
74 """
75 configurations = {}
76
77 lines = []
78 for file in file_paths:
79 with open(file, 'r') as config_file:
80 lines += config_file.readlines()
81
82 for line in lines:
83 if not line.startswith('#define'):
84 continue
85
86 line = line.rstrip('\r\n')
87 line_items = line.split(maxsplit=2)
88 if len(line_items) == 3:
89 configurations[line_items[1]] = line_items[2]
90 elif len(line_items) == 2:
91 configurations[line_items[1]] = ''
92
93 logging.debug(configurations)
94
95 return configurations
96
Kevin Peng5c3fee72022-02-16 22:25:22 +080097def manifest_validation(manifest, pid):
Mingyang Sun294ce2e2021-06-11 11:58:24 +080098 """
99 This function validates FF-M compliance for partition manifest, and sets
100 default values for optional attributes.
Kevin Pengce99e5d2021-11-09 18:06:53 +0800101 The validation is skipped for TF-M specific Partitions (PID < TFM_PID_BASE).
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800102 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800103
Kevin Peng5c3fee72022-02-16 22:25:22 +0800104 service_list = manifest.get('services', [])
105 irq_list = manifest.get('irqs', [])
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800106
Kevin Peng5c3fee72022-02-16 22:25:22 +0800107 # "psa_framework_version" validation
108 if manifest['psa_framework_version'] not in [1.0, 1.1]:
109 raise Exception('Invalid psa_framework_version of {}'.format(manifest['name']))
110
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700111 # "type" validation
Kevin Peng5c3fee72022-02-16 22:25:22 +0800112 if manifest['type'] not in ['PSA-ROT', 'APPLICATION-ROT']:
113 raise Exception('Invalid type of {}'.format(manifest['name']))
114
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700115 # "priority" validation
116 if manifest['priority'] not in ['HIGH', 'NORMAL', 'LOW']:
117 raise Exception('Invalid priority of {}'.format(manifest['name']))
118
Chris Brandc422cdd2022-07-21 13:32:47 -0700119 if 'ns_agent' not in manifest:
120 manifest['ns_agent'] = False
121
Kevin Peng5c3fee72022-02-16 22:25:22 +0800122 # Every PSA Partition must have at least either a secure service or an IRQ
Kevin Pengce99e5d2021-11-09 18:06:53 +0800123 if (pid == None or pid >= TFM_PID_BASE) \
Kevin Peng8849b6a2021-11-09 14:17:35 +0800124 and len(service_list) == 0 and len(irq_list) == 0:
125 raise Exception('{} must declare at least either a secure service or an IRQ!'
Kevin Peng5c3fee72022-02-16 22:25:22 +0800126 .format(manifest['name']))
127
128 if manifest['psa_framework_version'] == 1.0:
129 # For 1.0 Partition, the model is IPC
130 manifest['model'] = 'IPC'
131
132 # "model" validation:
133 model = manifest.get('model', None)
134 if model == None:
135 raise Exception('{} is missing the "model" attribute'.format(manifest['name']))
136
137 # Assign a unified 'entry' for templates
138 if model == 'IPC':
139 # entry_point is mandatory for IPC Partitions
140 if 'entry_point' not in manifest.keys():
141 raise Exception('{} is missing the "entry_point" attribute'.format(manifest['name']))
142 manifest['entry'] = manifest['entry_point']
143 elif model == 'SFN':
144 if 'entry_init' in manifest.keys():
145 manifest['entry'] = manifest['entry_init']
146 else:
147 manifest['entry'] = 0
148 else:
149 raise Exception('Invalid "model" of {}'.format(manifest['name']))
Kevin Peng8849b6a2021-11-09 14:17:35 +0800150
151 # Service FF-M manifest validation
152 for service in service_list:
Kevin Peng5c3fee72022-02-16 22:25:22 +0800153 if manifest['psa_framework_version'] == 1.0:
154 service['connection_based'] = True
155 elif 'connection_based' not in service:
156 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
157
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800158 if 'version' not in service.keys():
159 service['version'] = 1
160 if 'version_policy' not in service.keys():
Kevin Peng5bc82d22021-10-19 11:18:40 +0800161 service['version_policy'] = 'STRICT'
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800162
Kevin Peng5bc82d22021-10-19 11:18:40 +0800163 # SID duplication check
164 if service['sid'] in sid_list:
165 raise Exception('Service ID: {} has duplications!'.format(service['sid']))
166 else:
167 sid_list.append(service['sid'])
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100168
Kevin Peng5c3fee72022-02-16 22:25:22 +0800169 return manifest
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800170
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800171def check_circular_dependency(partitions, service_partition_map):
172 """
173 This function detects if there is any circular partition dependency chain.
174 If a circular dependency is detected, the script exits with error.
175
176 Inputs:
177 - partitions: dict of partition manifests
178 - service_partition_map: map between services and their owner Partitions
179 """
180
181 dependency_table = {}
182 for partition in partitions:
183 manifest = partition['manifest']
184 dependencies = manifest['dependencies'].copy() \
185 if 'dependencies' in manifest else []
186 dependencies += manifest['weak_dependencies'].copy() \
187 if 'weak_dependencies' in manifest else []
188 dependency_table[manifest['name']] = {
189 'dependencies': [service_partition_map[dependency]
190 for dependency in dependencies
191 if dependency in service_partition_map],
192 'validated': False
193 }
194
195 for partition in dependency_table.keys():
196 validate_dependency_chain(partition, dependency_table, [])
197
198def validate_dependency_chain(partition,
199 dependency_table,
200 dependency_chain):
201 """
202 Recursively validate if the given partition and its dependencies
203 have a circular dependency with the given dependency_chain.
204 Exit with error code once any circular is detected.
205
206 Inputs:
207 - partition: next partition to be checked
208 - dependency_table: dict of partitions and their dependencies
209 - dependency_chain: list of dependencies in current chain
210 """
211
212 dependency_chain.append(partition)
213 if partition in dependency_chain[:-1]:
214 logging.error(
215 'Circular dependency exists in chain: {}'.format(
216 ', '.join(dependency_chain)))
217 exit(1)
218 for dependency in dependency_table[partition]['dependencies']:
219 if dependency_table[dependency]['validated']:
220 continue
221 validate_dependency_chain(dependency, dependency_table, dependency_chain)
222 dependency_table[partition]['validated'] = True
223
chesun012345aa52023-04-18 17:31:53 +0800224def manifest_attribute_check(manifest, manifest_item):
225 """
226 Check whether Non-FF-M compliant attributes are explicitly registered in manifest lists.
227
228 Inputs:
229 - manifest: next manifest to be checked
230 - manifest_item: the manifest items in manifest lists
231 """
232 allowed_attributes = ffm_manifest_attributes + manifest_item.get('non_ffm_attributes', [])
233 for keyword in manifest.keys():
234 if keyword not in allowed_attributes:
235 logging.error('The Non-FFM attribute {} is used by {} without registration.'.format(keyword, manifest['name']))
236 exit(1)
237
Kevin Pengfb1761b2022-05-12 12:11:31 +0800238def process_partition_manifests(manifest_lists, configs):
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100239 """
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800240 Parse the input manifest lists, check if manifest settings are valid,
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700241 generate the data base for generated files
Kevin Peng655f2392019-11-27 16:33:02 +0800242 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100243
244 Parameters
245 ----------
Kevin Peng65064c52021-10-27 17:12:17 +0800246 manifest_lists:
Kevin Pengfb1761b2022-05-12 12:11:31 +0800247 A list of Secure Partition manifest lists
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100248
249 Returns
250 -------
Kevin Peng5bc82d22021-10-19 11:18:40 +0800251 The manifest data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +0800252 """
Kevin Peng655f2392019-11-27 16:33:02 +0800253
Kevin Peng5bc82d22021-10-19 11:18:40 +0800254 context = {}
255
Ken Liu861b0782021-05-22 13:15:08 +0800256 partition_list = []
Kevin Peng65064c52021-10-27 17:12:17 +0800257 all_manifests = []
Kevin Peng56b0ea62021-10-18 11:32:57 +0800258 pid_list = []
259 no_pid_manifest_idx = []
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800260 service_partition_map = {}
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800261 partition_statistics = {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800262 'connection_based_srv_num': 0,
Kevin Peng47c26ec2022-03-11 11:49:52 +0800263 'ipc_partitions': [],
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800264 'mmio_region_num': 0,
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800265 'flih_num': 0,
266 'slih_num': 0
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800267 }
Kevin Peng9f1a7542022-02-07 16:32:27 +0800268 config_impl = {
269 'CONFIG_TFM_SPM_BACKEND_SFN' : '0',
270 'CONFIG_TFM_SPM_BACKEND_IPC' : '0',
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800271 'CONFIG_TFM_CONNECTION_BASED_SERVICE_API' : '0',
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800272 'CONFIG_TFM_MMIO_REGION_ENABLE' : '0',
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800273 'CONFIG_TFM_FLIH_API' : '0',
274 'CONFIG_TFM_SLIH_API' : '0'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800275 }
Kevin Peng655f2392019-11-27 16:33:02 +0800276
Kevin Pengfb1761b2022-05-12 12:11:31 +0800277 isolation_level = int(configs['TFM_ISOLATION_LEVEL'], base = 10)
278 backend = configs['CONFIG_TFM_SPM_BACKEND']
279
Kevin Peng65064c52021-10-27 17:12:17 +0800280 # Get all the manifests information as a dictionary
281 for i, item in enumerate(manifest_lists):
Kevin Pengfb1761b2022-05-12 12:11:31 +0800282 if not os.path.isfile(item):
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500283 logging.error('Manifest list item [{}] must be a file'.format(i))
Kevin Peng65064c52021-10-27 17:12:17 +0800284 exit(1)
Kevin Peng655f2392019-11-27 16:33:02 +0800285
Kevin Peng65064c52021-10-27 17:12:17 +0800286 # The manifest list file generated by configure_file()
287 with open(item) as manifest_list_yaml_file:
288 manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
289 for dict in manifest_dic:
Kevin Pengfb1761b2022-05-12 12:11:31 +0800290 # Replace environment variables in the manifest path and convert to absolute path.
291 # If it's already abspath, the path will not be changed.
292 manifest_path = os.path.join(os.path.dirname(item), # path of manifest list
293 os.path.expandvars(dict['manifest']))\
294 .replace('\\', '/')
295 dict['manifest'] = manifest_path
Kevin Peng65064c52021-10-27 17:12:17 +0800296 all_manifests.append(dict)
297
Chris Brand4b69fcf2022-06-06 09:37:49 -0700298 logging.info("------------ Display partition configuration - start ------------")
299
Kevin Peng65064c52021-10-27 17:12:17 +0800300 # Parse the manifests
301 for i, manifest_item in enumerate(all_manifests):
Kevin Pengfb1761b2022-05-12 12:11:31 +0800302 valid_enabled_conditions = ['1', 'on', 'true', 'enabled']
303 valid_disabled_conditions = ['0', 'off', 'false', 'disabled', '']
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800304 is_enabled = ''
305
306 if 'conditional' in manifest_item.keys():
Kevin Pengfb1761b2022-05-12 12:11:31 +0800307 if manifest_item['conditional'] not in configs.keys():
308 logging.error('Configuration "{}" is not defined!'.format(manifest_item['conditional']))
309 exit(1)
310 is_enabled = configs[manifest_item['conditional']].lower()
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800311 else:
Kevin Pengfb1761b2022-05-12 12:11:31 +0800312 # Partitions without 'conditional' is always on
313 is_enabled = '1'
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800314
315 if is_enabled in valid_disabled_conditions:
BohdanHunko6cea95d2022-08-16 15:33:51 +0300316 logging.info(" {:40s} OFF".format(manifest_item['description']))
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800317 continue
Chris Brand4b69fcf2022-06-06 09:37:49 -0700318 elif is_enabled in valid_enabled_conditions:
BohdanHunko6cea95d2022-08-16 15:33:51 +0300319 logging.info(" {:40s} ON".format(manifest_item['description']))
Chris Brand4b69fcf2022-06-06 09:37:49 -0700320 else:
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800321 raise Exception('Invalid "conditional" attribute: "{}" for {}. '
322 'Please set to one of {} or {}, case-insensitive.'\
323 .format(manifest_item['conditional'],
BohdanHunko6cea95d2022-08-16 15:33:51 +0300324 manifest_item['description'],
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800325 valid_enabled_conditions, valid_disabled_conditions))
326
Xinyu Zhangc46ee1f2021-04-01 10:10:43 +0800327 # Check if partition ID is manually set
328 if 'pid' not in manifest_item.keys():
329 no_pid_manifest_idx.append(i)
Kevin Peng8849b6a2021-11-09 14:17:35 +0800330 pid = None
Kevin Peng56b0ea62021-10-18 11:32:57 +0800331 else:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800332 pid = manifest_item['pid']
333
334 # Check if partition ID is duplicated
335 if pid in pid_list:
Antonio de Angelisbaa27642022-05-25 11:07:12 +0100336 raise Exception('PID No. {} has already been used!'.format(pid))
Kevin Peng8849b6a2021-11-09 14:17:35 +0800337 else:
338 pid_list.append(pid)
Xinyu Zhang19504a52021-03-31 16:26:20 +0800339
Kevin Pengfb1761b2022-05-12 12:11:31 +0800340 manifest_path = manifest_item['manifest']
Kevin Peng5bc82d22021-10-19 11:18:40 +0800341 with open(manifest_path) as manifest_file:
Kevin Pengec0e5ce2022-02-17 13:48:51 +0800342 manifest = yaml.safe_load(manifest_file)
chesun012345aa52023-04-18 17:31:53 +0800343 # check manifest attribute validity
344 manifest_attribute_check(manifest, manifest_item)
345
Kevin Pengec0e5ce2022-02-17 13:48:51 +0800346 if manifest.get('model', None) == 'dual':
347 # If a Partition supports both models, it can set the "model" to "backend".
348 # The actual model used follows the backend being used.
349 manifest['model'] = backend
350 manifest = manifest_validation(manifest, pid)
Kevin Peng655f2392019-11-27 16:33:02 +0800351
Kevin Pengce99e5d2021-11-09 18:06:53 +0800352 if pid == None or pid >= TFM_PID_BASE:
Kevin Pengd08f3ba2021-11-18 15:18:56 +0800353 # Count the number of IPC/SFN partitions
Kevin Peng47c26ec2022-03-11 11:49:52 +0800354 if manifest['model'] == 'IPC':
355 partition_statistics['ipc_partitions'].append(manifest['name'])
Mingyang Suneab7eae2021-09-30 13:06:52 +0800356
Kevin Peng5c3fee72022-02-16 22:25:22 +0800357 # Set initial value to -1 to make (srv_idx + 1) reflect the correct
358 # number (0) when there are no services.
359 srv_idx = -1
360 for srv_idx, service in enumerate(manifest.get('services', [])):
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800361 service_partition_map[service['name']] = manifest['name']
Kevin Peng5c3fee72022-02-16 22:25:22 +0800362 if manifest['model'] == 'IPC':
363 # Assign signal value, the first 4 bits are reserved by FF-M
364 service['signal_value'] = (1 << (srv_idx + 4))
365 else:
366 # Signals of SFN Partitions are SPM internal only, does not
367 # need to reserve 4 bits.
368 service['signal_value'] = (1 << srv_idx)
369 if service['connection_based']:
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800370 partition_statistics['connection_based_srv_num'] += 1
Kevin Peng5c3fee72022-02-16 22:25:22 +0800371 logging.debug('{} has {} services'.format(manifest['name'], srv_idx +1))
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800372
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800373 # Calculate the number of mmio region
374 mmio_region_list = manifest.get('mmio_regions', [])
375 partition_statistics['mmio_region_num'] += len(mmio_region_list)
376
Kevin Peng5c3fee72022-02-16 22:25:22 +0800377 # Set initial value to -1 to make (irq + 1) reflect the correct
378 # number (0) when there are no irqs.
379 irq_idx = -1
380 for irq_idx, irq in enumerate(manifest.get('irqs', [])):
381 # Assign signal value, from the most significant bit
382 irq['signal_value'] = (1 << (31 - irq_idx))
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800383 if irq.get('handling', None) == 'FLIH':
384 partition_statistics['flih_num'] += 1
385 else:
386 partition_statistics['slih_num'] += 1
Kevin Peng5c3fee72022-02-16 22:25:22 +0800387 logging.debug('{} has {} IRQS'.format(manifest['name'], irq_idx +1))
388
389 if ((srv_idx + 1) + (irq_idx + 1)) > 28:
390 raise Exception('Total number of Services and IRQs of {} exceeds the limit (28)'
391 .format(manifest['name']))
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800392
Kevin Peng65064c52021-10-27 17:12:17 +0800393 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800394
Kevin Peng4fade072021-10-26 17:57:50 +0800395 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800396 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800397 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800398 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800399
Kevin Peng5bc82d22021-10-19 11:18:40 +0800400 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
401 '{}.h'.format(manifest_out_basename))\
402 .replace('\\', '/')
403 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
404 'intermedia_{}.c'.format(manifest_out_basename))\
405 .replace('\\', '/')
406 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
407 'load_info_{}.c'.format(manifest_out_basename))\
408 .replace('\\', '/')
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800409 output_dir = os.path.join(OUT_DIR, output_path).replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800410
Kevin Peng5bc82d22021-10-19 11:18:40 +0800411 partition_list.append({'manifest': manifest, 'attr': manifest_item,
412 'manifest_out_basename': manifest_out_basename,
413 'header_file': manifest_head_file,
414 'intermedia_file': intermedia_file,
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800415 'loadinfo_file': load_info_file,
416 'output_dir':output_dir})
Ken Liu861b0782021-05-22 13:15:08 +0800417
Chris Brand4b69fcf2022-06-06 09:37:49 -0700418 logging.info("------------ Display partition configuration - end ------------")
419
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800420 check_circular_dependency(partition_list, service_partition_map)
421
Kevin Peng56b0ea62021-10-18 11:32:57 +0800422 # Automatically assign PIDs for partitions without 'pid' attribute
Kevin Pengce99e5d2021-11-09 18:06:53 +0800423 pid = max(pid_list, default = TFM_PID_BASE - 1)
Kevin Peng56b0ea62021-10-18 11:32:57 +0800424 for idx in no_pid_manifest_idx:
Kevin Pengc424eec2021-06-25 17:26:11 +0800425 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800426 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800427 pid_list.append(pid)
428
Kevin Peng9f1a7542022-02-07 16:32:27 +0800429 # Set up configurations
Kevin Peng76c0c162022-02-09 22:49:06 +0800430 if backend == 'SFN':
Kevin Peng47c26ec2022-03-11 11:49:52 +0800431 if len(partition_statistics['ipc_partitions']) > 0:
432 logging.error('SFN backend does not support IPC Partitions:')
433 logging.error(partition_statistics['ipc_partitions'])
Kevin Peng9f1a7542022-02-07 16:32:27 +0800434 exit(1)
Kevin Peng76c0c162022-02-09 22:49:06 +0800435
436 if isolation_level > 1:
437 logging.error('SFN backend does not support high isolation levels.')
438 exit(1)
439
Kevin Peng9f1a7542022-02-07 16:32:27 +0800440 config_impl['CONFIG_TFM_SPM_BACKEND_SFN'] = '1'
Kevin Peng76c0c162022-02-09 22:49:06 +0800441 elif backend == 'IPC':
Kevin Peng9f1a7542022-02-07 16:32:27 +0800442 config_impl['CONFIG_TFM_SPM_BACKEND_IPC'] = '1'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800443
444 if partition_statistics['connection_based_srv_num'] > 0:
445 config_impl['CONFIG_TFM_CONNECTION_BASED_SERVICE_API'] = 1
446
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800447 if partition_statistics['mmio_region_num'] > 0:
448 config_impl['CONFIG_TFM_MMIO_REGION_ENABLE'] = 1
449
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800450 if partition_statistics['flih_num'] > 0:
451 config_impl['CONFIG_TFM_FLIH_API'] = 1
Joakim Anderssoneec5cd32022-06-10 12:02:07 +0200452 if partition_statistics['slih_num'] > 0:
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800453 config_impl['CONFIG_TFM_SLIH_API'] = 1
454
Kevin Peng5bc82d22021-10-19 11:18:40 +0800455 context['partitions'] = partition_list
Kevin Peng9f1a7542022-02-07 16:32:27 +0800456 context['config_impl'] = config_impl
Kevin Pengce99e5d2021-11-09 18:06:53 +0800457 context['stateless_services'] = process_stateless_services(partition_list)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100458
Kevin Peng5bc82d22021-10-19 11:18:40 +0800459 return context
Ken Liu861b0782021-05-22 13:15:08 +0800460
461def gen_per_partition_files(context):
462 """
463 Generate per-partition files
464
465 Parameters
466 ----------
467 context:
468 context contains partition infos
469 """
470
Kevin Peng5bc82d22021-10-19 11:18:40 +0800471 partition_context = {}
Sherry Zhangf58f2bd2022-01-10 17:21:11 +0800472 partition_context['utilities'] = context['utilities']
Sherry Zhangf865c4e2022-03-23 13:53:38 +0800473 partition_context['config_impl'] = context['config_impl']
Ken Liu861b0782021-05-22 13:15:08 +0800474
Kevin Peng5bc82d22021-10-19 11:18:40 +0800475 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
476 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
477 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800478
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500479 logging.info ("Start to generate partition files:")
Ken Liu861b0782021-05-22 13:15:08 +0800480
481 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800482 partition_context['manifest'] = one_partition['manifest']
483 partition_context['attr'] = one_partition['attr']
484 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800485
BohdanHunko6cea95d2022-08-16 15:33:51 +0300486 logging.info ('Generating {} in {}'.format(one_partition['attr']['description'],
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800487 one_partition['output_dir']))
Ken Liu861b0782021-05-22 13:15:08 +0800488 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800489 if not os.path.exists(outfile_path):
490 os.makedirs(outfile_path)
491
Kevin Peng5bc82d22021-10-19 11:18:40 +0800492 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
493 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800494 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800495
Ken Liu861b0782021-05-22 13:15:08 +0800496 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800497 if not os.path.exists(intermediafile_path):
498 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800499 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
500 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800501 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800502
Ken Liu861b0782021-05-22 13:15:08 +0800503 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800504 if not os.path.exists(infofile_path):
505 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800506 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
507 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800508 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800509
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500510 logging.info ("Per-partition files done:")
Mingyang Sunf6a78572021-04-02 16:51:05 +0800511
Ken Liu861b0782021-05-22 13:15:08 +0800512def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800513 """
514 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800515
516 Parameters
517 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100518 gen_file_lists:
519 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800520 """
Kevin Peng655f2392019-11-27 16:33:02 +0800521 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800522
Raef Colesf42f0882020-07-10 10:01:58 +0100523 for f in gen_file_lists:
524 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800525 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800526 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800527
Kevin Peng655f2392019-11-27 16:33:02 +0800528 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000529 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800530 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000531 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800532 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800533
Kevin Peng4fade072021-10-26 17:57:50 +0800534 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800535
Ken Liu861b0782021-05-22 13:15:08 +0800536 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800537 if not os.path.exists(outfile_path):
538 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800539
Kevin Peng655f2392019-11-27 16:33:02 +0800540 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800541
Kevin Peng5bc82d22021-10-19 11:18:40 +0800542 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800543 outfile.write(template.render(context))
544 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800545
Kevin Pengce99e5d2021-11-09 18:06:53 +0800546def process_stateless_services(partitions):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800547 """
548 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800549 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800550 Valid stateless handle in service will be converted to an index. If the
551 stateless handle is set as "auto", or not set, framework will allocate a
552 valid index for the service.
553 Framework puts each service into a reordered stateless service list at
554 position of "index". Other unused positions are left None.
Ken Liu50948382022-10-27 12:45:53 +0800555
556 Keep the variable names start with upper case 'STATIC_HANDLE_' the same
557 as the preprocessors in C sources. This could easier the upcomping
558 modification when developer searches these definitions for modification.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800559 """
Kevin Pengce99e5d2021-11-09 18:06:53 +0800560
Kevin Pengc05319d2021-04-22 22:59:35 +0800561 collected_stateless_services = []
Ken Liu50948382022-10-27 12:45:53 +0800562 STATIC_HANDLE_NUM_LIMIT = 32
Mingyang Suna1ca6112021-01-11 11:34:59 +0800563
564 # Collect all stateless services first.
565 for partition in partitions:
566 # Skip the FF-M 1.0 partitions
567 if partition['manifest']['psa_framework_version'] < 1.1:
568 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800569
570 service_list = partition['manifest'].get('services', [])
571
572 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800573 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800574 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800575
Kevin Pengc05319d2021-04-22 22:59:35 +0800576 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800577 return []
578
Ken Liu50948382022-10-27 12:45:53 +0800579 if len(collected_stateless_services) > STATIC_HANDLE_NUM_LIMIT:
580 raise Exception('Stateless service numbers range exceed {number}.'.format(number=STATIC_HANDLE_NUM_LIMIT))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800581
582 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800583 Allocate an empty stateless service list to store services.
584 Use "handle - 1" as the index for service, since handle value starts from
585 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800586 """
Ken Liu50948382022-10-27 12:45:53 +0800587 reordered_stateless_services = [None] * STATIC_HANDLE_NUM_LIMIT
Kevin Pengc05319d2021-04-22 22:59:35 +0800588 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800589
Kevin Pengc05319d2021-04-22 22:59:35 +0800590 for service in collected_stateless_services:
591 # If not set, it is "auto" by default
592 if 'stateless_handle' not in service:
593 auto_alloc_services.append(service)
594 continue
595
Mingyang Sun4ecea992021-03-30 17:56:26 +0800596 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800597
Mingyang Sun4ecea992021-03-30 17:56:26 +0800598 # Fill in service list with specified stateless handle, otherwise skip
599 if isinstance(service_handle, int):
Ken Liu50948382022-10-27 12:45:53 +0800600 if service_handle < 1 or service_handle > STATIC_HANDLE_NUM_LIMIT:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800601 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800602 # Convert handle index to reordered service list index
603 service_handle = service_handle - 1
604
605 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800606 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800607 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800608 elif service_handle == 'auto':
609 auto_alloc_services.append(service)
610 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800611 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800612
Xinyu Zhangb2d4ed42023-02-14 11:43:16 +0800613 STATIC_HANDLE_IDX_BIT_WIDTH = 5
Kevin Pengce99e5d2021-11-09 18:06:53 +0800614 STATIC_HANDLE_IDX_MASK = (1 << STATIC_HANDLE_IDX_BIT_WIDTH) - 1
Ken Liu50948382022-10-27 12:45:53 +0800615 STATIC_HANDLE_INDICATOR_OFFSET = 30
616 STATIC_HANDLE_VER_OFFSET = 8
617 STATIC_HANDLE_VER_BIT_WIDTH = 8
Kevin Pengce99e5d2021-11-09 18:06:53 +0800618 STATIC_HANDLE_VER_MASK = (1 << STATIC_HANDLE_VER_BIT_WIDTH) - 1
619
Mingyang Sun4ecea992021-03-30 17:56:26 +0800620 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu50948382022-10-27 12:45:53 +0800621 for i in range(0, STATIC_HANDLE_NUM_LIMIT):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800622 service = reordered_stateless_services[i]
623
Kevin Pengc05319d2021-04-22 22:59:35 +0800624 if service == None and len(auto_alloc_services) > 0:
625 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800626
Mingyang Sun453ad402021-03-17 17:58:33 +0800627 """
628 Encode stateless flag and version into stateless handle
Mingyang Sun453ad402021-03-17 17:58:33 +0800629 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800630 stateless_handle_value = 0
631 if service != None:
Kevin Pengce99e5d2021-11-09 18:06:53 +0800632 stateless_index = (i & STATIC_HANDLE_IDX_MASK)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800633 stateless_handle_value |= stateless_index
Kevin Pengce99e5d2021-11-09 18:06:53 +0800634 stateless_handle_value |= (1 << STATIC_HANDLE_INDICATOR_OFFSET)
635 stateless_version = (service['version'] & STATIC_HANDLE_VER_MASK) << STATIC_HANDLE_VER_OFFSET
Mingyang Sun453ad402021-03-17 17:58:33 +0800636 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800637 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800638 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800639
Mingyang Sun4ecea992021-03-30 17:56:26 +0800640 reordered_stateless_services[i] = service
641
642 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800643
Kevin Peng655f2392019-11-27 16:33:02 +0800644def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000645 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
646 epilog='Note that environment variables in template files will be replaced with their values')
647
Kevin Peng655f2392019-11-27 16:33:02 +0800648 parser.add_argument('-o', '--outdir'
649 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800650 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800651 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800652 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800653
Kevin Peng5bc82d22021-10-19 11:18:40 +0800654 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100655 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800656 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100657 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800658 , metavar='manifest list'
659 , help='A list of Secure Partition manifest lists and their original paths.\n\
660 The manifest lists might be processed by CMake and\n\
661 the path might be different to the original one\n\
662 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800663
664 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100665 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800666 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100667 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800668 , metavar='file-list'
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700669 , help='These files describe the file list to generate')
Kevin Peng9f1a7542022-02-07 16:32:27 +0800670
Kevin Pengfb1761b2022-05-12 12:11:31 +0800671 parser.add_argument('-c', '--config-files'
672 , nargs='+'
673 , dest='config_files'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800674 , required=True
Kevin Pengfb1761b2022-05-12 12:11:31 +0800675 , metavar='config-files'
676 , help='A header file contains build configurations')
Kevin Peng9f1a7542022-02-07 16:32:27 +0800677
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500678 parser.add_argument('-q', '--quiet'
679 , dest='quiet'
680 , required=False
681 , default=False
682 , action='store_true'
683 , help='Reduce log messages')
Kevin Peng655f2392019-11-27 16:33:02 +0800684
685 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800686
Kevin Peng655f2392019-11-27 16:33:02 +0800687 return args
688
689ENV = Environment(
690 loader = TemplateLoader(),
691 autoescape = select_autoescape(['html', 'xml']),
692 lstrip_blocks = True,
693 trim_blocks = True,
694 keep_trailing_newline = True
695 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100696
Miklos Balint470919c2018-05-22 17:51:29 +0200697def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100698 """
699 The entry point of the script.
700
701 Generates the output files based on the templates and the manifests.
702 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800703
Kevin Peng655f2392019-11-27 16:33:02 +0800704 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800705
Kevin Peng655f2392019-11-27 16:33:02 +0800706 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800707
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500708 logging.basicConfig(format='%(message)s'
709 , level=logging.WARNING if args.quiet else logging.INFO)
710
Kevin Peng5bc82d22021-10-19 11:18:40 +0800711 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800712
Kevin Peng5bc82d22021-10-19 11:18:40 +0800713 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
714 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800715
Shawn Shana9ad1e02019-08-07 15:49:48 +0800716 """
Kevin Peng655f2392019-11-27 16:33:02 +0800717 Relative path to TF-M root folder is supported in the manifests
718 and default value of manifest list and generated file list are relative to TF-M root folder as well,
719 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800720 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800721 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 +0800722 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800723 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800724
Kevin Peng76c0c162022-02-09 22:49:06 +0800725 context = process_partition_manifests(manifest_lists,
Kevin Pengfb1761b2022-05-12 12:11:31 +0800726 parse_configurations(args.config_files))
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100727
Edison Ai6e3f2a32019-06-11 15:29:05 +0800728 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800729 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200730
Kevin Peng655f2392019-11-27 16:33:02 +0800731 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800732
Ken Liu861b0782021-05-22 13:15:08 +0800733 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800734 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200735
Kevin Peng5bc82d22021-10-19 11:18:40 +0800736if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200737 main()