blob: 3fd8f5c9a11b38ec222b94e4e54af5abdac7f33f [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
210 pid = 256
211 for idx in no_pid_manifest_idx:
212 while pid in pid_list:
213 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800214 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800215 pid_list.append(pid)
216
Kevin Peng5bc82d22021-10-19 11:18:40 +0800217 context['partitions'] = partition_list
218 context['ipc_partition_num'] = ipc_partition_num
219 context['sfn_partition_num'] = sfn_partition_num
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100220
Kevin Peng5bc82d22021-10-19 11:18:40 +0800221 context['stateless_services'] = process_stateless_services(partition_list, 32)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100222
Kevin Peng5bc82d22021-10-19 11:18:40 +0800223 return context
Ken Liu861b0782021-05-22 13:15:08 +0800224
225def gen_per_partition_files(context):
226 """
227 Generate per-partition files
228
229 Parameters
230 ----------
231 context:
232 context contains partition infos
233 """
234
Kevin Peng5bc82d22021-10-19 11:18:40 +0800235 utilities = {}
236 utilities['donotedit_warning'] = donotedit_warning
Ken Liu861b0782021-05-22 13:15:08 +0800237
Kevin Peng5bc82d22021-10-19 11:18:40 +0800238 partition_context = {}
239 partition_context['utilities'] = utilities
Ken Liu861b0782021-05-22 13:15:08 +0800240
Kevin Peng5bc82d22021-10-19 11:18:40 +0800241 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
242 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
243 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800244
Kevin Peng5bc82d22021-10-19 11:18:40 +0800245 print ('Start to generate partition files:')
Ken Liu861b0782021-05-22 13:15:08 +0800246
247 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800248 partition_context['manifest'] = one_partition['manifest']
249 partition_context['attr'] = one_partition['attr']
250 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800251
Kevin Peng5bc82d22021-10-19 11:18:40 +0800252 print ('Generating Header: ' + one_partition['header_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800253 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800254 if not os.path.exists(outfile_path):
255 os.makedirs(outfile_path)
256
Kevin Peng5bc82d22021-10-19 11:18:40 +0800257 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
258 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800259 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800260
Kevin Peng5bc82d22021-10-19 11:18:40 +0800261 print ('Generating Intermedia: ' + one_partition['intermedia_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800262 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800263 if not os.path.exists(intermediafile_path):
264 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800265 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
266 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800267 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800268
Kevin Peng5bc82d22021-10-19 11:18:40 +0800269 print ('Generating Loadinfo: ' + one_partition['loadinfo_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800270 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800271 if not os.path.exists(infofile_path):
272 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800273 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
274 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800275 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800276
Kevin Peng5bc82d22021-10-19 11:18:40 +0800277 print ('Per-partition files done:')
Mingyang Sunf6a78572021-04-02 16:51:05 +0800278
Ken Liu861b0782021-05-22 13:15:08 +0800279def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800280 """
281 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800282
283 Parameters
284 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100285 gen_file_lists:
286 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800287 """
Kevin Peng655f2392019-11-27 16:33:02 +0800288 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800289
Raef Colesf42f0882020-07-10 10:01:58 +0100290 for f in gen_file_lists:
291 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800292 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800293 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800294
Kevin Peng5bc82d22021-10-19 11:18:40 +0800295 print('Start to generate file from the generated list:')
Kevin Peng655f2392019-11-27 16:33:02 +0800296 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000297 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800298 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000299 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800300 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800301
Kevin Peng4fade072021-10-26 17:57:50 +0800302 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800303
Kevin Peng5bc82d22021-10-19 11:18:40 +0800304 print ('Generating ' + manifest_out_file)
edison.ai7b299f52020-07-16 15:44:18 +0800305
Ken Liu861b0782021-05-22 13:15:08 +0800306 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800307 if not os.path.exists(outfile_path):
308 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800309
Kevin Peng655f2392019-11-27 16:33:02 +0800310 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800311
Kevin Peng5bc82d22021-10-19 11:18:40 +0800312 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800313 outfile.write(template.render(context))
314 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800315
Kevin Peng5bc82d22021-10-19 11:18:40 +0800316 print ('Generation of files done')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800317
Ken Liu861b0782021-05-22 13:15:08 +0800318def process_stateless_services(partitions, stateless_index_max_num):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800319 """
320 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800321 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800322 Valid stateless handle in service will be converted to an index. If the
323 stateless handle is set as "auto", or not set, framework will allocate a
324 valid index for the service.
325 Framework puts each service into a reordered stateless service list at
326 position of "index". Other unused positions are left None.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800327 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800328 collected_stateless_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800329
330 # Collect all stateless services first.
331 for partition in partitions:
332 # Skip the FF-M 1.0 partitions
333 if partition['manifest']['psa_framework_version'] < 1.1:
334 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800335
336 service_list = partition['manifest'].get('services', [])
337
338 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800339 if 'connection_based' not in service:
340 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
341 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800342 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800343
Kevin Pengc05319d2021-04-22 22:59:35 +0800344 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800345 return []
346
Ken Liu861b0782021-05-22 13:15:08 +0800347 if len(collected_stateless_services) > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800348 raise Exception('Stateless service numbers range exceed {number}.'.format(number=stateless_index_max_num))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800349
350 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800351 Allocate an empty stateless service list to store services.
352 Use "handle - 1" as the index for service, since handle value starts from
353 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800354 """
Ken Liu861b0782021-05-22 13:15:08 +0800355 reordered_stateless_services = [None] * stateless_index_max_num
Kevin Pengc05319d2021-04-22 22:59:35 +0800356 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800357
Kevin Pengc05319d2021-04-22 22:59:35 +0800358 for service in collected_stateless_services:
359 # If not set, it is "auto" by default
360 if 'stateless_handle' not in service:
361 auto_alloc_services.append(service)
362 continue
363
Mingyang Sun4ecea992021-03-30 17:56:26 +0800364 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800365
Mingyang Sun4ecea992021-03-30 17:56:26 +0800366 # Fill in service list with specified stateless handle, otherwise skip
367 if isinstance(service_handle, int):
Ken Liu861b0782021-05-22 13:15:08 +0800368 if service_handle < 1 or service_handle > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800369 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800370 # Convert handle index to reordered service list index
371 service_handle = service_handle - 1
372
373 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800374 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800375 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800376 elif service_handle == 'auto':
377 auto_alloc_services.append(service)
378 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800379 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800380
381 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu861b0782021-05-22 13:15:08 +0800382 for i in range(0, stateless_index_max_num):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800383 service = reordered_stateless_services[i]
384
Kevin Pengc05319d2021-04-22 22:59:35 +0800385 if service == None and len(auto_alloc_services) > 0:
386 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800387
Mingyang Sun453ad402021-03-17 17:58:33 +0800388 """
389 Encode stateless flag and version into stateless handle
390 bit 30: stateless handle indicator
391 bit 15-8: stateless service version
392 bit 7-0: stateless handle index
393 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800394 stateless_handle_value = 0
395 if service != None:
396 stateless_index = (i & 0xFF)
397 stateless_handle_value |= stateless_index
Mingyang Sun453ad402021-03-17 17:58:33 +0800398 stateless_flag = 1 << 30
399 stateless_handle_value |= stateless_flag
Mingyang Sun4ecea992021-03-30 17:56:26 +0800400 stateless_version = (service['version'] & 0xFF) << 8
Mingyang Sun453ad402021-03-17 17:58:33 +0800401 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800402 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800403 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800404
Mingyang Sun4ecea992021-03-30 17:56:26 +0800405 reordered_stateless_services[i] = service
406
407 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800408
Kevin Peng655f2392019-11-27 16:33:02 +0800409def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000410 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
411 epilog='Note that environment variables in template files will be replaced with their values')
412
Kevin Peng655f2392019-11-27 16:33:02 +0800413 parser.add_argument('-o', '--outdir'
414 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800415 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800416 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800417 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800418
Kevin Peng5bc82d22021-10-19 11:18:40 +0800419 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100420 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800421 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100422 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800423 , metavar='manifest list'
424 , help='A list of Secure Partition manifest lists and their original paths.\n\
425 The manifest lists might be processed by CMake and\n\
426 the path might be different to the original one\n\
427 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800428
429 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100430 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800431 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100432 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800433 , metavar='file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100434 , help='These files descripe the file list to generate')
Kevin Peng655f2392019-11-27 16:33:02 +0800435
436 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800437
Kevin Peng65064c52021-10-27 17:12:17 +0800438 if len(args.manifest_lists) % 2 != 0:
439 print('Invalid structure in manifest lists.\n'
440 'Each element shall consist of a manifest list and its original path')
441 exit(1)
442
Kevin Peng655f2392019-11-27 16:33:02 +0800443 return args
444
445ENV = Environment(
446 loader = TemplateLoader(),
447 autoescape = select_autoescape(['html', 'xml']),
448 lstrip_blocks = True,
449 trim_blocks = True,
450 keep_trailing_newline = True
451 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100452
Miklos Balint470919c2018-05-22 17:51:29 +0200453def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100454 """
455 The entry point of the script.
456
457 Generates the output files based on the templates and the manifests.
458 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800459
Kevin Peng655f2392019-11-27 16:33:02 +0800460 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800461
Kevin Peng655f2392019-11-27 16:33:02 +0800462 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800463
Kevin Peng5bc82d22021-10-19 11:18:40 +0800464 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800465
Kevin Peng5bc82d22021-10-19 11:18:40 +0800466 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
467 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800468
Shawn Shana9ad1e02019-08-07 15:49:48 +0800469 """
Kevin Peng655f2392019-11-27 16:33:02 +0800470 Relative path to TF-M root folder is supported in the manifests
471 and default value of manifest list and generated file list are relative to TF-M root folder as well,
472 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800473 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800474 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 +0800475 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800476 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800477
Kevin Peng65064c52021-10-27 17:12:17 +0800478 context = process_partition_manifests(manifest_lists)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100479
Edison Ai6e3f2a32019-06-11 15:29:05 +0800480 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800481 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200482
Kevin Peng655f2392019-11-27 16:33:02 +0800483 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800484
Ken Liu861b0782021-05-22 13:15:08 +0800485 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800486 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200487
Kevin Peng5bc82d22021-10-19 11:18:40 +0800488if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200489 main()