blob: 99798ab24c3fef1bea2331c8c882f092b34fd356 [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 = []
Mate Toth-Pal36f21842018-11-08 16:12:51 +010036class TemplateLoader(BaseLoader):
37 """
38 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020039
Mate Toth-Pal36f21842018-11-08 16:12:51 +010040 An instance of this class is passed to the template engine. It is
41 responsible for reading the template file
42 """
43 def __init__(self):
44 pass
Miklos Balint470919c2018-05-22 17:51:29 +020045
Mate Toth-Pal36f21842018-11-08 16:12:51 +010046 def get_source(self, environment, template):
47 """
48 This function reads the template files.
49 For detailed documentation see:
50 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
51
52 Please note that this function always return 'false' as 'uptodate'
53 value, so the output file will always be generated.
54 """
55 if not os.path.isfile(template):
56 raise TemplateNotFound(template)
57 with open(template) as f:
58 source = f.read()
59 return source, template, False
60
Kevin Pengfb1761b2022-05-12 12:11:31 +080061def parse_configurations(file_paths):
62 """
63 Parses the given config files and return a dict whose key-values are build
64 configurations and their values.
65
66 Valid configurations should be in the format of:
67 "#define VAR [...]" in a single line.
68 The value of the config is optional.
69 """
70 configurations = {}
71
72 lines = []
73 for file in file_paths:
74 with open(file, 'r') as config_file:
75 lines += config_file.readlines()
76
77 for line in lines:
78 if not line.startswith('#define'):
79 continue
80
81 line = line.rstrip('\r\n')
82 line_items = line.split(maxsplit=2)
83 if len(line_items) == 3:
84 configurations[line_items[1]] = line_items[2]
85 elif len(line_items) == 2:
86 configurations[line_items[1]] = ''
87
88 logging.debug(configurations)
89
90 return configurations
91
Kevin Peng5c3fee72022-02-16 22:25:22 +080092def manifest_validation(manifest, pid):
Mingyang Sun294ce2e2021-06-11 11:58:24 +080093 """
94 This function validates FF-M compliance for partition manifest, and sets
95 default values for optional attributes.
Kevin Pengce99e5d2021-11-09 18:06:53 +080096 The validation is skipped for TF-M specific Partitions (PID < TFM_PID_BASE).
Mingyang Sun294ce2e2021-06-11 11:58:24 +080097 """
Kevin Peng5bc82d22021-10-19 11:18:40 +080098
Kevin Peng5c3fee72022-02-16 22:25:22 +080099 service_list = manifest.get('services', [])
100 irq_list = manifest.get('irqs', [])
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800101
Kevin Peng5c3fee72022-02-16 22:25:22 +0800102 # "psa_framework_version" validation
103 if manifest['psa_framework_version'] not in [1.0, 1.1]:
104 raise Exception('Invalid psa_framework_version of {}'.format(manifest['name']))
105
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700106 # "type" validation
Kevin Peng5c3fee72022-02-16 22:25:22 +0800107 if manifest['type'] not in ['PSA-ROT', 'APPLICATION-ROT']:
108 raise Exception('Invalid type of {}'.format(manifest['name']))
109
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700110 # "priority" validation
111 if manifest['priority'] not in ['HIGH', 'NORMAL', 'LOW']:
112 raise Exception('Invalid priority of {}'.format(manifest['name']))
113
Chris Brandc422cdd2022-07-21 13:32:47 -0700114 if 'ns_agent' not in manifest:
115 manifest['ns_agent'] = False
116
Kevin Peng5c3fee72022-02-16 22:25:22 +0800117 # Every PSA Partition must have at least either a secure service or an IRQ
Kevin Pengce99e5d2021-11-09 18:06:53 +0800118 if (pid == None or pid >= TFM_PID_BASE) \
Kevin Peng8849b6a2021-11-09 14:17:35 +0800119 and len(service_list) == 0 and len(irq_list) == 0:
120 raise Exception('{} must declare at least either a secure service or an IRQ!'
Kevin Peng5c3fee72022-02-16 22:25:22 +0800121 .format(manifest['name']))
122
123 if manifest['psa_framework_version'] == 1.0:
124 # For 1.0 Partition, the model is IPC
125 manifest['model'] = 'IPC'
126
127 # "model" validation:
128 model = manifest.get('model', None)
129 if model == None:
130 raise Exception('{} is missing the "model" attribute'.format(manifest['name']))
131
132 # Assign a unified 'entry' for templates
133 if model == 'IPC':
134 # entry_point is mandatory for IPC Partitions
135 if 'entry_point' not in manifest.keys():
136 raise Exception('{} is missing the "entry_point" attribute'.format(manifest['name']))
137 manifest['entry'] = manifest['entry_point']
138 elif model == 'SFN':
139 if 'entry_init' in manifest.keys():
140 manifest['entry'] = manifest['entry_init']
141 else:
142 manifest['entry'] = 0
143 else:
144 raise Exception('Invalid "model" of {}'.format(manifest['name']))
Kevin Peng8849b6a2021-11-09 14:17:35 +0800145
146 # Service FF-M manifest validation
147 for service in service_list:
Kevin Peng5c3fee72022-02-16 22:25:22 +0800148 if manifest['psa_framework_version'] == 1.0:
149 service['connection_based'] = True
150 elif 'connection_based' not in service:
151 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
152
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800153 if 'version' not in service.keys():
154 service['version'] = 1
155 if 'version_policy' not in service.keys():
Kevin Peng5bc82d22021-10-19 11:18:40 +0800156 service['version_policy'] = 'STRICT'
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800157
Kevin Peng5bc82d22021-10-19 11:18:40 +0800158 # SID duplication check
159 if service['sid'] in sid_list:
160 raise Exception('Service ID: {} has duplications!'.format(service['sid']))
161 else:
162 sid_list.append(service['sid'])
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100163
Kevin Peng5c3fee72022-02-16 22:25:22 +0800164 return manifest
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800165
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800166def check_circular_dependency(partitions, service_partition_map):
167 """
168 This function detects if there is any circular partition dependency chain.
169 If a circular dependency is detected, the script exits with error.
170
171 Inputs:
172 - partitions: dict of partition manifests
173 - service_partition_map: map between services and their owner Partitions
174 """
175
176 dependency_table = {}
177 for partition in partitions:
178 manifest = partition['manifest']
179 dependencies = manifest['dependencies'].copy() \
180 if 'dependencies' in manifest else []
181 dependencies += manifest['weak_dependencies'].copy() \
182 if 'weak_dependencies' in manifest else []
183 dependency_table[manifest['name']] = {
184 'dependencies': [service_partition_map[dependency]
185 for dependency in dependencies
186 if dependency in service_partition_map],
187 'validated': False
188 }
189
190 for partition in dependency_table.keys():
191 validate_dependency_chain(partition, dependency_table, [])
192
193def validate_dependency_chain(partition,
194 dependency_table,
195 dependency_chain):
196 """
197 Recursively validate if the given partition and its dependencies
198 have a circular dependency with the given dependency_chain.
199 Exit with error code once any circular is detected.
200
201 Inputs:
202 - partition: next partition to be checked
203 - dependency_table: dict of partitions and their dependencies
204 - dependency_chain: list of dependencies in current chain
205 """
206
207 dependency_chain.append(partition)
208 if partition in dependency_chain[:-1]:
209 logging.error(
210 'Circular dependency exists in chain: {}'.format(
211 ', '.join(dependency_chain)))
212 exit(1)
213 for dependency in dependency_table[partition]['dependencies']:
214 if dependency_table[dependency]['validated']:
215 continue
216 validate_dependency_chain(dependency, dependency_table, dependency_chain)
217 dependency_table[partition]['validated'] = True
218
Kevin Peng93efad02022-08-01 17:58:13 +0800219def manifest_attribute_to_int(manifest, attribute, configs):
220 """
221 This method tries to convert the value of the given `attribute` in the given
222 `manifest` to an integer.
223 If the value is a decimal/hexadecimal int, return it directly.
224 Otherwise, treat it as a configuration and find the value in the given `configs`.
225 If the configuration is not found, exit script with error.
226 """
227
228 value = manifest[attribute]
229 try:
230 # base 16 works for both decimal and hexadecimal
231 int(value, base=16)
232 except ValueError:
233 # Not an int, find the value in configs
234 if value not in configs.keys():
235 logging.error('{} is not defined in configurations'.format(value))
236 exit(1)
237
238 value = configs[value]
239
240 return value
241
Kevin Pengfb1761b2022-05-12 12:11:31 +0800242def process_partition_manifests(manifest_lists, configs):
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100243 """
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800244 Parse the input manifest lists, check if manifest settings are valid,
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700245 generate the data base for generated files
Kevin Peng655f2392019-11-27 16:33:02 +0800246 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100247
248 Parameters
249 ----------
Kevin Peng65064c52021-10-27 17:12:17 +0800250 manifest_lists:
Kevin Pengfb1761b2022-05-12 12:11:31 +0800251 A list of Secure Partition manifest lists
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100252
253 Returns
254 -------
Kevin Peng5bc82d22021-10-19 11:18:40 +0800255 The manifest data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +0800256 """
Kevin Peng655f2392019-11-27 16:33:02 +0800257
Kevin Peng5bc82d22021-10-19 11:18:40 +0800258 context = {}
259
Ken Liu861b0782021-05-22 13:15:08 +0800260 partition_list = []
Kevin Peng65064c52021-10-27 17:12:17 +0800261 all_manifests = []
Kevin Peng56b0ea62021-10-18 11:32:57 +0800262 pid_list = []
263 no_pid_manifest_idx = []
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800264 service_partition_map = {}
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800265 partition_statistics = {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800266 'connection_based_srv_num': 0,
Kevin Peng47c26ec2022-03-11 11:49:52 +0800267 'ipc_partitions': [],
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800268 'mmio_region_num': 0,
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800269 'flih_num': 0,
270 'slih_num': 0
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800271 }
Kevin Peng9f1a7542022-02-07 16:32:27 +0800272 config_impl = {
273 'CONFIG_TFM_SPM_BACKEND_SFN' : '0',
274 'CONFIG_TFM_SPM_BACKEND_IPC' : '0',
275 'CONFIG_TFM_PSA_API_SFN_CALL' : '0',
276 'CONFIG_TFM_PSA_API_CROSS_CALL' : '0',
277 'CONFIG_TFM_PSA_API_SUPERVISOR_CALL' : '0',
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800278 'CONFIG_TFM_CONNECTION_BASED_SERVICE_API' : '0',
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800279 'CONFIG_TFM_MMIO_REGION_ENABLE' : '0',
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800280 'CONFIG_TFM_FLIH_API' : '0',
281 'CONFIG_TFM_SLIH_API' : '0'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800282 }
Kevin Peng655f2392019-11-27 16:33:02 +0800283
Kevin Pengfb1761b2022-05-12 12:11:31 +0800284 isolation_level = int(configs['TFM_ISOLATION_LEVEL'], base = 10)
285 backend = configs['CONFIG_TFM_SPM_BACKEND']
286
Kevin Peng65064c52021-10-27 17:12:17 +0800287 # Get all the manifests information as a dictionary
288 for i, item in enumerate(manifest_lists):
Kevin Pengfb1761b2022-05-12 12:11:31 +0800289 if not os.path.isfile(item):
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500290 logging.error('Manifest list item [{}] must be a file'.format(i))
Kevin Peng65064c52021-10-27 17:12:17 +0800291 exit(1)
Kevin Peng655f2392019-11-27 16:33:02 +0800292
Kevin Peng65064c52021-10-27 17:12:17 +0800293 # The manifest list file generated by configure_file()
294 with open(item) as manifest_list_yaml_file:
295 manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
296 for dict in manifest_dic:
Kevin Pengfb1761b2022-05-12 12:11:31 +0800297 # Replace environment variables in the manifest path and convert to absolute path.
298 # If it's already abspath, the path will not be changed.
299 manifest_path = os.path.join(os.path.dirname(item), # path of manifest list
300 os.path.expandvars(dict['manifest']))\
301 .replace('\\', '/')
302 dict['manifest'] = manifest_path
Kevin Peng65064c52021-10-27 17:12:17 +0800303 all_manifests.append(dict)
304
Chris Brand4b69fcf2022-06-06 09:37:49 -0700305 logging.info("------------ Display partition configuration - start ------------")
306
Kevin Peng65064c52021-10-27 17:12:17 +0800307 # Parse the manifests
308 for i, manifest_item in enumerate(all_manifests):
Kevin Pengfb1761b2022-05-12 12:11:31 +0800309 valid_enabled_conditions = ['1', 'on', 'true', 'enabled']
310 valid_disabled_conditions = ['0', 'off', 'false', 'disabled', '']
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800311 is_enabled = ''
312
313 if 'conditional' in manifest_item.keys():
Kevin Pengfb1761b2022-05-12 12:11:31 +0800314 if manifest_item['conditional'] not in configs.keys():
315 logging.error('Configuration "{}" is not defined!'.format(manifest_item['conditional']))
316 exit(1)
317 is_enabled = configs[manifest_item['conditional']].lower()
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800318 else:
Kevin Pengfb1761b2022-05-12 12:11:31 +0800319 # Partitions without 'conditional' is always on
320 is_enabled = '1'
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800321
322 if is_enabled in valid_disabled_conditions:
BohdanHunko6cea95d2022-08-16 15:33:51 +0300323 logging.info(" {:40s} OFF".format(manifest_item['description']))
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800324 continue
Chris Brand4b69fcf2022-06-06 09:37:49 -0700325 elif is_enabled in valid_enabled_conditions:
BohdanHunko6cea95d2022-08-16 15:33:51 +0300326 logging.info(" {:40s} ON".format(manifest_item['description']))
Chris Brand4b69fcf2022-06-06 09:37:49 -0700327 else:
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800328 raise Exception('Invalid "conditional" attribute: "{}" for {}. '
329 'Please set to one of {} or {}, case-insensitive.'\
330 .format(manifest_item['conditional'],
BohdanHunko6cea95d2022-08-16 15:33:51 +0300331 manifest_item['description'],
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800332 valid_enabled_conditions, valid_disabled_conditions))
333
Xinyu Zhangc46ee1f2021-04-01 10:10:43 +0800334 # Check if partition ID is manually set
335 if 'pid' not in manifest_item.keys():
336 no_pid_manifest_idx.append(i)
Kevin Peng8849b6a2021-11-09 14:17:35 +0800337 pid = None
Kevin Peng56b0ea62021-10-18 11:32:57 +0800338 else:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800339 pid = manifest_item['pid']
340
341 # Check if partition ID is duplicated
342 if pid in pid_list:
Antonio de Angelisbaa27642022-05-25 11:07:12 +0100343 raise Exception('PID No. {} has already been used!'.format(pid))
Kevin Peng8849b6a2021-11-09 14:17:35 +0800344 else:
345 pid_list.append(pid)
Xinyu Zhang19504a52021-03-31 16:26:20 +0800346
Kevin Pengfb1761b2022-05-12 12:11:31 +0800347 manifest_path = manifest_item['manifest']
Kevin Peng5bc82d22021-10-19 11:18:40 +0800348 with open(manifest_path) as manifest_file:
Kevin Pengec0e5ce2022-02-17 13:48:51 +0800349 manifest = yaml.safe_load(manifest_file)
350 if manifest.get('model', None) == 'dual':
351 # If a Partition supports both models, it can set the "model" to "backend".
352 # The actual model used follows the backend being used.
353 manifest['model'] = backend
354 manifest = manifest_validation(manifest, pid)
Kevin Peng655f2392019-11-27 16:33:02 +0800355
Kevin Pengce99e5d2021-11-09 18:06:53 +0800356 if pid == None or pid >= TFM_PID_BASE:
Kevin Pengd08f3ba2021-11-18 15:18:56 +0800357 # Count the number of IPC/SFN partitions
Kevin Peng47c26ec2022-03-11 11:49:52 +0800358 if manifest['model'] == 'IPC':
359 partition_statistics['ipc_partitions'].append(manifest['name'])
Mingyang Suneab7eae2021-09-30 13:06:52 +0800360
Kevin Peng93efad02022-08-01 17:58:13 +0800361 # Convert stack_size and heap_size to int. They might be configurations.
362 manifest['stack_size'] = manifest_attribute_to_int(manifest, 'stack_size', configs)
363
364 if 'heap_size' in manifest.keys():
365 manifest['heap_size'] = manifest_attribute_to_int(manifest, 'heap_size', configs)
366
Kevin Peng5c3fee72022-02-16 22:25:22 +0800367 # Set initial value to -1 to make (srv_idx + 1) reflect the correct
368 # number (0) when there are no services.
369 srv_idx = -1
370 for srv_idx, service in enumerate(manifest.get('services', [])):
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800371 service_partition_map[service['name']] = manifest['name']
Kevin Peng5c3fee72022-02-16 22:25:22 +0800372 if manifest['model'] == 'IPC':
373 # Assign signal value, the first 4 bits are reserved by FF-M
374 service['signal_value'] = (1 << (srv_idx + 4))
375 else:
376 # Signals of SFN Partitions are SPM internal only, does not
377 # need to reserve 4 bits.
378 service['signal_value'] = (1 << srv_idx)
379 if service['connection_based']:
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800380 partition_statistics['connection_based_srv_num'] += 1
Kevin Peng5c3fee72022-02-16 22:25:22 +0800381 logging.debug('{} has {} services'.format(manifest['name'], srv_idx +1))
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800382
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800383 # Calculate the number of mmio region
384 mmio_region_list = manifest.get('mmio_regions', [])
385 partition_statistics['mmio_region_num'] += len(mmio_region_list)
386
Kevin Peng5c3fee72022-02-16 22:25:22 +0800387 # Set initial value to -1 to make (irq + 1) reflect the correct
388 # number (0) when there are no irqs.
389 irq_idx = -1
390 for irq_idx, irq in enumerate(manifest.get('irqs', [])):
391 # Assign signal value, from the most significant bit
392 irq['signal_value'] = (1 << (31 - irq_idx))
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800393 if irq.get('handling', None) == 'FLIH':
394 partition_statistics['flih_num'] += 1
395 else:
396 partition_statistics['slih_num'] += 1
Kevin Peng5c3fee72022-02-16 22:25:22 +0800397 logging.debug('{} has {} IRQS'.format(manifest['name'], irq_idx +1))
398
399 if ((srv_idx + 1) + (irq_idx + 1)) > 28:
400 raise Exception('Total number of Services and IRQs of {} exceeds the limit (28)'
401 .format(manifest['name']))
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800402
Kevin Peng65064c52021-10-27 17:12:17 +0800403 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800404
Kevin Peng4fade072021-10-26 17:57:50 +0800405 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800406 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800407 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800408 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800409
Kevin Peng5bc82d22021-10-19 11:18:40 +0800410 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
411 '{}.h'.format(manifest_out_basename))\
412 .replace('\\', '/')
413 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
414 'intermedia_{}.c'.format(manifest_out_basename))\
415 .replace('\\', '/')
416 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
417 'load_info_{}.c'.format(manifest_out_basename))\
418 .replace('\\', '/')
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800419 output_dir = os.path.join(OUT_DIR, output_path).replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800420
Kevin Peng5bc82d22021-10-19 11:18:40 +0800421 partition_list.append({'manifest': manifest, 'attr': manifest_item,
422 'manifest_out_basename': manifest_out_basename,
423 'header_file': manifest_head_file,
424 'intermedia_file': intermedia_file,
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800425 'loadinfo_file': load_info_file,
426 'output_dir':output_dir})
Ken Liu861b0782021-05-22 13:15:08 +0800427
Chris Brand4b69fcf2022-06-06 09:37:49 -0700428 logging.info("------------ Display partition configuration - end ------------")
429
Xinyu Zhang7d0a5c82022-05-16 18:15:11 +0800430 check_circular_dependency(partition_list, service_partition_map)
431
Kevin Peng56b0ea62021-10-18 11:32:57 +0800432 # Automatically assign PIDs for partitions without 'pid' attribute
Kevin Pengce99e5d2021-11-09 18:06:53 +0800433 pid = max(pid_list, default = TFM_PID_BASE - 1)
Kevin Peng56b0ea62021-10-18 11:32:57 +0800434 for idx in no_pid_manifest_idx:
Kevin Pengc424eec2021-06-25 17:26:11 +0800435 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800436 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800437 pid_list.append(pid)
438
Kevin Peng9f1a7542022-02-07 16:32:27 +0800439 # Set up configurations
Kevin Peng76c0c162022-02-09 22:49:06 +0800440 if backend == 'SFN':
Kevin Peng47c26ec2022-03-11 11:49:52 +0800441 if len(partition_statistics['ipc_partitions']) > 0:
442 logging.error('SFN backend does not support IPC Partitions:')
443 logging.error(partition_statistics['ipc_partitions'])
Kevin Peng9f1a7542022-02-07 16:32:27 +0800444 exit(1)
Kevin Peng76c0c162022-02-09 22:49:06 +0800445
446 if isolation_level > 1:
447 logging.error('SFN backend does not support high isolation levels.')
448 exit(1)
449
Kevin Peng9f1a7542022-02-07 16:32:27 +0800450 config_impl['CONFIG_TFM_SPM_BACKEND_SFN'] = '1'
451 config_impl['CONFIG_TFM_PSA_API_SFN_CALL'] = '1'
Kevin Peng76c0c162022-02-09 22:49:06 +0800452 elif backend == 'IPC':
Kevin Peng9f1a7542022-02-07 16:32:27 +0800453 config_impl['CONFIG_TFM_SPM_BACKEND_IPC'] = '1'
454 if isolation_level > 1:
455 config_impl['CONFIG_TFM_PSA_API_SUPERVISOR_CALL'] = '1'
456 else:
457 config_impl['CONFIG_TFM_PSA_API_CROSS_CALL'] = '1'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800458
459 if partition_statistics['connection_based_srv_num'] > 0:
460 config_impl['CONFIG_TFM_CONNECTION_BASED_SERVICE_API'] = 1
461
Sherry Zhang2ed48fd2022-09-06 11:33:22 +0800462 if partition_statistics['mmio_region_num'] > 0:
463 config_impl['CONFIG_TFM_MMIO_REGION_ENABLE'] = 1
464
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800465 if partition_statistics['flih_num'] > 0:
466 config_impl['CONFIG_TFM_FLIH_API'] = 1
Joakim Anderssoneec5cd32022-06-10 12:02:07 +0200467 if partition_statistics['slih_num'] > 0:
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800468 config_impl['CONFIG_TFM_SLIH_API'] = 1
469
Kevin Peng5bc82d22021-10-19 11:18:40 +0800470 context['partitions'] = partition_list
Kevin Peng9f1a7542022-02-07 16:32:27 +0800471 context['config_impl'] = config_impl
Kevin Pengce99e5d2021-11-09 18:06:53 +0800472 context['stateless_services'] = process_stateless_services(partition_list)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100473
Kevin Peng5bc82d22021-10-19 11:18:40 +0800474 return context
Ken Liu861b0782021-05-22 13:15:08 +0800475
476def gen_per_partition_files(context):
477 """
478 Generate per-partition files
479
480 Parameters
481 ----------
482 context:
483 context contains partition infos
484 """
485
Kevin Peng5bc82d22021-10-19 11:18:40 +0800486 partition_context = {}
Sherry Zhangf58f2bd2022-01-10 17:21:11 +0800487 partition_context['utilities'] = context['utilities']
Sherry Zhangf865c4e2022-03-23 13:53:38 +0800488 partition_context['config_impl'] = context['config_impl']
Ken Liu861b0782021-05-22 13:15:08 +0800489
Kevin Peng5bc82d22021-10-19 11:18:40 +0800490 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
491 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
492 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800493
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500494 logging.info ("Start to generate partition files:")
Ken Liu861b0782021-05-22 13:15:08 +0800495
496 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800497 partition_context['manifest'] = one_partition['manifest']
498 partition_context['attr'] = one_partition['attr']
499 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800500
BohdanHunko6cea95d2022-08-16 15:33:51 +0300501 logging.info ('Generating {} in {}'.format(one_partition['attr']['description'],
Jianliang Shen785ed5e2022-02-08 14:16:06 +0800502 one_partition['output_dir']))
Ken Liu861b0782021-05-22 13:15:08 +0800503 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800504 if not os.path.exists(outfile_path):
505 os.makedirs(outfile_path)
506
Kevin Peng5bc82d22021-10-19 11:18:40 +0800507 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
508 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800509 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800510
Ken Liu861b0782021-05-22 13:15:08 +0800511 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800512 if not os.path.exists(intermediafile_path):
513 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800514 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
515 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800516 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800517
Ken Liu861b0782021-05-22 13:15:08 +0800518 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800519 if not os.path.exists(infofile_path):
520 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800521 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
522 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800523 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800524
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500525 logging.info ("Per-partition files done:")
Mingyang Sunf6a78572021-04-02 16:51:05 +0800526
Ken Liu861b0782021-05-22 13:15:08 +0800527def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800528 """
529 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800530
531 Parameters
532 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100533 gen_file_lists:
534 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800535 """
Kevin Peng655f2392019-11-27 16:33:02 +0800536 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800537
Raef Colesf42f0882020-07-10 10:01:58 +0100538 for f in gen_file_lists:
539 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800540 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800541 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800542
Kevin Peng655f2392019-11-27 16:33:02 +0800543 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000544 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800545 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000546 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800547 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800548
Kevin Peng4fade072021-10-26 17:57:50 +0800549 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800550
Ken Liu861b0782021-05-22 13:15:08 +0800551 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800552 if not os.path.exists(outfile_path):
553 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800554
Kevin Peng655f2392019-11-27 16:33:02 +0800555 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800556
Kevin Peng5bc82d22021-10-19 11:18:40 +0800557 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800558 outfile.write(template.render(context))
559 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800560
Kevin Pengce99e5d2021-11-09 18:06:53 +0800561def process_stateless_services(partitions):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800562 """
563 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800564 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800565 Valid stateless handle in service will be converted to an index. If the
566 stateless handle is set as "auto", or not set, framework will allocate a
567 valid index for the service.
568 Framework puts each service into a reordered stateless service list at
569 position of "index". Other unused positions are left None.
Ken Liu50948382022-10-27 12:45:53 +0800570
571 Keep the variable names start with upper case 'STATIC_HANDLE_' the same
572 as the preprocessors in C sources. This could easier the upcomping
573 modification when developer searches these definitions for modification.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800574 """
Kevin Pengce99e5d2021-11-09 18:06:53 +0800575
Kevin Pengc05319d2021-04-22 22:59:35 +0800576 collected_stateless_services = []
Ken Liu50948382022-10-27 12:45:53 +0800577 STATIC_HANDLE_NUM_LIMIT = 32
Mingyang Suna1ca6112021-01-11 11:34:59 +0800578
579 # Collect all stateless services first.
580 for partition in partitions:
581 # Skip the FF-M 1.0 partitions
582 if partition['manifest']['psa_framework_version'] < 1.1:
583 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800584
585 service_list = partition['manifest'].get('services', [])
586
587 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800588 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800589 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800590
Kevin Pengc05319d2021-04-22 22:59:35 +0800591 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800592 return []
593
Ken Liu50948382022-10-27 12:45:53 +0800594 if len(collected_stateless_services) > STATIC_HANDLE_NUM_LIMIT:
595 raise Exception('Stateless service numbers range exceed {number}.'.format(number=STATIC_HANDLE_NUM_LIMIT))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800596
597 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800598 Allocate an empty stateless service list to store services.
599 Use "handle - 1" as the index for service, since handle value starts from
600 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800601 """
Ken Liu50948382022-10-27 12:45:53 +0800602 reordered_stateless_services = [None] * STATIC_HANDLE_NUM_LIMIT
Kevin Pengc05319d2021-04-22 22:59:35 +0800603 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800604
Kevin Pengc05319d2021-04-22 22:59:35 +0800605 for service in collected_stateless_services:
606 # If not set, it is "auto" by default
607 if 'stateless_handle' not in service:
608 auto_alloc_services.append(service)
609 continue
610
Mingyang Sun4ecea992021-03-30 17:56:26 +0800611 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800612
Mingyang Sun4ecea992021-03-30 17:56:26 +0800613 # Fill in service list with specified stateless handle, otherwise skip
614 if isinstance(service_handle, int):
Ken Liu50948382022-10-27 12:45:53 +0800615 if service_handle < 1 or service_handle > STATIC_HANDLE_NUM_LIMIT:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800616 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800617 # Convert handle index to reordered service list index
618 service_handle = service_handle - 1
619
620 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800621 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800622 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800623 elif service_handle == 'auto':
624 auto_alloc_services.append(service)
625 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800626 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800627
Ken Liu50948382022-10-27 12:45:53 +0800628 STATIC_HANDLE_IDX_BIT_WIDTH = 8
Kevin Pengce99e5d2021-11-09 18:06:53 +0800629 STATIC_HANDLE_IDX_MASK = (1 << STATIC_HANDLE_IDX_BIT_WIDTH) - 1
Ken Liu50948382022-10-27 12:45:53 +0800630 STATIC_HANDLE_INDICATOR_OFFSET = 30
631 STATIC_HANDLE_VER_OFFSET = 8
632 STATIC_HANDLE_VER_BIT_WIDTH = 8
Kevin Pengce99e5d2021-11-09 18:06:53 +0800633 STATIC_HANDLE_VER_MASK = (1 << STATIC_HANDLE_VER_BIT_WIDTH) - 1
634
Mingyang Sun4ecea992021-03-30 17:56:26 +0800635 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu50948382022-10-27 12:45:53 +0800636 for i in range(0, STATIC_HANDLE_NUM_LIMIT):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800637 service = reordered_stateless_services[i]
638
Kevin Pengc05319d2021-04-22 22:59:35 +0800639 if service == None and len(auto_alloc_services) > 0:
640 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800641
Mingyang Sun453ad402021-03-17 17:58:33 +0800642 """
643 Encode stateless flag and version into stateless handle
Mingyang Sun453ad402021-03-17 17:58:33 +0800644 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800645 stateless_handle_value = 0
646 if service != None:
Kevin Pengce99e5d2021-11-09 18:06:53 +0800647 stateless_index = (i & STATIC_HANDLE_IDX_MASK)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800648 stateless_handle_value |= stateless_index
Kevin Pengce99e5d2021-11-09 18:06:53 +0800649 stateless_handle_value |= (1 << STATIC_HANDLE_INDICATOR_OFFSET)
650 stateless_version = (service['version'] & STATIC_HANDLE_VER_MASK) << STATIC_HANDLE_VER_OFFSET
Mingyang Sun453ad402021-03-17 17:58:33 +0800651 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800652 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800653 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800654
Mingyang Sun4ecea992021-03-30 17:56:26 +0800655 reordered_stateless_services[i] = service
656
657 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800658
Kevin Peng655f2392019-11-27 16:33:02 +0800659def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000660 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
661 epilog='Note that environment variables in template files will be replaced with their values')
662
Kevin Peng655f2392019-11-27 16:33:02 +0800663 parser.add_argument('-o', '--outdir'
664 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800665 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800666 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800667 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800668
Kevin Peng5bc82d22021-10-19 11:18:40 +0800669 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100670 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800671 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100672 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800673 , metavar='manifest list'
674 , help='A list of Secure Partition manifest lists and their original paths.\n\
675 The manifest lists might be processed by CMake and\n\
676 the path might be different to the original one\n\
677 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800678
679 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100680 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800681 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100682 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800683 , metavar='file-list'
Chris Brandf1d6b6f2022-07-22 11:49:01 -0700684 , help='These files describe the file list to generate')
Kevin Peng9f1a7542022-02-07 16:32:27 +0800685
Kevin Pengfb1761b2022-05-12 12:11:31 +0800686 parser.add_argument('-c', '--config-files'
687 , nargs='+'
688 , dest='config_files'
Kevin Peng9f1a7542022-02-07 16:32:27 +0800689 , required=True
Kevin Pengfb1761b2022-05-12 12:11:31 +0800690 , metavar='config-files'
691 , help='A header file contains build configurations')
Kevin Peng9f1a7542022-02-07 16:32:27 +0800692
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500693 parser.add_argument('-q', '--quiet'
694 , dest='quiet'
695 , required=False
696 , default=False
697 , action='store_true'
698 , help='Reduce log messages')
Kevin Peng655f2392019-11-27 16:33:02 +0800699
700 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800701
Kevin Peng655f2392019-11-27 16:33:02 +0800702 return args
703
704ENV = Environment(
705 loader = TemplateLoader(),
706 autoescape = select_autoescape(['html', 'xml']),
707 lstrip_blocks = True,
708 trim_blocks = True,
709 keep_trailing_newline = True
710 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100711
Miklos Balint470919c2018-05-22 17:51:29 +0200712def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100713 """
714 The entry point of the script.
715
716 Generates the output files based on the templates and the manifests.
717 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800718
Kevin Peng655f2392019-11-27 16:33:02 +0800719 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800720
Kevin Peng655f2392019-11-27 16:33:02 +0800721 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800722
Jimmy Brisson89d4f8d2021-06-23 10:17:36 -0500723 logging.basicConfig(format='%(message)s'
724 , level=logging.WARNING if args.quiet else logging.INFO)
725
Kevin Peng5bc82d22021-10-19 11:18:40 +0800726 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800727
Kevin Peng5bc82d22021-10-19 11:18:40 +0800728 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
729 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800730
Shawn Shana9ad1e02019-08-07 15:49:48 +0800731 """
Kevin Peng655f2392019-11-27 16:33:02 +0800732 Relative path to TF-M root folder is supported in the manifests
733 and default value of manifest list and generated file list are relative to TF-M root folder as well,
734 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800735 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800736 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 +0800737 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800738 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800739
Kevin Peng76c0c162022-02-09 22:49:06 +0800740 context = process_partition_manifests(manifest_lists,
Kevin Pengfb1761b2022-05-12 12:11:31 +0800741 parse_configurations(args.config_files))
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100742
Edison Ai6e3f2a32019-06-11 15:29:05 +0800743 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800744 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200745
Kevin Peng655f2392019-11-27 16:33:02 +0800746 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800747
Ken Liu861b0782021-05-22 13:15:08 +0800748 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800749 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200750
Kevin Peng5bc82d22021-10-19 11:18:40 +0800751if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200752 main()