blob: 8b7afa1c53c36b568b7d2c89be65be9c838d97c3 [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
Kevin Pengce99e5d2021-11-09 18:06:53 +080010import re
Shawn Shana9ad1e02019-08-07 15:49:48 +080011import sys
12import argparse
Ken Liu1f345b02020-05-30 21:11:05 +080013from jinja2 import Environment, BaseLoader, select_autoescape, TemplateNotFound
Miklos Balint470919c2018-05-22 17:51:29 +020014
15try:
16 import yaml
17except ImportError as e:
Kevin Peng5bc82d22021-10-19 11:18:40 +080018 print (str(e) + ' To install it, type:')
19 print ('pip install PyYAML')
Miklos Balint470919c2018-05-22 17:51:29 +020020 exit(1)
21
Edison Ai48b2d9e2019-06-24 14:39:45 +080022donotedit_warning = \
Kevin Peng5bc82d22021-10-19 11:18:40 +080023 '/*********** ' + \
24 'WARNING: This is an auto-generated file. Do not edit!' + \
25 ' ***********/'
Kevin Peng655f2392019-11-27 16:33:02 +080026
Kevin Pengce99e5d2021-11-09 18:06:53 +080027TFM_ROOT_DIR = os.path.join(sys.path[0], '..')
Kevin Peng655f2392019-11-27 16:33:02 +080028OUT_DIR = None # The root directory that files are generated to
Edison Ai48b2d9e2019-06-24 14:39:45 +080029
Sherry Zhang87e6d2e2021-12-27 14:48:59 +080030# PID[0, TFM_PID_BASE - 1] are reserved for TF-M SPM and test usages
Kevin Pengce99e5d2021-11-09 18:06:53 +080031TFM_PID_BASE = 256
32
Ruiqi Jiang71d361c2021-06-23 17:45:55 +010033# variable for checking for duplicated sid
34sid_list = []
Mate Toth-Pal36f21842018-11-08 16:12:51 +010035class TemplateLoader(BaseLoader):
36 """
37 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020038
Mate Toth-Pal36f21842018-11-08 16:12:51 +010039 An instance of this class is passed to the template engine. It is
40 responsible for reading the template file
41 """
42 def __init__(self):
43 pass
Miklos Balint470919c2018-05-22 17:51:29 +020044
Mate Toth-Pal36f21842018-11-08 16:12:51 +010045 def get_source(self, environment, template):
46 """
47 This function reads the template files.
48 For detailed documentation see:
49 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
50
51 Please note that this function always return 'false' as 'uptodate'
52 value, so the output file will always be generated.
53 """
54 if not os.path.isfile(template):
55 raise TemplateNotFound(template)
56 with open(template) as f:
57 source = f.read()
58 return source, template, False
59
Kevin Pengce99e5d2021-11-09 18:06:53 +080060def get_single_macro_def_from_file(file_name, macro_name):
61 """
62 This function parses the given file_name to get the definition of the given
63 C Macro (macro_name).
64
65 It assumes that the target Macro has no multiple definitions in different
66 build configurations.
67
68 It supports Macros defined in multi-line, for example:
69 #define SOME_MACRO \
70 the_macro_value
71
72 Inputs:
73 - file_name: the file to get the Macro from
74 - macro_name: the name of the Macro to get
75 Returns:
76 - The Macro definition with '()' stripped, or Exception if not found
77 """
78
79 with open(file_name, 'r') as f:
80 pattern = re.compile(r'#define\s+{}[\\\s]+.*'.format(macro_name))
81 result = pattern.findall(f.read())
82
83 if len(result) != 1:
84 raise Exception('{} not defined or has multiple definitions'.format(macro_name))
85
86 macro_def = result[0].split()[-1].strip('()')
87
88 return macro_def
89
Kevin Peng8849b6a2021-11-09 14:17:35 +080090def manifest_validation(partition_manifest, pid):
Mingyang Sun294ce2e2021-06-11 11:58:24 +080091 """
92 This function validates FF-M compliance for partition manifest, and sets
93 default values for optional attributes.
Kevin Pengce99e5d2021-11-09 18:06:53 +080094 The validation is skipped for TF-M specific Partitions (PID < TFM_PID_BASE).
Mingyang Sun294ce2e2021-06-11 11:58:24 +080095 More validation items will be added.
96 """
Kevin Peng5bc82d22021-10-19 11:18:40 +080097
Kevin Peng8849b6a2021-11-09 14:17:35 +080098 service_list = partition_manifest.get('services', [])
99 irq_list = partition_manifest.get('irqs', [])
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800100
Kevin Pengce99e5d2021-11-09 18:06:53 +0800101 if (pid == None or pid >= TFM_PID_BASE) \
Kevin Peng8849b6a2021-11-09 14:17:35 +0800102 and len(service_list) == 0 and len(irq_list) == 0:
103 raise Exception('{} must declare at least either a secure service or an IRQ!'
104 .format(partition_manifest['name']))
105
106 # Service FF-M manifest validation
107 for service in service_list:
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800108 if 'version' not in service.keys():
109 service['version'] = 1
110 if 'version_policy' not in service.keys():
Kevin Peng5bc82d22021-10-19 11:18:40 +0800111 service['version_policy'] = 'STRICT'
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800112
Kevin Peng5bc82d22021-10-19 11:18:40 +0800113 # SID duplication check
114 if service['sid'] in sid_list:
115 raise Exception('Service ID: {} has duplications!'.format(service['sid']))
116 else:
117 sid_list.append(service['sid'])
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100118
Mingyang Sun294ce2e2021-06-11 11:58:24 +0800119 return partition_manifest
120
Kevin Peng65064c52021-10-27 17:12:17 +0800121def process_partition_manifests(manifest_lists):
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100122 """
Kevin Peng65064c52021-10-27 17:12:17 +0800123 Parse the input manifest lists, generate the data base for genereated files
Kevin Peng655f2392019-11-27 16:33:02 +0800124 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100125
126 Parameters
127 ----------
Kevin Peng65064c52021-10-27 17:12:17 +0800128 manifest_lists:
129 A list of Secure Partition manifest lists and their original paths.
130 The manifest lists might be processed by CMake and the paths might be
131 different to the original ones. Original paths are needed to handle
132 relative paths in the lists.
133 The format must be [list A, orignal path A, list B, orignal path B, ...]
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100134
135 Returns
136 -------
Kevin Peng5bc82d22021-10-19 11:18:40 +0800137 The manifest data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +0800138 """
Kevin Peng655f2392019-11-27 16:33:02 +0800139
Kevin Peng5bc82d22021-10-19 11:18:40 +0800140 context = {}
141
Ken Liu861b0782021-05-22 13:15:08 +0800142 partition_list = []
Kevin Peng65064c52021-10-27 17:12:17 +0800143 all_manifests = []
Mingyang Suneab7eae2021-09-30 13:06:52 +0800144 ipc_partition_num = 0
145 sfn_partition_num = 0
Kevin Peng56b0ea62021-10-18 11:32:57 +0800146 pid_list = []
147 no_pid_manifest_idx = []
Kevin Peng655f2392019-11-27 16:33:02 +0800148
Kevin Peng65064c52021-10-27 17:12:17 +0800149 # Get all the manifests information as a dictionary
150 for i, item in enumerate(manifest_lists):
151 if i % 2 == 0 and not os.path.isfile(item):
152 print('Manifest list item [{}] must be a file'.format(i))
153 exit(1)
Kevin Peng655f2392019-11-27 16:33:02 +0800154
Kevin Peng65064c52021-10-27 17:12:17 +0800155 if i % 2 == 1:
156 if not os.path.isdir(item):
157 print('Manifest list item [{}] must be a directory'.format(i))
158 exit(1)
David Hub2694202021-07-15 14:58:39 +0800159
Kevin Peng65064c52021-10-27 17:12:17 +0800160 # Skip original manifest paths
161 continue
David Hub2694202021-07-15 14:58:39 +0800162
Kevin Peng65064c52021-10-27 17:12:17 +0800163 # The manifest list file generated by configure_file()
164 with open(item) as manifest_list_yaml_file:
165 manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
166 for dict in manifest_dic:
167 # Add original path of manifest list.
168 # The validation will be done in the next loop.
169 dict['list_path'] = manifest_lists[i + 1]
170 all_manifests.append(dict)
171
172 # Parse the manifests
173 for i, manifest_item in enumerate(all_manifests):
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800174 valid_enabled_conditions = ['on', 'true', 'enabled']
Kevin Peng50f413c2021-11-12 10:31:45 +0800175 valid_disabled_conditions = ['off', 'false', 'disabled', '']
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800176 is_enabled = ''
177
178 if 'conditional' in manifest_item.keys():
Kevin Peng50f413c2021-11-12 10:31:45 +0800179 is_enabled = str(manifest_item['conditional']).lower()
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800180 else:
181 # Partitions without 'conditional' is alwasy on
182 is_enabled = 'on'
183
184 if is_enabled in valid_disabled_conditions:
185 continue
186 elif is_enabled not in valid_enabled_conditions:
187 raise Exception('Invalid "conditional" attribute: "{}" for {}. '
188 'Please set to one of {} or {}, case-insensitive.'\
189 .format(manifest_item['conditional'],
190 manifest_item['name'],
191 valid_enabled_conditions, valid_disabled_conditions))
192
Xinyu Zhangc46ee1f2021-04-01 10:10:43 +0800193 # Check if partition ID is manually set
194 if 'pid' not in manifest_item.keys():
195 no_pid_manifest_idx.append(i)
Kevin Peng8849b6a2021-11-09 14:17:35 +0800196 pid = None
Kevin Peng56b0ea62021-10-18 11:32:57 +0800197 else:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800198 pid = manifest_item['pid']
199
200 # Check if partition ID is duplicated
201 if pid in pid_list:
202 raise Exception('PID No. {pid} has already been used!'.format(pid))
203 else:
204 pid_list.append(pid)
Xinyu Zhang19504a52021-03-31 16:26:20 +0800205
Raef Coles558487a2020-10-29 13:09:44 +0000206 # Replace environment variables in the manifest path
Kevin Peng655f2392019-11-27 16:33:02 +0800207 manifest_path = os.path.expandvars(manifest_item['manifest'])
Kevin Peng65064c52021-10-27 17:12:17 +0800208 # Convert to absolute path. If it's already abspath, the path will not be changed.
209 manifest_path = os.path.join(manifest_item['list_path'], manifest_path).replace('\\', '/')
David Hub2694202021-07-15 14:58:39 +0800210
Kevin Peng5bc82d22021-10-19 11:18:40 +0800211 with open(manifest_path) as manifest_file:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800212 manifest = manifest_validation(yaml.safe_load(manifest_file), pid)
Kevin Peng655f2392019-11-27 16:33:02 +0800213
Kevin Pengce99e5d2021-11-09 18:06:53 +0800214 if pid == None or pid >= TFM_PID_BASE:
Kevin Pengd08f3ba2021-11-18 15:18:56 +0800215 # Count the number of IPC/SFN partitions
216 if manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'SFN':
217 sfn_partition_num += 1
218 else:
219 ipc_partition_num += 1
Mingyang Suneab7eae2021-09-30 13:06:52 +0800220
Kevin Peng65064c52021-10-27 17:12:17 +0800221 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800222
Kevin Peng4fade072021-10-26 17:57:50 +0800223 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800224 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800225 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800226 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800227
Kevin Peng5bc82d22021-10-19 11:18:40 +0800228 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
229 '{}.h'.format(manifest_out_basename))\
230 .replace('\\', '/')
231 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
232 'intermedia_{}.c'.format(manifest_out_basename))\
233 .replace('\\', '/')
234 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
235 'load_info_{}.c'.format(manifest_out_basename))\
236 .replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800237
Kevin Peng5bc82d22021-10-19 11:18:40 +0800238 partition_list.append({'manifest': manifest, 'attr': manifest_item,
239 'manifest_out_basename': manifest_out_basename,
240 'header_file': manifest_head_file,
241 'intermedia_file': intermedia_file,
242 'loadinfo_file': load_info_file})
Ken Liu861b0782021-05-22 13:15:08 +0800243
Kevin Peng56b0ea62021-10-18 11:32:57 +0800244 # Automatically assign PIDs for partitions without 'pid' attribute
Kevin Pengce99e5d2021-11-09 18:06:53 +0800245 pid = max(pid_list, default = TFM_PID_BASE - 1)
Kevin Peng56b0ea62021-10-18 11:32:57 +0800246 for idx in no_pid_manifest_idx:
Kevin Pengc424eec2021-06-25 17:26:11 +0800247 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800248 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800249 pid_list.append(pid)
250
Kevin Peng5bc82d22021-10-19 11:18:40 +0800251 context['partitions'] = partition_list
252 context['ipc_partition_num'] = ipc_partition_num
253 context['sfn_partition_num'] = sfn_partition_num
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100254
Kevin Pengce99e5d2021-11-09 18:06:53 +0800255 context['stateless_services'] = process_stateless_services(partition_list)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100256
Kevin Peng5bc82d22021-10-19 11:18:40 +0800257 return context
Ken Liu861b0782021-05-22 13:15:08 +0800258
259def gen_per_partition_files(context):
260 """
261 Generate per-partition files
262
263 Parameters
264 ----------
265 context:
266 context contains partition infos
267 """
268
Kevin Peng5bc82d22021-10-19 11:18:40 +0800269 utilities = {}
270 utilities['donotedit_warning'] = donotedit_warning
Ken Liu861b0782021-05-22 13:15:08 +0800271
Kevin Peng5bc82d22021-10-19 11:18:40 +0800272 partition_context = {}
273 partition_context['utilities'] = utilities
Ken Liu861b0782021-05-22 13:15:08 +0800274
Kevin Peng5bc82d22021-10-19 11:18:40 +0800275 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
276 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
277 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800278
Kevin Peng5bc82d22021-10-19 11:18:40 +0800279 print ('Start to generate partition files:')
Ken Liu861b0782021-05-22 13:15:08 +0800280
281 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800282 partition_context['manifest'] = one_partition['manifest']
283 partition_context['attr'] = one_partition['attr']
284 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800285
Kevin Peng5bc82d22021-10-19 11:18:40 +0800286 print ('Generating Header: ' + one_partition['header_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800287 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800288 if not os.path.exists(outfile_path):
289 os.makedirs(outfile_path)
290
Kevin Peng5bc82d22021-10-19 11:18:40 +0800291 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
292 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800293 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800294
Kevin Peng5bc82d22021-10-19 11:18:40 +0800295 print ('Generating Intermedia: ' + one_partition['intermedia_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800296 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800297 if not os.path.exists(intermediafile_path):
298 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800299 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
300 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800301 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800302
Kevin Peng5bc82d22021-10-19 11:18:40 +0800303 print ('Generating Loadinfo: ' + one_partition['loadinfo_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800304 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800305 if not os.path.exists(infofile_path):
306 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800307 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
308 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800309 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800310
Kevin Peng5bc82d22021-10-19 11:18:40 +0800311 print ('Per-partition files done:')
Mingyang Sunf6a78572021-04-02 16:51:05 +0800312
Ken Liu861b0782021-05-22 13:15:08 +0800313def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800314 """
315 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800316
317 Parameters
318 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100319 gen_file_lists:
320 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800321 """
Kevin Peng655f2392019-11-27 16:33:02 +0800322 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800323
Raef Colesf42f0882020-07-10 10:01:58 +0100324 for f in gen_file_lists:
325 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800326 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800327 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800328
Kevin Peng5bc82d22021-10-19 11:18:40 +0800329 print('Start to generate file from the generated list:')
Kevin Peng655f2392019-11-27 16:33:02 +0800330 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000331 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800332 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000333 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800334 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800335
Kevin Peng4fade072021-10-26 17:57:50 +0800336 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800337
Kevin Peng5bc82d22021-10-19 11:18:40 +0800338 print ('Generating ' + manifest_out_file)
edison.ai7b299f52020-07-16 15:44:18 +0800339
Ken Liu861b0782021-05-22 13:15:08 +0800340 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800341 if not os.path.exists(outfile_path):
342 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800343
Kevin Peng655f2392019-11-27 16:33:02 +0800344 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800345
Kevin Peng5bc82d22021-10-19 11:18:40 +0800346 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800347 outfile.write(template.render(context))
348 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800349
Kevin Peng5bc82d22021-10-19 11:18:40 +0800350 print ('Generation of files done')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800351
Kevin Pengce99e5d2021-11-09 18:06:53 +0800352def process_stateless_services(partitions):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800353 """
354 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800355 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800356 Valid stateless handle in service will be converted to an index. If the
357 stateless handle is set as "auto", or not set, framework will allocate a
358 valid index for the service.
359 Framework puts each service into a reordered stateless service list at
360 position of "index". Other unused positions are left None.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800361 """
Kevin Pengce99e5d2021-11-09 18:06:53 +0800362
363 STATIC_HANDLE_CONFIG_FILE = 'secure_fw/spm/cmsis_psa/spm_ipc.h'
364
Kevin Pengc05319d2021-04-22 22:59:35 +0800365 collected_stateless_services = []
Kevin Pengce99e5d2021-11-09 18:06:53 +0800366 stateless_index_max_num = \
367 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_NUM_LIMIT'), base = 10)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800368
369 # Collect all stateless services first.
370 for partition in partitions:
371 # Skip the FF-M 1.0 partitions
372 if partition['manifest']['psa_framework_version'] < 1.1:
373 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800374
375 service_list = partition['manifest'].get('services', [])
376
377 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800378 if 'connection_based' not in service:
379 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
380 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800381 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800382
Kevin Pengc05319d2021-04-22 22:59:35 +0800383 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800384 return []
385
Ken Liu861b0782021-05-22 13:15:08 +0800386 if len(collected_stateless_services) > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800387 raise Exception('Stateless service numbers range exceed {number}.'.format(number=stateless_index_max_num))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800388
389 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800390 Allocate an empty stateless service list to store services.
391 Use "handle - 1" as the index for service, since handle value starts from
392 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800393 """
Ken Liu861b0782021-05-22 13:15:08 +0800394 reordered_stateless_services = [None] * stateless_index_max_num
Kevin Pengc05319d2021-04-22 22:59:35 +0800395 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800396
Kevin Pengc05319d2021-04-22 22:59:35 +0800397 for service in collected_stateless_services:
398 # If not set, it is "auto" by default
399 if 'stateless_handle' not in service:
400 auto_alloc_services.append(service)
401 continue
402
Mingyang Sun4ecea992021-03-30 17:56:26 +0800403 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800404
Mingyang Sun4ecea992021-03-30 17:56:26 +0800405 # Fill in service list with specified stateless handle, otherwise skip
406 if isinstance(service_handle, int):
Ken Liu861b0782021-05-22 13:15:08 +0800407 if service_handle < 1 or service_handle > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800408 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800409 # Convert handle index to reordered service list index
410 service_handle = service_handle - 1
411
412 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800413 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800414 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800415 elif service_handle == 'auto':
416 auto_alloc_services.append(service)
417 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800418 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800419
Kevin Pengce99e5d2021-11-09 18:06:53 +0800420 STATIC_HANDLE_IDX_BIT_WIDTH = \
421 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_IDX_BIT_WIDTH'), base = 10)
422 STATIC_HANDLE_IDX_MASK = (1 << STATIC_HANDLE_IDX_BIT_WIDTH) - 1
423
424 STATIC_HANDLE_INDICATOR_OFFSET = \
425 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_INDICATOR_OFFSET'), base = 10)
426
427 STATIC_HANDLE_VER_OFFSET = \
428 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_VER_OFFSET'), base = 10)
429
430 STATIC_HANDLE_VER_BIT_WIDTH = \
431 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_VER_BIT_WIDTH'), base = 10)
432 STATIC_HANDLE_VER_MASK = (1 << STATIC_HANDLE_VER_BIT_WIDTH) - 1
433
Mingyang Sun4ecea992021-03-30 17:56:26 +0800434 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu861b0782021-05-22 13:15:08 +0800435 for i in range(0, stateless_index_max_num):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800436 service = reordered_stateless_services[i]
437
Kevin Pengc05319d2021-04-22 22:59:35 +0800438 if service == None and len(auto_alloc_services) > 0:
439 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800440
Mingyang Sun453ad402021-03-17 17:58:33 +0800441 """
442 Encode stateless flag and version into stateless handle
Kevin Pengce99e5d2021-11-09 18:06:53 +0800443 Check STATIC_HANDLE_CONFIG_FILE for details
Mingyang Sun453ad402021-03-17 17:58:33 +0800444 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800445 stateless_handle_value = 0
446 if service != None:
Kevin Pengce99e5d2021-11-09 18:06:53 +0800447 stateless_index = (i & STATIC_HANDLE_IDX_MASK)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800448 stateless_handle_value |= stateless_index
Kevin Pengce99e5d2021-11-09 18:06:53 +0800449 stateless_handle_value |= (1 << STATIC_HANDLE_INDICATOR_OFFSET)
450 stateless_version = (service['version'] & STATIC_HANDLE_VER_MASK) << STATIC_HANDLE_VER_OFFSET
Mingyang Sun453ad402021-03-17 17:58:33 +0800451 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800452 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800453 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800454
Mingyang Sun4ecea992021-03-30 17:56:26 +0800455 reordered_stateless_services[i] = service
456
457 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800458
Kevin Peng655f2392019-11-27 16:33:02 +0800459def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000460 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
461 epilog='Note that environment variables in template files will be replaced with their values')
462
Kevin Peng655f2392019-11-27 16:33:02 +0800463 parser.add_argument('-o', '--outdir'
464 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800465 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800466 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800467 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800468
Kevin Peng5bc82d22021-10-19 11:18:40 +0800469 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100470 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800471 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100472 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800473 , metavar='manifest list'
474 , help='A list of Secure Partition manifest lists and their original paths.\n\
475 The manifest lists might be processed by CMake and\n\
476 the path might be different to the original one\n\
477 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800478
479 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100480 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800481 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100482 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800483 , metavar='file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100484 , help='These files descripe the file list to generate')
Kevin Peng655f2392019-11-27 16:33:02 +0800485
486 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800487
Kevin Peng65064c52021-10-27 17:12:17 +0800488 if len(args.manifest_lists) % 2 != 0:
489 print('Invalid structure in manifest lists.\n'
490 'Each element shall consist of a manifest list and its original path')
491 exit(1)
492
Kevin Peng655f2392019-11-27 16:33:02 +0800493 return args
494
495ENV = Environment(
496 loader = TemplateLoader(),
497 autoescape = select_autoescape(['html', 'xml']),
498 lstrip_blocks = True,
499 trim_blocks = True,
500 keep_trailing_newline = True
501 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100502
Miklos Balint470919c2018-05-22 17:51:29 +0200503def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100504 """
505 The entry point of the script.
506
507 Generates the output files based on the templates and the manifests.
508 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800509
Kevin Peng655f2392019-11-27 16:33:02 +0800510 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800511
Kevin Peng655f2392019-11-27 16:33:02 +0800512 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800513
Kevin Peng5bc82d22021-10-19 11:18:40 +0800514 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800515
Kevin Peng5bc82d22021-10-19 11:18:40 +0800516 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
517 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800518
Shawn Shana9ad1e02019-08-07 15:49:48 +0800519 """
Kevin Peng655f2392019-11-27 16:33:02 +0800520 Relative path to TF-M root folder is supported in the manifests
521 and default value of manifest list and generated file list are relative to TF-M root folder as well,
522 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800523 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800524 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 +0800525 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800526 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800527
Kevin Peng65064c52021-10-27 17:12:17 +0800528 context = process_partition_manifests(manifest_lists)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100529
Edison Ai6e3f2a32019-06-11 15:29:05 +0800530 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800531 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200532
Kevin Peng655f2392019-11-27 16:33:02 +0800533 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800534
Ken Liu861b0782021-05-22 13:15:08 +0800535 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800536 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200537
Kevin Peng5bc82d22021-10-19 11:18:40 +0800538if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200539 main()