blob: cb742c6573ba67a0de3dc6c7b4bca0b0df6580b1 [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
Mingyang Suneab7eae2021-09-30 13:06:52 +0800179 # Count the number of IPC partitions
Kevin Peng5bc82d22021-10-19 11:18:40 +0800180 if manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'IPC':
Mingyang Suneab7eae2021-09-30 13:06:52 +0800181 ipc_partition_num += 1
Kevin Peng5bc82d22021-10-19 11:18:40 +0800182 elif manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'SFN':
Mingyang Suneab7eae2021-09-30 13:06:52 +0800183 sfn_partition_num += 1
Kevin Peng5bc82d22021-10-19 11:18:40 +0800184 elif 'services' in manifest.keys() or 'irqs' in manifest.keys():
185 # This is only to skip Library Model Partitions
Mingyang Suneab7eae2021-09-30 13:06:52 +0800186 ipc_partition_num += 1
187
Kevin Peng65064c52021-10-27 17:12:17 +0800188 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800189
Kevin Peng4fade072021-10-26 17:57:50 +0800190 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800191 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800192 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800193 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800194
Kevin Peng5bc82d22021-10-19 11:18:40 +0800195 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
196 '{}.h'.format(manifest_out_basename))\
197 .replace('\\', '/')
198 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
199 'intermedia_{}.c'.format(manifest_out_basename))\
200 .replace('\\', '/')
201 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
202 'load_info_{}.c'.format(manifest_out_basename))\
203 .replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800204
Kevin Peng5bc82d22021-10-19 11:18:40 +0800205 partition_list.append({'manifest': manifest, 'attr': manifest_item,
206 'manifest_out_basename': manifest_out_basename,
207 'header_file': manifest_head_file,
208 'intermedia_file': intermedia_file,
209 'loadinfo_file': load_info_file})
Ken Liu861b0782021-05-22 13:15:08 +0800210
Kevin Peng56b0ea62021-10-18 11:32:57 +0800211 # Automatically assign PIDs for partitions without 'pid' attribute
212 pid = 256
213 for idx in no_pid_manifest_idx:
214 while pid in pid_list:
215 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800216 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800217 pid_list.append(pid)
218
Kevin Peng5bc82d22021-10-19 11:18:40 +0800219 context['partitions'] = partition_list
220 context['ipc_partition_num'] = ipc_partition_num
221 context['sfn_partition_num'] = sfn_partition_num
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100222
Kevin Peng5bc82d22021-10-19 11:18:40 +0800223 context['stateless_services'] = process_stateless_services(partition_list, 32)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100224
Kevin Peng5bc82d22021-10-19 11:18:40 +0800225 return context
Ken Liu861b0782021-05-22 13:15:08 +0800226
227def gen_per_partition_files(context):
228 """
229 Generate per-partition files
230
231 Parameters
232 ----------
233 context:
234 context contains partition infos
235 """
236
Kevin Peng5bc82d22021-10-19 11:18:40 +0800237 utilities = {}
238 utilities['donotedit_warning'] = donotedit_warning
Ken Liu861b0782021-05-22 13:15:08 +0800239
Kevin Peng5bc82d22021-10-19 11:18:40 +0800240 partition_context = {}
241 partition_context['utilities'] = utilities
Ken Liu861b0782021-05-22 13:15:08 +0800242
Kevin Peng5bc82d22021-10-19 11:18:40 +0800243 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
244 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
245 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800246
Kevin Peng5bc82d22021-10-19 11:18:40 +0800247 print ('Start to generate partition files:')
Ken Liu861b0782021-05-22 13:15:08 +0800248
249 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800250 partition_context['manifest'] = one_partition['manifest']
251 partition_context['attr'] = one_partition['attr']
252 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800253
Kevin Peng5bc82d22021-10-19 11:18:40 +0800254 print ('Generating Header: ' + one_partition['header_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800255 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800256 if not os.path.exists(outfile_path):
257 os.makedirs(outfile_path)
258
Kevin Peng5bc82d22021-10-19 11:18:40 +0800259 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
260 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800261 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800262
Kevin Peng5bc82d22021-10-19 11:18:40 +0800263 print ('Generating Intermedia: ' + one_partition['intermedia_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800264 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800265 if not os.path.exists(intermediafile_path):
266 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800267 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
268 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800269 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800270
Kevin Peng5bc82d22021-10-19 11:18:40 +0800271 print ('Generating Loadinfo: ' + one_partition['loadinfo_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800272 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800273 if not os.path.exists(infofile_path):
274 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800275 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
276 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800277 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800278
Kevin Peng5bc82d22021-10-19 11:18:40 +0800279 print ('Per-partition files done:')
Mingyang Sunf6a78572021-04-02 16:51:05 +0800280
Ken Liu861b0782021-05-22 13:15:08 +0800281def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800282 """
283 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800284
285 Parameters
286 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100287 gen_file_lists:
288 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800289 """
Kevin Peng655f2392019-11-27 16:33:02 +0800290 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800291
Raef Colesf42f0882020-07-10 10:01:58 +0100292 for f in gen_file_lists:
293 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800294 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800295 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800296
Kevin Peng5bc82d22021-10-19 11:18:40 +0800297 print('Start to generate file from the generated list:')
Kevin Peng655f2392019-11-27 16:33:02 +0800298 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000299 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800300 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000301 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800302 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800303
Kevin Peng4fade072021-10-26 17:57:50 +0800304 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800305
Kevin Peng5bc82d22021-10-19 11:18:40 +0800306 print ('Generating ' + manifest_out_file)
edison.ai7b299f52020-07-16 15:44:18 +0800307
Ken Liu861b0782021-05-22 13:15:08 +0800308 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800309 if not os.path.exists(outfile_path):
310 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800311
Kevin Peng655f2392019-11-27 16:33:02 +0800312 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800313
Kevin Peng5bc82d22021-10-19 11:18:40 +0800314 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800315 outfile.write(template.render(context))
316 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800317
Kevin Peng5bc82d22021-10-19 11:18:40 +0800318 print ('Generation of files done')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800319
Ken Liu861b0782021-05-22 13:15:08 +0800320def process_stateless_services(partitions, stateless_index_max_num):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800321 """
322 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800323 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800324 Valid stateless handle in service will be converted to an index. If the
325 stateless handle is set as "auto", or not set, framework will allocate a
326 valid index for the service.
327 Framework puts each service into a reordered stateless service list at
328 position of "index". Other unused positions are left None.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800329 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800330 collected_stateless_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800331
332 # Collect all stateless services first.
333 for partition in partitions:
334 # Skip the FF-M 1.0 partitions
335 if partition['manifest']['psa_framework_version'] < 1.1:
336 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800337
338 service_list = partition['manifest'].get('services', [])
339
340 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800341 if 'connection_based' not in service:
342 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
343 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800344 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800345
Kevin Pengc05319d2021-04-22 22:59:35 +0800346 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800347 return []
348
Ken Liu861b0782021-05-22 13:15:08 +0800349 if len(collected_stateless_services) > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800350 raise Exception('Stateless service numbers range exceed {number}.'.format(number=stateless_index_max_num))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800351
352 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800353 Allocate an empty stateless service list to store services.
354 Use "handle - 1" as the index for service, since handle value starts from
355 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800356 """
Ken Liu861b0782021-05-22 13:15:08 +0800357 reordered_stateless_services = [None] * stateless_index_max_num
Kevin Pengc05319d2021-04-22 22:59:35 +0800358 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800359
Kevin Pengc05319d2021-04-22 22:59:35 +0800360 for service in collected_stateless_services:
361 # If not set, it is "auto" by default
362 if 'stateless_handle' not in service:
363 auto_alloc_services.append(service)
364 continue
365
Mingyang Sun4ecea992021-03-30 17:56:26 +0800366 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800367
Mingyang Sun4ecea992021-03-30 17:56:26 +0800368 # Fill in service list with specified stateless handle, otherwise skip
369 if isinstance(service_handle, int):
Ken Liu861b0782021-05-22 13:15:08 +0800370 if service_handle < 1 or service_handle > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800371 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800372 # Convert handle index to reordered service list index
373 service_handle = service_handle - 1
374
375 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800376 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800377 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800378 elif service_handle == 'auto':
379 auto_alloc_services.append(service)
380 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800381 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800382
383 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu861b0782021-05-22 13:15:08 +0800384 for i in range(0, stateless_index_max_num):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800385 service = reordered_stateless_services[i]
386
Kevin Pengc05319d2021-04-22 22:59:35 +0800387 if service == None and len(auto_alloc_services) > 0:
388 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800389
Mingyang Sun453ad402021-03-17 17:58:33 +0800390 """
391 Encode stateless flag and version into stateless handle
392 bit 30: stateless handle indicator
393 bit 15-8: stateless service version
394 bit 7-0: stateless handle index
395 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800396 stateless_handle_value = 0
397 if service != None:
398 stateless_index = (i & 0xFF)
399 stateless_handle_value |= stateless_index
Mingyang Sun453ad402021-03-17 17:58:33 +0800400 stateless_flag = 1 << 30
401 stateless_handle_value |= stateless_flag
Mingyang Sun4ecea992021-03-30 17:56:26 +0800402 stateless_version = (service['version'] & 0xFF) << 8
Mingyang Sun453ad402021-03-17 17:58:33 +0800403 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800404 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800405 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800406
Mingyang Sun4ecea992021-03-30 17:56:26 +0800407 reordered_stateless_services[i] = service
408
409 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800410
Kevin Peng655f2392019-11-27 16:33:02 +0800411def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000412 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
413 epilog='Note that environment variables in template files will be replaced with their values')
414
Kevin Peng655f2392019-11-27 16:33:02 +0800415 parser.add_argument('-o', '--outdir'
416 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800417 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800418 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800419 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800420
Kevin Peng5bc82d22021-10-19 11:18:40 +0800421 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100422 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800423 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100424 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800425 , metavar='manifest list'
426 , help='A list of Secure Partition manifest lists and their original paths.\n\
427 The manifest lists might be processed by CMake and\n\
428 the path might be different to the original one\n\
429 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800430
431 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100432 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800433 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100434 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800435 , metavar='file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100436 , help='These files descripe the file list to generate')
Kevin Peng655f2392019-11-27 16:33:02 +0800437
438 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800439
Kevin Peng65064c52021-10-27 17:12:17 +0800440 if len(args.manifest_lists) % 2 != 0:
441 print('Invalid structure in manifest lists.\n'
442 'Each element shall consist of a manifest list and its original path')
443 exit(1)
444
Kevin Peng655f2392019-11-27 16:33:02 +0800445 return args
446
447ENV = Environment(
448 loader = TemplateLoader(),
449 autoescape = select_autoescape(['html', 'xml']),
450 lstrip_blocks = True,
451 trim_blocks = True,
452 keep_trailing_newline = True
453 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100454
Miklos Balint470919c2018-05-22 17:51:29 +0200455def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100456 """
457 The entry point of the script.
458
459 Generates the output files based on the templates and the manifests.
460 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800461
Kevin Peng655f2392019-11-27 16:33:02 +0800462 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800463
Kevin Peng655f2392019-11-27 16:33:02 +0800464 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800465
Kevin Peng5bc82d22021-10-19 11:18:40 +0800466 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800467
Kevin Peng5bc82d22021-10-19 11:18:40 +0800468 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
469 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800470
Shawn Shana9ad1e02019-08-07 15:49:48 +0800471 """
Kevin Peng655f2392019-11-27 16:33:02 +0800472 Relative path to TF-M root folder is supported in the manifests
473 and default value of manifest list and generated file list are relative to TF-M root folder as well,
474 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800475 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800476 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 +0800477 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800478 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800479
Kevin Peng65064c52021-10-27 17:12:17 +0800480 context = process_partition_manifests(manifest_lists)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100481
Edison Ai6e3f2a32019-06-11 15:29:05 +0800482 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800483 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200484
Kevin Peng655f2392019-11-27 16:33:02 +0800485 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800486
Ken Liu861b0782021-05-22 13:15:08 +0800487 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800488 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200489
Kevin Peng5bc82d22021-10-19 11:18:40 +0800490if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200491 main()