blob: 3a6bd71442e7905ed85a8a59278ac89e044b2a15 [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.
Miklos Balint470919c2018-05-22 17:51:29 +02003#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8import os
Mate Toth-Pal36f21842018-11-08 16:12:51 +01009import io
Kevin Pengce99e5d2021-11-09 18:06:53 +080010import re
Shawn Shana9ad1e02019-08-07 15:49:48 +080011import sys
12import argparse
Ken Liu1f345b02020-05-30 21:11:05 +080013from jinja2 import Environment, BaseLoader, select_autoescape, TemplateNotFound
Miklos Balint470919c2018-05-22 17:51:29 +020014
15try:
16 import yaml
17except ImportError as e:
Kevin Peng5bc82d22021-10-19 11:18:40 +080018 print (str(e) + ' To install it, type:')
19 print ('pip install PyYAML')
Miklos Balint470919c2018-05-22 17:51:29 +020020 exit(1)
21
Edison Ai48b2d9e2019-06-24 14:39:45 +080022donotedit_warning = \
Sherry Zhangf58f2bd2022-01-10 17:21:11 +080023 ' WARNING: This is an auto-generated file. Do not edit! '
Kevin Peng655f2392019-11-27 16:33:02 +080024
Kevin Pengce99e5d2021-11-09 18:06:53 +080025TFM_ROOT_DIR = os.path.join(sys.path[0], '..')
Kevin Peng655f2392019-11-27 16:33:02 +080026OUT_DIR = None # The root directory that files are generated to
Edison Ai48b2d9e2019-06-24 14:39:45 +080027
Sherry Zhang87e6d2e2021-12-27 14:48:59 +080028# PID[0, TFM_PID_BASE - 1] are reserved for TF-M SPM and test usages
Kevin Pengce99e5d2021-11-09 18:06:53 +080029TFM_PID_BASE = 256
30
Ruiqi Jiang71d361c2021-06-23 17:45:55 +010031# variable for checking for duplicated sid
32sid_list = []
Mate Toth-Pal36f21842018-11-08 16:12:51 +010033class TemplateLoader(BaseLoader):
34 """
35 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020036
Mate Toth-Pal36f21842018-11-08 16:12:51 +010037 An instance of this class is passed to the template engine. It is
38 responsible for reading the template file
39 """
40 def __init__(self):
41 pass
Miklos Balint470919c2018-05-22 17:51:29 +020042
Mate Toth-Pal36f21842018-11-08 16:12:51 +010043 def get_source(self, environment, template):
44 """
45 This function reads the template files.
46 For detailed documentation see:
47 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
48
49 Please note that this function always return 'false' as 'uptodate'
50 value, so the output file will always be generated.
51 """
52 if not os.path.isfile(template):
53 raise TemplateNotFound(template)
54 with open(template) as f:
55 source = f.read()
56 return source, template, False
57
Kevin Pengce99e5d2021-11-09 18:06:53 +080058def get_single_macro_def_from_file(file_name, macro_name):
59 """
60 This function parses the given file_name to get the definition of the given
61 C Macro (macro_name).
62
63 It assumes that the target Macro has no multiple definitions in different
64 build configurations.
65
66 It supports Macros defined in multi-line, for example:
67 #define SOME_MACRO \
68 the_macro_value
69
70 Inputs:
71 - file_name: the file to get the Macro from
72 - macro_name: the name of the Macro to get
73 Returns:
74 - The Macro definition with '()' stripped, or Exception if not found
75 """
76
77 with open(file_name, 'r') as f:
78 pattern = re.compile(r'#define\s+{}[\\\s]+.*'.format(macro_name))
79 result = pattern.findall(f.read())
80
81 if len(result) != 1:
82 raise Exception('{} not defined or has multiple definitions'.format(macro_name))
83
84 macro_def = result[0].split()[-1].strip('()')
85
86 return macro_def
87
Kevin Peng8849b6a2021-11-09 14:17:35 +080088def manifest_validation(partition_manifest, pid):
Mingyang Sun294ce2e2021-06-11 11:58:24 +080089 """
90 This function validates FF-M compliance for partition manifest, and sets
91 default values for optional attributes.
Kevin Pengce99e5d2021-11-09 18:06:53 +080092 The validation is skipped for TF-M specific Partitions (PID < TFM_PID_BASE).
Mingyang Sun294ce2e2021-06-11 11:58:24 +080093 More validation items will be added.
94 """
Kevin Peng5bc82d22021-10-19 11:18:40 +080095
Kevin Peng8849b6a2021-11-09 14:17:35 +080096 service_list = partition_manifest.get('services', [])
97 irq_list = partition_manifest.get('irqs', [])
Mingyang Sun294ce2e2021-06-11 11:58:24 +080098
Kevin Pengce99e5d2021-11-09 18:06:53 +080099 if (pid == None or pid >= TFM_PID_BASE) \
Kevin Peng8849b6a2021-11-09 14:17:35 +0800100 and len(service_list) == 0 and len(irq_list) == 0:
101 raise Exception('{} must declare at least either a secure service or an IRQ!'
102 .format(partition_manifest['name']))
103
104 # Service FF-M manifest validation
105 for service in service_list:
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800106 if 'version' not in service.keys():
107 service['version'] = 1
108 if 'version_policy' not in service.keys():
Kevin Peng5bc82d22021-10-19 11:18:40 +0800109 service['version_policy'] = 'STRICT'
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800110
Kevin Peng5bc82d22021-10-19 11:18:40 +0800111 # SID duplication check
112 if service['sid'] in sid_list:
113 raise Exception('Service ID: {} has duplications!'.format(service['sid']))
114 else:
115 sid_list.append(service['sid'])
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100116
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800117 return partition_manifest
118
Kevin Peng65064c52021-10-27 17:12:17 +0800119def process_partition_manifests(manifest_lists):
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100120 """
Kevin Peng65064c52021-10-27 17:12:17 +0800121 Parse the input manifest lists, generate the data base for genereated files
Kevin Peng655f2392019-11-27 16:33:02 +0800122 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100123
124 Parameters
125 ----------
Kevin Peng65064c52021-10-27 17:12:17 +0800126 manifest_lists:
127 A list of Secure Partition manifest lists and their original paths.
128 The manifest lists might be processed by CMake and the paths might be
129 different to the original ones. Original paths are needed to handle
130 relative paths in the lists.
131 The format must be [list A, orignal path A, list B, orignal path B, ...]
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100132
133 Returns
134 -------
Kevin Peng5bc82d22021-10-19 11:18:40 +0800135 The manifest data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +0800136 """
Kevin Peng655f2392019-11-27 16:33:02 +0800137
Kevin Peng5bc82d22021-10-19 11:18:40 +0800138 context = {}
139
Ken Liu861b0782021-05-22 13:15:08 +0800140 partition_list = []
Kevin Peng65064c52021-10-27 17:12:17 +0800141 all_manifests = []
Kevin Peng56b0ea62021-10-18 11:32:57 +0800142 pid_list = []
143 no_pid_manifest_idx = []
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800144 partition_statistics = {
145 'ipc_partition_num': 0,
146 'sfn_partition_num': 0
147 }
Kevin Peng655f2392019-11-27 16:33:02 +0800148
Kevin Peng65064c52021-10-27 17:12:17 +0800149 # Get all the manifests information as a dictionary
150 for i, item in enumerate(manifest_lists):
151 if i % 2 == 0 and not os.path.isfile(item):
152 print('Manifest list item [{}] must be a file'.format(i))
153 exit(1)
Kevin Peng655f2392019-11-27 16:33:02 +0800154
Kevin Peng65064c52021-10-27 17:12:17 +0800155 if i % 2 == 1:
156 if not os.path.isdir(item):
157 print('Manifest list item [{}] must be a directory'.format(i))
158 exit(1)
David Hub2694202021-07-15 14:58:39 +0800159
Kevin Peng65064c52021-10-27 17:12:17 +0800160 # Skip original manifest paths
161 continue
David Hub2694202021-07-15 14:58:39 +0800162
Kevin Peng65064c52021-10-27 17:12:17 +0800163 # The manifest list file generated by configure_file()
164 with open(item) as manifest_list_yaml_file:
165 manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
166 for dict in manifest_dic:
167 # Add original path of manifest list.
168 # The validation will be done in the next loop.
169 dict['list_path'] = manifest_lists[i + 1]
170 all_manifests.append(dict)
171
172 # Parse the manifests
173 for i, manifest_item in enumerate(all_manifests):
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800174 valid_enabled_conditions = ['on', 'true', 'enabled']
Kevin Peng50f413c2021-11-12 10:31:45 +0800175 valid_disabled_conditions = ['off', 'false', 'disabled', '']
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800176 is_enabled = ''
177
178 if 'conditional' in manifest_item.keys():
Kevin Peng50f413c2021-11-12 10:31:45 +0800179 is_enabled = str(manifest_item['conditional']).lower()
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800180 else:
181 # Partitions without 'conditional' is alwasy on
182 is_enabled = 'on'
183
184 if is_enabled in valid_disabled_conditions:
185 continue
186 elif is_enabled not in valid_enabled_conditions:
187 raise Exception('Invalid "conditional" attribute: "{}" for {}. '
188 'Please set to one of {} or {}, case-insensitive.'\
189 .format(manifest_item['conditional'],
190 manifest_item['name'],
191 valid_enabled_conditions, valid_disabled_conditions))
192
Xinyu Zhangc46ee1f2021-04-01 10:10:43 +0800193 # Check if partition ID is manually set
194 if 'pid' not in manifest_item.keys():
195 no_pid_manifest_idx.append(i)
Kevin Peng8849b6a2021-11-09 14:17:35 +0800196 pid = None
Kevin Peng56b0ea62021-10-18 11:32:57 +0800197 else:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800198 pid = manifest_item['pid']
199
200 # Check if partition ID is duplicated
201 if pid in pid_list:
202 raise Exception('PID No. {pid} has already been used!'.format(pid))
203 else:
204 pid_list.append(pid)
Xinyu Zhang19504a52021-03-31 16:26:20 +0800205
Raef Coles558487a2020-10-29 13:09:44 +0000206 # Replace environment variables in the manifest path
Kevin Peng655f2392019-11-27 16:33:02 +0800207 manifest_path = os.path.expandvars(manifest_item['manifest'])
Kevin Peng65064c52021-10-27 17:12:17 +0800208 # Convert to absolute path. If it's already abspath, the path will not be changed.
209 manifest_path = os.path.join(manifest_item['list_path'], manifest_path).replace('\\', '/')
David Hub2694202021-07-15 14:58:39 +0800210
Kevin Peng5bc82d22021-10-19 11:18:40 +0800211 with open(manifest_path) as manifest_file:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800212 manifest = manifest_validation(yaml.safe_load(manifest_file), pid)
Kevin Peng655f2392019-11-27 16:33:02 +0800213
Kevin Pengce99e5d2021-11-09 18:06:53 +0800214 if pid == None or pid >= TFM_PID_BASE:
Kevin Pengd08f3ba2021-11-18 15:18:56 +0800215 # Count the number of IPC/SFN partitions
216 if manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'SFN':
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800217 partition_statistics['sfn_partition_num'] += 1
Kevin Pengd08f3ba2021-11-18 15:18:56 +0800218 else:
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800219 partition_statistics['ipc_partition_num'] += 1
Mingyang Suneab7eae2021-09-30 13:06:52 +0800220
Kevin Peng65064c52021-10-27 17:12:17 +0800221 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800222
Kevin Peng4fade072021-10-26 17:57:50 +0800223 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800224 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800225 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800226 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800227
Kevin Peng5bc82d22021-10-19 11:18:40 +0800228 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
229 '{}.h'.format(manifest_out_basename))\
230 .replace('\\', '/')
231 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
232 'intermedia_{}.c'.format(manifest_out_basename))\
233 .replace('\\', '/')
234 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
235 'load_info_{}.c'.format(manifest_out_basename))\
236 .replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800237
Kevin Peng5bc82d22021-10-19 11:18:40 +0800238 partition_list.append({'manifest': manifest, 'attr': manifest_item,
239 'manifest_out_basename': manifest_out_basename,
240 'header_file': manifest_head_file,
241 'intermedia_file': intermedia_file,
242 'loadinfo_file': load_info_file})
Ken Liu861b0782021-05-22 13:15:08 +0800243
Kevin Peng56b0ea62021-10-18 11:32:57 +0800244 # Automatically assign PIDs for partitions without 'pid' attribute
Kevin Pengce99e5d2021-11-09 18:06:53 +0800245 pid = max(pid_list, default = TFM_PID_BASE - 1)
Kevin Peng56b0ea62021-10-18 11:32:57 +0800246 for idx in no_pid_manifest_idx:
Kevin Pengc424eec2021-06-25 17:26:11 +0800247 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800248 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800249 pid_list.append(pid)
250
Kevin Peng5bc82d22021-10-19 11:18:40 +0800251 context['partitions'] = partition_list
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800252 context['partition_statistics'] = partition_statistics
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100253
Kevin Pengce99e5d2021-11-09 18:06:53 +0800254 context['stateless_services'] = process_stateless_services(partition_list)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100255
Kevin Peng5bc82d22021-10-19 11:18:40 +0800256 return context
Ken Liu861b0782021-05-22 13:15:08 +0800257
258def gen_per_partition_files(context):
259 """
260 Generate per-partition files
261
262 Parameters
263 ----------
264 context:
265 context contains partition infos
266 """
267
Kevin Peng5bc82d22021-10-19 11:18:40 +0800268 partition_context = {}
Sherry Zhangf58f2bd2022-01-10 17:21:11 +0800269 partition_context['utilities'] = context['utilities']
Ken Liu861b0782021-05-22 13:15:08 +0800270
Kevin Peng5bc82d22021-10-19 11:18:40 +0800271 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
272 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
273 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800274
Kevin Peng5bc82d22021-10-19 11:18:40 +0800275 print ('Start to generate partition files:')
Ken Liu861b0782021-05-22 13:15:08 +0800276
277 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800278 partition_context['manifest'] = one_partition['manifest']
279 partition_context['attr'] = one_partition['attr']
280 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800281
Kevin Peng5bc82d22021-10-19 11:18:40 +0800282 print ('Generating Header: ' + one_partition['header_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800283 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800284 if not os.path.exists(outfile_path):
285 os.makedirs(outfile_path)
286
Kevin Peng5bc82d22021-10-19 11:18:40 +0800287 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
288 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800289 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800290
Kevin Peng5bc82d22021-10-19 11:18:40 +0800291 print ('Generating Intermedia: ' + one_partition['intermedia_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800292 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800293 if not os.path.exists(intermediafile_path):
294 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800295 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
296 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800297 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800298
Kevin Peng5bc82d22021-10-19 11:18:40 +0800299 print ('Generating Loadinfo: ' + one_partition['loadinfo_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800300 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800301 if not os.path.exists(infofile_path):
302 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800303 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
304 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800305 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800306
Kevin Peng5bc82d22021-10-19 11:18:40 +0800307 print ('Per-partition files done:')
Mingyang Sunf6a78572021-04-02 16:51:05 +0800308
Ken Liu861b0782021-05-22 13:15:08 +0800309def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800310 """
311 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800312
313 Parameters
314 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100315 gen_file_lists:
316 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800317 """
Kevin Peng655f2392019-11-27 16:33:02 +0800318 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800319
Raef Colesf42f0882020-07-10 10:01:58 +0100320 for f in gen_file_lists:
321 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800322 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800323 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800324
Kevin Peng5bc82d22021-10-19 11:18:40 +0800325 print('Start to generate file from the generated list:')
Kevin Peng655f2392019-11-27 16:33:02 +0800326 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000327 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800328 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000329 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800330 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800331
Kevin Peng4fade072021-10-26 17:57:50 +0800332 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800333
Kevin Peng5bc82d22021-10-19 11:18:40 +0800334 print ('Generating ' + manifest_out_file)
Ken Liu861b0782021-05-22 13:15:08 +0800335 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800336 if not os.path.exists(outfile_path):
337 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800338
Kevin Peng655f2392019-11-27 16:33:02 +0800339 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800340
Kevin Peng5bc82d22021-10-19 11:18:40 +0800341 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800342 outfile.write(template.render(context))
343 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800344
Kevin Peng5bc82d22021-10-19 11:18:40 +0800345 print ('Generation of files done')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800346
Kevin Pengce99e5d2021-11-09 18:06:53 +0800347def process_stateless_services(partitions):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800348 """
349 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800350 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800351 Valid stateless handle in service will be converted to an index. If the
352 stateless handle is set as "auto", or not set, framework will allocate a
353 valid index for the service.
354 Framework puts each service into a reordered stateless service list at
355 position of "index". Other unused positions are left None.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800356 """
Kevin Pengce99e5d2021-11-09 18:06:53 +0800357
358 STATIC_HANDLE_CONFIG_FILE = 'secure_fw/spm/cmsis_psa/spm_ipc.h'
359
Kevin Pengc05319d2021-04-22 22:59:35 +0800360 collected_stateless_services = []
Kevin Pengce99e5d2021-11-09 18:06:53 +0800361 stateless_index_max_num = \
362 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_NUM_LIMIT'), base = 10)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800363
364 # Collect all stateless services first.
365 for partition in partitions:
366 # Skip the FF-M 1.0 partitions
367 if partition['manifest']['psa_framework_version'] < 1.1:
368 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800369
370 service_list = partition['manifest'].get('services', [])
371
372 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800373 if 'connection_based' not in service:
374 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
375 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800376 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800377
Kevin Pengc05319d2021-04-22 22:59:35 +0800378 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800379 return []
380
Ken Liu861b0782021-05-22 13:15:08 +0800381 if len(collected_stateless_services) > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800382 raise Exception('Stateless service numbers range exceed {number}.'.format(number=stateless_index_max_num))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800383
384 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800385 Allocate an empty stateless service list to store services.
386 Use "handle - 1" as the index for service, since handle value starts from
387 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800388 """
Ken Liu861b0782021-05-22 13:15:08 +0800389 reordered_stateless_services = [None] * stateless_index_max_num
Kevin Pengc05319d2021-04-22 22:59:35 +0800390 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800391
Kevin Pengc05319d2021-04-22 22:59:35 +0800392 for service in collected_stateless_services:
393 # If not set, it is "auto" by default
394 if 'stateless_handle' not in service:
395 auto_alloc_services.append(service)
396 continue
397
Mingyang Sun4ecea992021-03-30 17:56:26 +0800398 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800399
Mingyang Sun4ecea992021-03-30 17:56:26 +0800400 # Fill in service list with specified stateless handle, otherwise skip
401 if isinstance(service_handle, int):
Ken Liu861b0782021-05-22 13:15:08 +0800402 if service_handle < 1 or service_handle > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800403 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800404 # Convert handle index to reordered service list index
405 service_handle = service_handle - 1
406
407 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800408 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800409 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800410 elif service_handle == 'auto':
411 auto_alloc_services.append(service)
412 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800413 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800414
Kevin Pengce99e5d2021-11-09 18:06:53 +0800415 STATIC_HANDLE_IDX_BIT_WIDTH = \
416 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_IDX_BIT_WIDTH'), base = 10)
417 STATIC_HANDLE_IDX_MASK = (1 << STATIC_HANDLE_IDX_BIT_WIDTH) - 1
418
419 STATIC_HANDLE_INDICATOR_OFFSET = \
420 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_INDICATOR_OFFSET'), base = 10)
421
422 STATIC_HANDLE_VER_OFFSET = \
423 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_VER_OFFSET'), base = 10)
424
425 STATIC_HANDLE_VER_BIT_WIDTH = \
426 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_VER_BIT_WIDTH'), base = 10)
427 STATIC_HANDLE_VER_MASK = (1 << STATIC_HANDLE_VER_BIT_WIDTH) - 1
428
Mingyang Sun4ecea992021-03-30 17:56:26 +0800429 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu861b0782021-05-22 13:15:08 +0800430 for i in range(0, stateless_index_max_num):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800431 service = reordered_stateless_services[i]
432
Kevin Pengc05319d2021-04-22 22:59:35 +0800433 if service == None and len(auto_alloc_services) > 0:
434 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800435
Mingyang Sun453ad402021-03-17 17:58:33 +0800436 """
437 Encode stateless flag and version into stateless handle
Kevin Pengce99e5d2021-11-09 18:06:53 +0800438 Check STATIC_HANDLE_CONFIG_FILE for details
Mingyang Sun453ad402021-03-17 17:58:33 +0800439 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800440 stateless_handle_value = 0
441 if service != None:
Kevin Pengce99e5d2021-11-09 18:06:53 +0800442 stateless_index = (i & STATIC_HANDLE_IDX_MASK)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800443 stateless_handle_value |= stateless_index
Kevin Pengce99e5d2021-11-09 18:06:53 +0800444 stateless_handle_value |= (1 << STATIC_HANDLE_INDICATOR_OFFSET)
445 stateless_version = (service['version'] & STATIC_HANDLE_VER_MASK) << STATIC_HANDLE_VER_OFFSET
Mingyang Sun453ad402021-03-17 17:58:33 +0800446 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800447 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800448 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800449
Mingyang Sun4ecea992021-03-30 17:56:26 +0800450 reordered_stateless_services[i] = service
451
452 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800453
Kevin Peng655f2392019-11-27 16:33:02 +0800454def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000455 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
456 epilog='Note that environment variables in template files will be replaced with their values')
457
Kevin Peng655f2392019-11-27 16:33:02 +0800458 parser.add_argument('-o', '--outdir'
459 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800460 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800461 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800462 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800463
Kevin Peng5bc82d22021-10-19 11:18:40 +0800464 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100465 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800466 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100467 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800468 , metavar='manifest list'
469 , help='A list of Secure Partition manifest lists and their original paths.\n\
470 The manifest lists might be processed by CMake and\n\
471 the path might be different to the original one\n\
472 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800473
474 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100475 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800476 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100477 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800478 , metavar='file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100479 , help='These files descripe the file list to generate')
Kevin Peng655f2392019-11-27 16:33:02 +0800480
481 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800482
Kevin Peng65064c52021-10-27 17:12:17 +0800483 if len(args.manifest_lists) % 2 != 0:
484 print('Invalid structure in manifest lists.\n'
485 'Each element shall consist of a manifest list and its original path')
486 exit(1)
487
Kevin Peng655f2392019-11-27 16:33:02 +0800488 return args
489
490ENV = Environment(
491 loader = TemplateLoader(),
492 autoescape = select_autoescape(['html', 'xml']),
493 lstrip_blocks = True,
494 trim_blocks = True,
495 keep_trailing_newline = True
496 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100497
Miklos Balint470919c2018-05-22 17:51:29 +0200498def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100499 """
500 The entry point of the script.
501
502 Generates the output files based on the templates and the manifests.
503 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800504
Kevin Peng655f2392019-11-27 16:33:02 +0800505 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800506
Kevin Peng655f2392019-11-27 16:33:02 +0800507 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800508
Kevin Peng5bc82d22021-10-19 11:18:40 +0800509 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800510
Kevin Peng5bc82d22021-10-19 11:18:40 +0800511 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
512 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800513
Shawn Shana9ad1e02019-08-07 15:49:48 +0800514 """
Kevin Peng655f2392019-11-27 16:33:02 +0800515 Relative path to TF-M root folder is supported in the manifests
516 and default value of manifest list and generated file list are relative to TF-M root folder as well,
517 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800518 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800519 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 +0800520 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800521 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800522
Kevin Peng65064c52021-10-27 17:12:17 +0800523 context = process_partition_manifests(manifest_lists)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100524
Edison Ai6e3f2a32019-06-11 15:29:05 +0800525 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800526 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200527
Kevin Peng655f2392019-11-27 16:33:02 +0800528 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800529
Ken Liu861b0782021-05-22 13:15:08 +0800530 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800531 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200532
Kevin Peng5bc82d22021-10-19 11:18:40 +0800533if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200534 main()