blob: 61421655938f59c055cc09be7dca6a5f761c518c [file] [log] [blame]
Miklos Balint470919c2018-05-22 17:51:29 +02001#-------------------------------------------------------------------------------
Kevin Peng578a8492020-12-31 10:22:59 +08002# Copyright (c) 2018-2021, 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
Shawn Shana9ad1e02019-08-07 15:49:48 +080010import sys
11import argparse
Ken Liu1f345b02020-05-30 21:11:05 +080012from jinja2 import Environment, BaseLoader, select_autoescape, TemplateNotFound
Miklos Balint470919c2018-05-22 17:51:29 +020013
14try:
15 import yaml
16except ImportError as e:
Kevin Peng5bc82d22021-10-19 11:18:40 +080017 print (str(e) + ' To install it, type:')
18 print ('pip install PyYAML')
Miklos Balint470919c2018-05-22 17:51:29 +020019 exit(1)
20
Edison Ai48b2d9e2019-06-24 14:39:45 +080021donotedit_warning = \
Kevin Peng5bc82d22021-10-19 11:18:40 +080022 '/*********** ' + \
23 'WARNING: This is an auto-generated file. Do not edit!' + \
24 ' ***********/'
Kevin Peng655f2392019-11-27 16:33:02 +080025
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
Ruiqi Jiang71d361c2021-06-23 17:45:55 +010028# variable for checking for duplicated sid
29sid_list = []
Mate Toth-Pal36f21842018-11-08 16:12:51 +010030class TemplateLoader(BaseLoader):
31 """
32 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020033
Mate Toth-Pal36f21842018-11-08 16:12:51 +010034 An instance of this class is passed to the template engine. It is
35 responsible for reading the template file
36 """
37 def __init__(self):
38 pass
Miklos Balint470919c2018-05-22 17:51:29 +020039
Mate Toth-Pal36f21842018-11-08 16:12:51 +010040 def get_source(self, environment, template):
41 """
42 This function reads the template files.
43 For detailed documentation see:
44 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
45
46 Please note that this function always return 'false' as 'uptodate'
47 value, so the output file will always be generated.
48 """
49 if not os.path.isfile(template):
50 raise TemplateNotFound(template)
51 with open(template) as f:
52 source = f.read()
53 return source, template, False
54
Kevin Peng8849b6a2021-11-09 14:17:35 +080055def manifest_validation(partition_manifest, pid):
Mingyang Sun294ce2e2021-06-11 11:58:24 +080056 """
57 This function validates FF-M compliance for partition manifest, and sets
58 default values for optional attributes.
Kevin Peng8849b6a2021-11-09 14:17:35 +080059 The validation is skipped for TF-M specific Partitions (PID < 256).
Mingyang Sun294ce2e2021-06-11 11:58:24 +080060 More validation items will be added.
61 """
Kevin Peng5bc82d22021-10-19 11:18:40 +080062
Kevin Peng8849b6a2021-11-09 14:17:35 +080063 service_list = partition_manifest.get('services', [])
64 irq_list = partition_manifest.get('irqs', [])
Mingyang Sun294ce2e2021-06-11 11:58:24 +080065
Kevin Peng8849b6a2021-11-09 14:17:35 +080066 if (pid == None or pid >= 256) \
67 and len(service_list) == 0 and len(irq_list) == 0:
68 raise Exception('{} must declare at least either a secure service or an IRQ!'
69 .format(partition_manifest['name']))
70
71 # Service FF-M manifest validation
72 for service in service_list:
Mingyang Sun294ce2e2021-06-11 11:58:24 +080073 if 'version' not in service.keys():
74 service['version'] = 1
75 if 'version_policy' not in service.keys():
Kevin Peng5bc82d22021-10-19 11:18:40 +080076 service['version_policy'] = 'STRICT'
Mingyang Sun294ce2e2021-06-11 11:58:24 +080077
Kevin Peng5bc82d22021-10-19 11:18:40 +080078 # SID duplication check
79 if service['sid'] in sid_list:
80 raise Exception('Service ID: {} has duplications!'.format(service['sid']))
81 else:
82 sid_list.append(service['sid'])
Ruiqi Jiang71d361c2021-06-23 17:45:55 +010083
Mingyang Sun294ce2e2021-06-11 11:58:24 +080084 return partition_manifest
85
Kevin Peng65064c52021-10-27 17:12:17 +080086def process_partition_manifests(manifest_lists):
Mate Toth-Pal36f21842018-11-08 16:12:51 +010087 """
Kevin Peng65064c52021-10-27 17:12:17 +080088 Parse the input manifest lists, generate the data base for genereated files
Kevin Peng655f2392019-11-27 16:33:02 +080089 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +010090
91 Parameters
92 ----------
Kevin Peng65064c52021-10-27 17:12:17 +080093 manifest_lists:
94 A list of Secure Partition manifest lists and their original paths.
95 The manifest lists might be processed by CMake and the paths might be
96 different to the original ones. Original paths are needed to handle
97 relative paths in the lists.
98 The format must be [list A, orignal path A, list B, orignal path B, ...]
Mate Toth-Pal36f21842018-11-08 16:12:51 +010099
100 Returns
101 -------
Kevin Peng5bc82d22021-10-19 11:18:40 +0800102 The manifest data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +0800103 """
Kevin Peng655f2392019-11-27 16:33:02 +0800104
Kevin Peng5bc82d22021-10-19 11:18:40 +0800105 context = {}
106
Ken Liu861b0782021-05-22 13:15:08 +0800107 partition_list = []
Kevin Peng65064c52021-10-27 17:12:17 +0800108 all_manifests = []
Mingyang Suneab7eae2021-09-30 13:06:52 +0800109 ipc_partition_num = 0
110 sfn_partition_num = 0
Kevin Peng56b0ea62021-10-18 11:32:57 +0800111 pid_list = []
112 no_pid_manifest_idx = []
Kevin Peng655f2392019-11-27 16:33:02 +0800113
Kevin Peng65064c52021-10-27 17:12:17 +0800114 # Get all the manifests information as a dictionary
115 for i, item in enumerate(manifest_lists):
116 if i % 2 == 0 and not os.path.isfile(item):
117 print('Manifest list item [{}] must be a file'.format(i))
118 exit(1)
Kevin Peng655f2392019-11-27 16:33:02 +0800119
Kevin Peng65064c52021-10-27 17:12:17 +0800120 if i % 2 == 1:
121 if not os.path.isdir(item):
122 print('Manifest list item [{}] must be a directory'.format(i))
123 exit(1)
David Hub2694202021-07-15 14:58:39 +0800124
Kevin Peng65064c52021-10-27 17:12:17 +0800125 # Skip original manifest paths
126 continue
David Hub2694202021-07-15 14:58:39 +0800127
Kevin Peng65064c52021-10-27 17:12:17 +0800128 # The manifest list file generated by configure_file()
129 with open(item) as manifest_list_yaml_file:
130 manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
131 for dict in manifest_dic:
132 # Add original path of manifest list.
133 # The validation will be done in the next loop.
134 dict['list_path'] = manifest_lists[i + 1]
135 all_manifests.append(dict)
136
137 # Parse the manifests
138 for i, manifest_item in enumerate(all_manifests):
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800139 valid_enabled_conditions = ['on', 'true', 'enabled']
Kevin Peng50f413c2021-11-12 10:31:45 +0800140 valid_disabled_conditions = ['off', 'false', 'disabled', '']
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800141 is_enabled = ''
142
143 if 'conditional' in manifest_item.keys():
Kevin Peng50f413c2021-11-12 10:31:45 +0800144 is_enabled = str(manifest_item['conditional']).lower()
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800145 else:
146 # Partitions without 'conditional' is alwasy on
147 is_enabled = 'on'
148
149 if is_enabled in valid_disabled_conditions:
150 continue
151 elif is_enabled not in valid_enabled_conditions:
152 raise Exception('Invalid "conditional" attribute: "{}" for {}. '
153 'Please set to one of {} or {}, case-insensitive.'\
154 .format(manifest_item['conditional'],
155 manifest_item['name'],
156 valid_enabled_conditions, valid_disabled_conditions))
157
Xinyu Zhangc46ee1f2021-04-01 10:10:43 +0800158 # Check if partition ID is manually set
159 if 'pid' not in manifest_item.keys():
160 no_pid_manifest_idx.append(i)
Kevin Peng8849b6a2021-11-09 14:17:35 +0800161 pid = None
Kevin Peng56b0ea62021-10-18 11:32:57 +0800162 else:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800163 pid = manifest_item['pid']
164
165 # Check if partition ID is duplicated
166 if pid in pid_list:
167 raise Exception('PID No. {pid} has already been used!'.format(pid))
168 else:
169 pid_list.append(pid)
Xinyu Zhang19504a52021-03-31 16:26:20 +0800170
Raef Coles558487a2020-10-29 13:09:44 +0000171 # Replace environment variables in the manifest path
Kevin Peng655f2392019-11-27 16:33:02 +0800172 manifest_path = os.path.expandvars(manifest_item['manifest'])
Kevin Peng65064c52021-10-27 17:12:17 +0800173 # Convert to absolute path. If it's already abspath, the path will not be changed.
174 manifest_path = os.path.join(manifest_item['list_path'], manifest_path).replace('\\', '/')
David Hub2694202021-07-15 14:58:39 +0800175
Kevin Peng5bc82d22021-10-19 11:18:40 +0800176 with open(manifest_path) as manifest_file:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800177 manifest = manifest_validation(yaml.safe_load(manifest_file), pid)
Kevin Peng655f2392019-11-27 16:33:02 +0800178
Kevin Pengd08f3ba2021-11-18 15:18:56 +0800179 if pid == None or pid >= 256:
180 # Count the number of IPC/SFN partitions
181 if manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'SFN':
182 sfn_partition_num += 1
183 else:
184 ipc_partition_num += 1
Mingyang Suneab7eae2021-09-30 13:06:52 +0800185
Kevin Peng65064c52021-10-27 17:12:17 +0800186 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800187
Kevin Peng4fade072021-10-26 17:57:50 +0800188 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800189 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800190 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800191 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800192
Kevin Peng5bc82d22021-10-19 11:18:40 +0800193 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
194 '{}.h'.format(manifest_out_basename))\
195 .replace('\\', '/')
196 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
197 'intermedia_{}.c'.format(manifest_out_basename))\
198 .replace('\\', '/')
199 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
200 'load_info_{}.c'.format(manifest_out_basename))\
201 .replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800202
Kevin Peng5bc82d22021-10-19 11:18:40 +0800203 partition_list.append({'manifest': manifest, 'attr': manifest_item,
204 'manifest_out_basename': manifest_out_basename,
205 'header_file': manifest_head_file,
206 'intermedia_file': intermedia_file,
207 'loadinfo_file': load_info_file})
Ken Liu861b0782021-05-22 13:15:08 +0800208
Kevin Peng56b0ea62021-10-18 11:32:57 +0800209 # Automatically assign PIDs for partitions without 'pid' attribute
Kevin Pengc424eec2021-06-25 17:26:11 +0800210 pid = max(pid_list, default = 256 - 1)
Kevin Peng56b0ea62021-10-18 11:32:57 +0800211 for idx in no_pid_manifest_idx:
Kevin Pengc424eec2021-06-25 17:26:11 +0800212 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800213 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800214 pid_list.append(pid)
215
Kevin Peng5bc82d22021-10-19 11:18:40 +0800216 context['partitions'] = partition_list
217 context['ipc_partition_num'] = ipc_partition_num
218 context['sfn_partition_num'] = sfn_partition_num
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100219
Kevin Peng5bc82d22021-10-19 11:18:40 +0800220 context['stateless_services'] = process_stateless_services(partition_list, 32)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100221
Kevin Peng5bc82d22021-10-19 11:18:40 +0800222 return context
Ken Liu861b0782021-05-22 13:15:08 +0800223
224def gen_per_partition_files(context):
225 """
226 Generate per-partition files
227
228 Parameters
229 ----------
230 context:
231 context contains partition infos
232 """
233
Kevin Peng5bc82d22021-10-19 11:18:40 +0800234 utilities = {}
235 utilities['donotedit_warning'] = donotedit_warning
Ken Liu861b0782021-05-22 13:15:08 +0800236
Kevin Peng5bc82d22021-10-19 11:18:40 +0800237 partition_context = {}
238 partition_context['utilities'] = utilities
Ken Liu861b0782021-05-22 13:15:08 +0800239
Kevin Peng5bc82d22021-10-19 11:18:40 +0800240 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
241 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
242 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800243
Kevin Peng5bc82d22021-10-19 11:18:40 +0800244 print ('Start to generate partition files:')
Ken Liu861b0782021-05-22 13:15:08 +0800245
246 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800247 partition_context['manifest'] = one_partition['manifest']
248 partition_context['attr'] = one_partition['attr']
249 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800250
Kevin Peng5bc82d22021-10-19 11:18:40 +0800251 print ('Generating Header: ' + one_partition['header_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800252 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800253 if not os.path.exists(outfile_path):
254 os.makedirs(outfile_path)
255
Kevin Peng5bc82d22021-10-19 11:18:40 +0800256 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
257 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800258 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800259
Kevin Peng5bc82d22021-10-19 11:18:40 +0800260 print ('Generating Intermedia: ' + one_partition['intermedia_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800261 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800262 if not os.path.exists(intermediafile_path):
263 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800264 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
265 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800266 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800267
Kevin Peng5bc82d22021-10-19 11:18:40 +0800268 print ('Generating Loadinfo: ' + one_partition['loadinfo_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800269 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800270 if not os.path.exists(infofile_path):
271 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800272 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
273 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800274 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800275
Kevin Peng5bc82d22021-10-19 11:18:40 +0800276 print ('Per-partition files done:')
Mingyang Sunf6a78572021-04-02 16:51:05 +0800277
Ken Liu861b0782021-05-22 13:15:08 +0800278def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800279 """
280 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800281
282 Parameters
283 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100284 gen_file_lists:
285 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800286 """
Kevin Peng655f2392019-11-27 16:33:02 +0800287 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800288
Raef Colesf42f0882020-07-10 10:01:58 +0100289 for f in gen_file_lists:
290 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800291 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800292 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800293
Kevin Peng5bc82d22021-10-19 11:18:40 +0800294 print('Start to generate file from the generated list:')
Kevin Peng655f2392019-11-27 16:33:02 +0800295 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000296 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800297 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000298 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800299 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800300
Kevin Peng4fade072021-10-26 17:57:50 +0800301 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800302
Kevin Peng5bc82d22021-10-19 11:18:40 +0800303 print ('Generating ' + manifest_out_file)
edison.ai7b299f52020-07-16 15:44:18 +0800304
Ken Liu861b0782021-05-22 13:15:08 +0800305 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800306 if not os.path.exists(outfile_path):
307 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800308
Kevin Peng655f2392019-11-27 16:33:02 +0800309 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800310
Kevin Peng5bc82d22021-10-19 11:18:40 +0800311 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800312 outfile.write(template.render(context))
313 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800314
Kevin Peng5bc82d22021-10-19 11:18:40 +0800315 print ('Generation of files done')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800316
Ken Liu861b0782021-05-22 13:15:08 +0800317def process_stateless_services(partitions, stateless_index_max_num):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800318 """
319 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800320 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800321 Valid stateless handle in service will be converted to an index. If the
322 stateless handle is set as "auto", or not set, framework will allocate a
323 valid index for the service.
324 Framework puts each service into a reordered stateless service list at
325 position of "index". Other unused positions are left None.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800326 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800327 collected_stateless_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800328
329 # Collect all stateless services first.
330 for partition in partitions:
331 # Skip the FF-M 1.0 partitions
332 if partition['manifest']['psa_framework_version'] < 1.1:
333 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800334
335 service_list = partition['manifest'].get('services', [])
336
337 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800338 if 'connection_based' not in service:
339 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
340 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800341 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800342
Kevin Pengc05319d2021-04-22 22:59:35 +0800343 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800344 return []
345
Ken Liu861b0782021-05-22 13:15:08 +0800346 if len(collected_stateless_services) > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800347 raise Exception('Stateless service numbers range exceed {number}.'.format(number=stateless_index_max_num))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800348
349 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800350 Allocate an empty stateless service list to store services.
351 Use "handle - 1" as the index for service, since handle value starts from
352 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800353 """
Ken Liu861b0782021-05-22 13:15:08 +0800354 reordered_stateless_services = [None] * stateless_index_max_num
Kevin Pengc05319d2021-04-22 22:59:35 +0800355 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800356
Kevin Pengc05319d2021-04-22 22:59:35 +0800357 for service in collected_stateless_services:
358 # If not set, it is "auto" by default
359 if 'stateless_handle' not in service:
360 auto_alloc_services.append(service)
361 continue
362
Mingyang Sun4ecea992021-03-30 17:56:26 +0800363 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800364
Mingyang Sun4ecea992021-03-30 17:56:26 +0800365 # Fill in service list with specified stateless handle, otherwise skip
366 if isinstance(service_handle, int):
Ken Liu861b0782021-05-22 13:15:08 +0800367 if service_handle < 1 or service_handle > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800368 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800369 # Convert handle index to reordered service list index
370 service_handle = service_handle - 1
371
372 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800373 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800374 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800375 elif service_handle == 'auto':
376 auto_alloc_services.append(service)
377 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800378 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800379
380 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu861b0782021-05-22 13:15:08 +0800381 for i in range(0, stateless_index_max_num):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800382 service = reordered_stateless_services[i]
383
Kevin Pengc05319d2021-04-22 22:59:35 +0800384 if service == None and len(auto_alloc_services) > 0:
385 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800386
Mingyang Sun453ad402021-03-17 17:58:33 +0800387 """
388 Encode stateless flag and version into stateless handle
389 bit 30: stateless handle indicator
390 bit 15-8: stateless service version
391 bit 7-0: stateless handle index
392 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800393 stateless_handle_value = 0
394 if service != None:
395 stateless_index = (i & 0xFF)
396 stateless_handle_value |= stateless_index
Mingyang Sun453ad402021-03-17 17:58:33 +0800397 stateless_flag = 1 << 30
398 stateless_handle_value |= stateless_flag
Mingyang Sun4ecea992021-03-30 17:56:26 +0800399 stateless_version = (service['version'] & 0xFF) << 8
Mingyang Sun453ad402021-03-17 17:58:33 +0800400 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800401 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800402 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800403
Mingyang Sun4ecea992021-03-30 17:56:26 +0800404 reordered_stateless_services[i] = service
405
406 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800407
Kevin Peng655f2392019-11-27 16:33:02 +0800408def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000409 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
410 epilog='Note that environment variables in template files will be replaced with their values')
411
Kevin Peng655f2392019-11-27 16:33:02 +0800412 parser.add_argument('-o', '--outdir'
413 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800414 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800415 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800416 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800417
Kevin Peng5bc82d22021-10-19 11:18:40 +0800418 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100419 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800420 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100421 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800422 , metavar='manifest list'
423 , help='A list of Secure Partition manifest lists and their original paths.\n\
424 The manifest lists might be processed by CMake and\n\
425 the path might be different to the original one\n\
426 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800427
428 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100429 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800430 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100431 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800432 , metavar='file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100433 , help='These files descripe the file list to generate')
Kevin Peng655f2392019-11-27 16:33:02 +0800434
435 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800436
Kevin Peng65064c52021-10-27 17:12:17 +0800437 if len(args.manifest_lists) % 2 != 0:
438 print('Invalid structure in manifest lists.\n'
439 'Each element shall consist of a manifest list and its original path')
440 exit(1)
441
Kevin Peng655f2392019-11-27 16:33:02 +0800442 return args
443
444ENV = Environment(
445 loader = TemplateLoader(),
446 autoescape = select_autoescape(['html', 'xml']),
447 lstrip_blocks = True,
448 trim_blocks = True,
449 keep_trailing_newline = True
450 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100451
Miklos Balint470919c2018-05-22 17:51:29 +0200452def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100453 """
454 The entry point of the script.
455
456 Generates the output files based on the templates and the manifests.
457 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800458
Kevin Peng655f2392019-11-27 16:33:02 +0800459 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800460
Kevin Peng655f2392019-11-27 16:33:02 +0800461 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800462
Kevin Peng5bc82d22021-10-19 11:18:40 +0800463 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800464
Kevin Peng5bc82d22021-10-19 11:18:40 +0800465 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
466 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800467
Shawn Shana9ad1e02019-08-07 15:49:48 +0800468 """
Kevin Peng655f2392019-11-27 16:33:02 +0800469 Relative path to TF-M root folder is supported in the manifests
470 and default value of manifest list and generated file list are relative to TF-M root folder as well,
471 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800472 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800473 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 +0800474 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800475 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800476
Kevin Peng65064c52021-10-27 17:12:17 +0800477 context = process_partition_manifests(manifest_lists)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100478
Edison Ai6e3f2a32019-06-11 15:29:05 +0800479 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800480 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200481
Kevin Peng655f2392019-11-27 16:33:02 +0800482 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800483
Ken Liu861b0782021-05-22 13:15:08 +0800484 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800485 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200486
Kevin Peng5bc82d22021-10-19 11:18:40 +0800487if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200488 main()