blob: c081c3044b9a4885ec959be6f509aeaced7d85a0 [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
Mingyang Sun294ce2e2021-06-11 11:58:24 +080055def manifest_validation(partition_manifest):
56 """
57 This function validates FF-M compliance for partition manifest, and sets
58 default values for optional attributes.
59 More validation items will be added.
60 """
Kevin Peng5bc82d22021-10-19 11:18:40 +080061
Mingyang Sun294ce2e2021-06-11 11:58:24 +080062 # Service FF-M manifest validation
63 if 'services' not in partition_manifest.keys():
64 return partition_manifest
65
66 for service in partition_manifest['services']:
67 if 'version' not in service.keys():
68 service['version'] = 1
69 if 'version_policy' not in service.keys():
Kevin Peng5bc82d22021-10-19 11:18:40 +080070 service['version_policy'] = 'STRICT'
Mingyang Sun294ce2e2021-06-11 11:58:24 +080071
Kevin Peng5bc82d22021-10-19 11:18:40 +080072 # SID duplication check
73 if service['sid'] in sid_list:
74 raise Exception('Service ID: {} has duplications!'.format(service['sid']))
75 else:
76 sid_list.append(service['sid'])
Ruiqi Jiang71d361c2021-06-23 17:45:55 +010077
Mingyang Sun294ce2e2021-06-11 11:58:24 +080078 return partition_manifest
79
Kevin Peng65064c52021-10-27 17:12:17 +080080def process_partition_manifests(manifest_lists):
Mate Toth-Pal36f21842018-11-08 16:12:51 +010081 """
Kevin Peng65064c52021-10-27 17:12:17 +080082 Parse the input manifest lists, generate the data base for genereated files
Kevin Peng655f2392019-11-27 16:33:02 +080083 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +010084
85 Parameters
86 ----------
Kevin Peng65064c52021-10-27 17:12:17 +080087 manifest_lists:
88 A list of Secure Partition manifest lists and their original paths.
89 The manifest lists might be processed by CMake and the paths might be
90 different to the original ones. Original paths are needed to handle
91 relative paths in the lists.
92 The format must be [list A, orignal path A, list B, orignal path B, ...]
Mate Toth-Pal36f21842018-11-08 16:12:51 +010093
94 Returns
95 -------
Kevin Peng5bc82d22021-10-19 11:18:40 +080096 The manifest data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +080097 """
Kevin Peng655f2392019-11-27 16:33:02 +080098
Kevin Peng5bc82d22021-10-19 11:18:40 +080099 context = {}
100
Ken Liu861b0782021-05-22 13:15:08 +0800101 partition_list = []
Kevin Peng65064c52021-10-27 17:12:17 +0800102 all_manifests = []
Mingyang Suneab7eae2021-09-30 13:06:52 +0800103 ipc_partition_num = 0
104 sfn_partition_num = 0
Kevin Peng56b0ea62021-10-18 11:32:57 +0800105 pid_list = []
106 no_pid_manifest_idx = []
Kevin Peng655f2392019-11-27 16:33:02 +0800107
Kevin Peng65064c52021-10-27 17:12:17 +0800108 # Get all the manifests information as a dictionary
109 for i, item in enumerate(manifest_lists):
110 if i % 2 == 0 and not os.path.isfile(item):
111 print('Manifest list item [{}] must be a file'.format(i))
112 exit(1)
Kevin Peng655f2392019-11-27 16:33:02 +0800113
Kevin Peng65064c52021-10-27 17:12:17 +0800114 if i % 2 == 1:
115 if not os.path.isdir(item):
116 print('Manifest list item [{}] must be a directory'.format(i))
117 exit(1)
David Hub2694202021-07-15 14:58:39 +0800118
Kevin Peng65064c52021-10-27 17:12:17 +0800119 # Skip original manifest paths
120 continue
David Hub2694202021-07-15 14:58:39 +0800121
Kevin Peng65064c52021-10-27 17:12:17 +0800122 # The manifest list file generated by configure_file()
123 with open(item) as manifest_list_yaml_file:
124 manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
125 for dict in manifest_dic:
126 # Add original path of manifest list.
127 # The validation will be done in the next loop.
128 dict['list_path'] = manifest_lists[i + 1]
129 all_manifests.append(dict)
130
131 # Parse the manifests
132 for i, manifest_item in enumerate(all_manifests):
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800133 valid_enabled_conditions = ['on', 'true', 'enabled']
134 valid_disabled_conditions = ['off', 'false', 'disabled']
135 is_enabled = ''
136
137 if 'conditional' in manifest_item.keys():
138 is_enabled = manifest_item['conditional'].lower()
139 else:
140 # Partitions without 'conditional' is alwasy on
141 is_enabled = 'on'
142
143 if is_enabled in valid_disabled_conditions:
144 continue
145 elif is_enabled not in valid_enabled_conditions:
146 raise Exception('Invalid "conditional" attribute: "{}" for {}. '
147 'Please set to one of {} or {}, case-insensitive.'\
148 .format(manifest_item['conditional'],
149 manifest_item['name'],
150 valid_enabled_conditions, valid_disabled_conditions))
151
Xinyu Zhangc46ee1f2021-04-01 10:10:43 +0800152 # Check if partition ID is manually set
153 if 'pid' not in manifest_item.keys():
154 no_pid_manifest_idx.append(i)
Xinyu Zhang19504a52021-03-31 16:26:20 +0800155 # Check if partition ID is duplicated
Kevin Peng56b0ea62021-10-18 11:32:57 +0800156 elif manifest_item['pid'] in pid_list:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800157 raise Exception('PID No. {pid} has already been used!'.format(pid=manifest_item['pid']))
Kevin Peng56b0ea62021-10-18 11:32:57 +0800158 else:
159 pid_list.append(manifest_item['pid'])
Xinyu Zhang19504a52021-03-31 16:26:20 +0800160
Raef Coles558487a2020-10-29 13:09:44 +0000161 # Replace environment variables in the manifest path
Kevin Peng655f2392019-11-27 16:33:02 +0800162 manifest_path = os.path.expandvars(manifest_item['manifest'])
Kevin Peng65064c52021-10-27 17:12:17 +0800163 # Convert to absolute path. If it's already abspath, the path will not be changed.
164 manifest_path = os.path.join(manifest_item['list_path'], manifest_path).replace('\\', '/')
David Hub2694202021-07-15 14:58:39 +0800165
Kevin Peng5bc82d22021-10-19 11:18:40 +0800166 with open(manifest_path) as manifest_file:
167 manifest = manifest_validation(yaml.safe_load(manifest_file))
Kevin Peng655f2392019-11-27 16:33:02 +0800168
Mingyang Suneab7eae2021-09-30 13:06:52 +0800169 # Count the number of IPC partitions
Kevin Peng5bc82d22021-10-19 11:18:40 +0800170 if manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'IPC':
Mingyang Suneab7eae2021-09-30 13:06:52 +0800171 ipc_partition_num += 1
Kevin Peng5bc82d22021-10-19 11:18:40 +0800172 elif manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'SFN':
Mingyang Suneab7eae2021-09-30 13:06:52 +0800173 sfn_partition_num += 1
Kevin Peng5bc82d22021-10-19 11:18:40 +0800174 elif 'services' in manifest.keys() or 'irqs' in manifest.keys():
175 # This is only to skip Library Model Partitions
Mingyang Suneab7eae2021-09-30 13:06:52 +0800176 ipc_partition_num += 1
177
Kevin Peng65064c52021-10-27 17:12:17 +0800178 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800179
Kevin Peng4fade072021-10-26 17:57:50 +0800180 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800181 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800182 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800183 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800184
Kevin Peng5bc82d22021-10-19 11:18:40 +0800185 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
186 '{}.h'.format(manifest_out_basename))\
187 .replace('\\', '/')
188 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
189 'intermedia_{}.c'.format(manifest_out_basename))\
190 .replace('\\', '/')
191 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
192 'load_info_{}.c'.format(manifest_out_basename))\
193 .replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800194
Kevin Peng5bc82d22021-10-19 11:18:40 +0800195 partition_list.append({'manifest': manifest, 'attr': manifest_item,
196 'manifest_out_basename': manifest_out_basename,
197 'header_file': manifest_head_file,
198 'intermedia_file': intermedia_file,
199 'loadinfo_file': load_info_file})
Ken Liu861b0782021-05-22 13:15:08 +0800200
Kevin Peng56b0ea62021-10-18 11:32:57 +0800201 # Automatically assign PIDs for partitions without 'pid' attribute
202 pid = 256
203 for idx in no_pid_manifest_idx:
204 while pid in pid_list:
205 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800206 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800207 pid_list.append(pid)
208
Kevin Peng5bc82d22021-10-19 11:18:40 +0800209 context['partitions'] = partition_list
210 context['ipc_partition_num'] = ipc_partition_num
211 context['sfn_partition_num'] = sfn_partition_num
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100212
Kevin Peng5bc82d22021-10-19 11:18:40 +0800213 context['stateless_services'] = process_stateless_services(partition_list, 32)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100214
Kevin Peng5bc82d22021-10-19 11:18:40 +0800215 return context
Ken Liu861b0782021-05-22 13:15:08 +0800216
217def gen_per_partition_files(context):
218 """
219 Generate per-partition files
220
221 Parameters
222 ----------
223 context:
224 context contains partition infos
225 """
226
Kevin Peng5bc82d22021-10-19 11:18:40 +0800227 utilities = {}
228 utilities['donotedit_warning'] = donotedit_warning
Ken Liu861b0782021-05-22 13:15:08 +0800229
Kevin Peng5bc82d22021-10-19 11:18:40 +0800230 partition_context = {}
231 partition_context['utilities'] = utilities
Ken Liu861b0782021-05-22 13:15:08 +0800232
Kevin Peng5bc82d22021-10-19 11:18:40 +0800233 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
234 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
235 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800236
Kevin Peng5bc82d22021-10-19 11:18:40 +0800237 print ('Start to generate partition files:')
Ken Liu861b0782021-05-22 13:15:08 +0800238
239 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800240 partition_context['manifest'] = one_partition['manifest']
241 partition_context['attr'] = one_partition['attr']
242 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800243
Kevin Peng5bc82d22021-10-19 11:18:40 +0800244 print ('Generating Header: ' + one_partition['header_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800245 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800246 if not os.path.exists(outfile_path):
247 os.makedirs(outfile_path)
248
Kevin Peng5bc82d22021-10-19 11:18:40 +0800249 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
250 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800251 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800252
Kevin Peng5bc82d22021-10-19 11:18:40 +0800253 print ('Generating Intermedia: ' + one_partition['intermedia_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800254 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800255 if not os.path.exists(intermediafile_path):
256 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800257 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
258 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800259 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800260
Kevin Peng5bc82d22021-10-19 11:18:40 +0800261 print ('Generating Loadinfo: ' + one_partition['loadinfo_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800262 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800263 if not os.path.exists(infofile_path):
264 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800265 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
266 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800267 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800268
Kevin Peng5bc82d22021-10-19 11:18:40 +0800269 print ('Per-partition files done:')
Mingyang Sunf6a78572021-04-02 16:51:05 +0800270
Ken Liu861b0782021-05-22 13:15:08 +0800271def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800272 """
273 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800274
275 Parameters
276 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100277 gen_file_lists:
278 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800279 """
Kevin Peng655f2392019-11-27 16:33:02 +0800280 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800281
Raef Colesf42f0882020-07-10 10:01:58 +0100282 for f in gen_file_lists:
283 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800284 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800285 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800286
Kevin Peng5bc82d22021-10-19 11:18:40 +0800287 print('Start to generate file from the generated list:')
Kevin Peng655f2392019-11-27 16:33:02 +0800288 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000289 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800290 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000291 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800292 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800293
Kevin Peng4fade072021-10-26 17:57:50 +0800294 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800295
Kevin Peng5bc82d22021-10-19 11:18:40 +0800296 print ('Generating ' + manifest_out_file)
edison.ai7b299f52020-07-16 15:44:18 +0800297
Ken Liu861b0782021-05-22 13:15:08 +0800298 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800299 if not os.path.exists(outfile_path):
300 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800301
Kevin Peng655f2392019-11-27 16:33:02 +0800302 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800303
Kevin Peng5bc82d22021-10-19 11:18:40 +0800304 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800305 outfile.write(template.render(context))
306 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800307
Kevin Peng5bc82d22021-10-19 11:18:40 +0800308 print ('Generation of files done')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800309
Ken Liu861b0782021-05-22 13:15:08 +0800310def process_stateless_services(partitions, stateless_index_max_num):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800311 """
312 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800313 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800314 Valid stateless handle in service will be converted to an index. If the
315 stateless handle is set as "auto", or not set, framework will allocate a
316 valid index for the service.
317 Framework puts each service into a reordered stateless service list at
318 position of "index". Other unused positions are left None.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800319 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800320 collected_stateless_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800321
322 # Collect all stateless services first.
323 for partition in partitions:
324 # Skip the FF-M 1.0 partitions
325 if partition['manifest']['psa_framework_version'] < 1.1:
326 continue
Mingyang Suna1ca6112021-01-11 11:34:59 +0800327 for service in partition['manifest']['services']:
328 if 'connection_based' not in service:
329 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
330 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800331 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800332
Kevin Pengc05319d2021-04-22 22:59:35 +0800333 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800334 return []
335
Ken Liu861b0782021-05-22 13:15:08 +0800336 if len(collected_stateless_services) > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800337 raise Exception('Stateless service numbers range exceed {number}.'.format(number=stateless_index_max_num))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800338
339 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800340 Allocate an empty stateless service list to store services.
341 Use "handle - 1" as the index for service, since handle value starts from
342 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800343 """
Ken Liu861b0782021-05-22 13:15:08 +0800344 reordered_stateless_services = [None] * stateless_index_max_num
Kevin Pengc05319d2021-04-22 22:59:35 +0800345 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800346
Kevin Pengc05319d2021-04-22 22:59:35 +0800347 for service in collected_stateless_services:
348 # If not set, it is "auto" by default
349 if 'stateless_handle' not in service:
350 auto_alloc_services.append(service)
351 continue
352
Mingyang Sun4ecea992021-03-30 17:56:26 +0800353 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800354
Mingyang Sun4ecea992021-03-30 17:56:26 +0800355 # Fill in service list with specified stateless handle, otherwise skip
356 if isinstance(service_handle, int):
Ken Liu861b0782021-05-22 13:15:08 +0800357 if service_handle < 1 or service_handle > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800358 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800359 # Convert handle index to reordered service list index
360 service_handle = service_handle - 1
361
362 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800363 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800364 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800365 elif service_handle == 'auto':
366 auto_alloc_services.append(service)
367 else:
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
370 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu861b0782021-05-22 13:15:08 +0800371 for i in range(0, stateless_index_max_num):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800372 service = reordered_stateless_services[i]
373
Kevin Pengc05319d2021-04-22 22:59:35 +0800374 if service == None and len(auto_alloc_services) > 0:
375 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800376
Mingyang Sun453ad402021-03-17 17:58:33 +0800377 """
378 Encode stateless flag and version into stateless handle
379 bit 30: stateless handle indicator
380 bit 15-8: stateless service version
381 bit 7-0: stateless handle index
382 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800383 stateless_handle_value = 0
384 if service != None:
385 stateless_index = (i & 0xFF)
386 stateless_handle_value |= stateless_index
Mingyang Sun453ad402021-03-17 17:58:33 +0800387 stateless_flag = 1 << 30
388 stateless_handle_value |= stateless_flag
Mingyang Sun4ecea992021-03-30 17:56:26 +0800389 stateless_version = (service['version'] & 0xFF) << 8
Mingyang Sun453ad402021-03-17 17:58:33 +0800390 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800391 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800392 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800393
Mingyang Sun4ecea992021-03-30 17:56:26 +0800394 reordered_stateless_services[i] = service
395
396 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800397
Kevin Peng655f2392019-11-27 16:33:02 +0800398def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000399 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
400 epilog='Note that environment variables in template files will be replaced with their values')
401
Kevin Peng655f2392019-11-27 16:33:02 +0800402 parser.add_argument('-o', '--outdir'
403 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800404 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800405 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800406 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800407
Kevin Peng5bc82d22021-10-19 11:18:40 +0800408 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100409 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800410 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100411 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800412 , metavar='manifest list'
413 , help='A list of Secure Partition manifest lists and their original paths.\n\
414 The manifest lists might be processed by CMake and\n\
415 the path might be different to the original one\n\
416 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800417
418 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100419 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800420 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100421 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800422 , metavar='file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100423 , help='These files descripe the file list to generate')
Kevin Peng655f2392019-11-27 16:33:02 +0800424
425 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800426
Kevin Peng65064c52021-10-27 17:12:17 +0800427 if len(args.manifest_lists) % 2 != 0:
428 print('Invalid structure in manifest lists.\n'
429 'Each element shall consist of a manifest list and its original path')
430 exit(1)
431
Kevin Peng655f2392019-11-27 16:33:02 +0800432 return args
433
434ENV = Environment(
435 loader = TemplateLoader(),
436 autoescape = select_autoescape(['html', 'xml']),
437 lstrip_blocks = True,
438 trim_blocks = True,
439 keep_trailing_newline = True
440 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100441
Miklos Balint470919c2018-05-22 17:51:29 +0200442def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100443 """
444 The entry point of the script.
445
446 Generates the output files based on the templates and the manifests.
447 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800448
Kevin Peng655f2392019-11-27 16:33:02 +0800449 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800450
Kevin Peng655f2392019-11-27 16:33:02 +0800451 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800452
Kevin Peng5bc82d22021-10-19 11:18:40 +0800453 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800454
Kevin Peng5bc82d22021-10-19 11:18:40 +0800455 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
456 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800457
Shawn Shana9ad1e02019-08-07 15:49:48 +0800458 """
Kevin Peng655f2392019-11-27 16:33:02 +0800459 Relative path to TF-M root folder is supported in the manifests
460 and default value of manifest list and generated file list are relative to TF-M root folder as well,
461 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800462 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800463 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 +0800464 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800465 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800466
Kevin Peng65064c52021-10-27 17:12:17 +0800467 context = process_partition_manifests(manifest_lists)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100468
Edison Ai6e3f2a32019-06-11 15:29:05 +0800469 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800470 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200471
Kevin Peng655f2392019-11-27 16:33:02 +0800472 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800473
Ken Liu861b0782021-05-22 13:15:08 +0800474 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800475 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200476
Kevin Peng5bc82d22021-10-19 11:18:40 +0800477if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200478 main()