blob: 5652461ec3ee00eb580f0113f4afde56e38212de [file] [log] [blame]
Miklos Balint470919c2018-05-22 17:51:29 +02001#-------------------------------------------------------------------------------
Xinyu Zhang90f08dc2022-01-12 15:55:17 +08002# Copyright (c) 2018-2022, 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 = []
Kevin Peng56b0ea62021-10-18 11:32:57 +0800144 pid_list = []
145 no_pid_manifest_idx = []
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800146 partition_statistics = {
147 'ipc_partition_num': 0,
148 'sfn_partition_num': 0
149 }
Kevin Peng655f2392019-11-27 16:33:02 +0800150
Kevin Peng65064c52021-10-27 17:12:17 +0800151 # Get all the manifests information as a dictionary
152 for i, item in enumerate(manifest_lists):
153 if i % 2 == 0 and not os.path.isfile(item):
154 print('Manifest list item [{}] must be a file'.format(i))
155 exit(1)
Kevin Peng655f2392019-11-27 16:33:02 +0800156
Kevin Peng65064c52021-10-27 17:12:17 +0800157 if i % 2 == 1:
158 if not os.path.isdir(item):
159 print('Manifest list item [{}] must be a directory'.format(i))
160 exit(1)
David Hub2694202021-07-15 14:58:39 +0800161
Kevin Peng65064c52021-10-27 17:12:17 +0800162 # Skip original manifest paths
163 continue
David Hub2694202021-07-15 14:58:39 +0800164
Kevin Peng65064c52021-10-27 17:12:17 +0800165 # The manifest list file generated by configure_file()
166 with open(item) as manifest_list_yaml_file:
167 manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
168 for dict in manifest_dic:
169 # Add original path of manifest list.
170 # The validation will be done in the next loop.
171 dict['list_path'] = manifest_lists[i + 1]
172 all_manifests.append(dict)
173
174 # Parse the manifests
175 for i, manifest_item in enumerate(all_manifests):
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800176 valid_enabled_conditions = ['on', 'true', 'enabled']
Kevin Peng50f413c2021-11-12 10:31:45 +0800177 valid_disabled_conditions = ['off', 'false', 'disabled', '']
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800178 is_enabled = ''
179
180 if 'conditional' in manifest_item.keys():
Kevin Peng50f413c2021-11-12 10:31:45 +0800181 is_enabled = str(manifest_item['conditional']).lower()
Kevin Peng68d9a3a2021-10-18 11:39:54 +0800182 else:
183 # Partitions without 'conditional' is alwasy on
184 is_enabled = 'on'
185
186 if is_enabled in valid_disabled_conditions:
187 continue
188 elif is_enabled not in valid_enabled_conditions:
189 raise Exception('Invalid "conditional" attribute: "{}" for {}. '
190 'Please set to one of {} or {}, case-insensitive.'\
191 .format(manifest_item['conditional'],
192 manifest_item['name'],
193 valid_enabled_conditions, valid_disabled_conditions))
194
Xinyu Zhangc46ee1f2021-04-01 10:10:43 +0800195 # Check if partition ID is manually set
196 if 'pid' not in manifest_item.keys():
197 no_pid_manifest_idx.append(i)
Kevin Peng8849b6a2021-11-09 14:17:35 +0800198 pid = None
Kevin Peng56b0ea62021-10-18 11:32:57 +0800199 else:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800200 pid = manifest_item['pid']
201
202 # Check if partition ID is duplicated
203 if pid in pid_list:
204 raise Exception('PID No. {pid} has already been used!'.format(pid))
205 else:
206 pid_list.append(pid)
Xinyu Zhang19504a52021-03-31 16:26:20 +0800207
Raef Coles558487a2020-10-29 13:09:44 +0000208 # Replace environment variables in the manifest path
Kevin Peng655f2392019-11-27 16:33:02 +0800209 manifest_path = os.path.expandvars(manifest_item['manifest'])
Kevin Peng65064c52021-10-27 17:12:17 +0800210 # Convert to absolute path. If it's already abspath, the path will not be changed.
211 manifest_path = os.path.join(manifest_item['list_path'], manifest_path).replace('\\', '/')
David Hub2694202021-07-15 14:58:39 +0800212
Kevin Peng5bc82d22021-10-19 11:18:40 +0800213 with open(manifest_path) as manifest_file:
Kevin Peng8849b6a2021-11-09 14:17:35 +0800214 manifest = manifest_validation(yaml.safe_load(manifest_file), pid)
Kevin Peng655f2392019-11-27 16:33:02 +0800215
Kevin Pengce99e5d2021-11-09 18:06:53 +0800216 if pid == None or pid >= TFM_PID_BASE:
Kevin Pengd08f3ba2021-11-18 15:18:56 +0800217 # Count the number of IPC/SFN partitions
218 if manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'SFN':
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800219 partition_statistics['sfn_partition_num'] += 1
Kevin Pengd08f3ba2021-11-18 15:18:56 +0800220 else:
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800221 partition_statistics['ipc_partition_num'] += 1
Mingyang Suneab7eae2021-09-30 13:06:52 +0800222
Kevin Peng65064c52021-10-27 17:12:17 +0800223 manifest_out_basename = os.path.splitext(os.path.basename(manifest_path))[0]
Kevin Peng655f2392019-11-27 16:33:02 +0800224
Kevin Peng4fade072021-10-26 17:57:50 +0800225 if 'output_path' in manifest_item:
Kevin Peng4fade072021-10-26 17:57:50 +0800226 output_path = os.path.expandvars(manifest_item['output_path'])
Kevin Peng4fade072021-10-26 17:57:50 +0800227 else:
Kevin Peng65064c52021-10-27 17:12:17 +0800228 output_path = ''
David Hub2694202021-07-15 14:58:39 +0800229
Kevin Peng5bc82d22021-10-19 11:18:40 +0800230 manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
231 '{}.h'.format(manifest_out_basename))\
232 .replace('\\', '/')
233 intermedia_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
234 'intermedia_{}.c'.format(manifest_out_basename))\
235 .replace('\\', '/')
236 load_info_file = os.path.join(OUT_DIR, output_path, 'auto_generated',
237 'load_info_{}.c'.format(manifest_out_basename))\
238 .replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800239
Kevin Peng5bc82d22021-10-19 11:18:40 +0800240 partition_list.append({'manifest': manifest, 'attr': manifest_item,
241 'manifest_out_basename': manifest_out_basename,
242 'header_file': manifest_head_file,
243 'intermedia_file': intermedia_file,
244 'loadinfo_file': load_info_file})
Ken Liu861b0782021-05-22 13:15:08 +0800245
Kevin Peng56b0ea62021-10-18 11:32:57 +0800246 # Automatically assign PIDs for partitions without 'pid' attribute
Kevin Pengce99e5d2021-11-09 18:06:53 +0800247 pid = max(pid_list, default = TFM_PID_BASE - 1)
Kevin Peng56b0ea62021-10-18 11:32:57 +0800248 for idx in no_pid_manifest_idx:
Kevin Pengc424eec2021-06-25 17:26:11 +0800249 pid += 1
Kevin Peng65064c52021-10-27 17:12:17 +0800250 all_manifests[idx]['pid'] = pid
Kevin Peng56b0ea62021-10-18 11:32:57 +0800251 pid_list.append(pid)
252
Kevin Peng5bc82d22021-10-19 11:18:40 +0800253 context['partitions'] = partition_list
Xinyu Zhang90f08dc2022-01-12 15:55:17 +0800254 context['partition_statistics'] = partition_statistics
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100255
Kevin Pengce99e5d2021-11-09 18:06:53 +0800256 context['stateless_services'] = process_stateless_services(partition_list)
Ruiqi Jiang71d361c2021-06-23 17:45:55 +0100257
Kevin Peng5bc82d22021-10-19 11:18:40 +0800258 return context
Ken Liu861b0782021-05-22 13:15:08 +0800259
260def gen_per_partition_files(context):
261 """
262 Generate per-partition files
263
264 Parameters
265 ----------
266 context:
267 context contains partition infos
268 """
269
Kevin Peng5bc82d22021-10-19 11:18:40 +0800270 utilities = {}
271 utilities['donotedit_warning'] = donotedit_warning
Ken Liu861b0782021-05-22 13:15:08 +0800272
Kevin Peng5bc82d22021-10-19 11:18:40 +0800273 partition_context = {}
274 partition_context['utilities'] = utilities
Ken Liu861b0782021-05-22 13:15:08 +0800275
Kevin Peng5bc82d22021-10-19 11:18:40 +0800276 manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
277 memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
278 infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
Ken Liu861b0782021-05-22 13:15:08 +0800279
Kevin Peng5bc82d22021-10-19 11:18:40 +0800280 print ('Start to generate partition files:')
Ken Liu861b0782021-05-22 13:15:08 +0800281
282 for one_partition in context['partitions']:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800283 partition_context['manifest'] = one_partition['manifest']
284 partition_context['attr'] = one_partition['attr']
285 partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
Ken Liu861b0782021-05-22 13:15:08 +0800286
Kevin Peng5bc82d22021-10-19 11:18:40 +0800287 print ('Generating Header: ' + one_partition['header_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800288 outfile_path = os.path.dirname(one_partition['header_file'])
Kevin Peng655f2392019-11-27 16:33:02 +0800289 if not os.path.exists(outfile_path):
290 os.makedirs(outfile_path)
291
Kevin Peng5bc82d22021-10-19 11:18:40 +0800292 headerfile = io.open(one_partition['header_file'], 'w', newline=None)
293 headerfile.write(manifesttemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800294 headerfile.close()
Kevin Peng655f2392019-11-27 16:33:02 +0800295
Kevin Peng5bc82d22021-10-19 11:18:40 +0800296 print ('Generating Intermedia: ' + one_partition['intermedia_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800297 intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
Mingyang Sund20999f2020-10-15 14:53:12 +0800298 if not os.path.exists(intermediafile_path):
299 os.makedirs(intermediafile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800300 intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
301 intermediafile.write(memorytemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800302 intermediafile.close()
Mingyang Sund20999f2020-10-15 14:53:12 +0800303
Kevin Peng5bc82d22021-10-19 11:18:40 +0800304 print ('Generating Loadinfo: ' + one_partition['loadinfo_file'])
Ken Liu861b0782021-05-22 13:15:08 +0800305 infofile_path = os.path.dirname(one_partition['loadinfo_file'])
Mingyang Sunf6a78572021-04-02 16:51:05 +0800306 if not os.path.exists(infofile_path):
307 os.makedirs(infofile_path)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800308 infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
309 infooutfile.write(infotemplate.render(partition_context))
Ken Liu861b0782021-05-22 13:15:08 +0800310 infooutfile.close()
Mingyang Sunf6a78572021-04-02 16:51:05 +0800311
Kevin Peng5bc82d22021-10-19 11:18:40 +0800312 print ('Per-partition files done:')
Mingyang Sunf6a78572021-04-02 16:51:05 +0800313
Ken Liu861b0782021-05-22 13:15:08 +0800314def gen_summary_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800315 """
316 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800317
318 Parameters
319 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100320 gen_file_lists:
321 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800322 """
Kevin Peng655f2392019-11-27 16:33:02 +0800323 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800324
Raef Colesf42f0882020-07-10 10:01:58 +0100325 for f in gen_file_lists:
326 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800327 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800328 file_list.extend(file_list_yaml['file_list'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800329
Kevin Peng5bc82d22021-10-19 11:18:40 +0800330 print('Start to generate file from the generated list:')
Kevin Peng655f2392019-11-27 16:33:02 +0800331 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000332 # Replace environment variables in the output filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800333 manifest_out_file = os.path.expandvars(file['output'])
Raef Coles558487a2020-10-29 13:09:44 +0000334 # Replace environment variables in the template filepath
Kevin Peng5bc82d22021-10-19 11:18:40 +0800335 templatefile_name = os.path.expandvars(file['template'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800336
Kevin Peng4fade072021-10-26 17:57:50 +0800337 manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800338
Kevin Peng5bc82d22021-10-19 11:18:40 +0800339 print ('Generating ' + manifest_out_file)
edison.ai7b299f52020-07-16 15:44:18 +0800340
Ken Liu861b0782021-05-22 13:15:08 +0800341 outfile_path = os.path.dirname(manifest_out_file)
Kevin Peng655f2392019-11-27 16:33:02 +0800342 if not os.path.exists(outfile_path):
343 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800344
Kevin Peng655f2392019-11-27 16:33:02 +0800345 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800346
Kevin Peng5bc82d22021-10-19 11:18:40 +0800347 outfile = io.open(manifest_out_file, 'w', newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800348 outfile.write(template.render(context))
349 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800350
Kevin Peng5bc82d22021-10-19 11:18:40 +0800351 print ('Generation of files done')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800352
Kevin Pengce99e5d2021-11-09 18:06:53 +0800353def process_stateless_services(partitions):
Mingyang Suna1ca6112021-01-11 11:34:59 +0800354 """
355 This function collects all stateless services together, and allocates
Mingyang Sun4ecea992021-03-30 17:56:26 +0800356 stateless handles for them.
Kevin Pengc05319d2021-04-22 22:59:35 +0800357 Valid stateless handle in service will be converted to an index. If the
358 stateless handle is set as "auto", or not set, framework will allocate a
359 valid index for the service.
360 Framework puts each service into a reordered stateless service list at
361 position of "index". Other unused positions are left None.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800362 """
Kevin Pengce99e5d2021-11-09 18:06:53 +0800363
364 STATIC_HANDLE_CONFIG_FILE = 'secure_fw/spm/cmsis_psa/spm_ipc.h'
365
Kevin Pengc05319d2021-04-22 22:59:35 +0800366 collected_stateless_services = []
Kevin Pengce99e5d2021-11-09 18:06:53 +0800367 stateless_index_max_num = \
368 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_NUM_LIMIT'), base = 10)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800369
370 # Collect all stateless services first.
371 for partition in partitions:
372 # Skip the FF-M 1.0 partitions
373 if partition['manifest']['psa_framework_version'] < 1.1:
374 continue
Kevin Peng8849b6a2021-11-09 14:17:35 +0800375
376 service_list = partition['manifest'].get('services', [])
377
378 for service in service_list:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800379 if 'connection_based' not in service:
380 raise Exception("'connection_based' is mandatory in FF-M 1.1 service!")
381 if service['connection_based'] is False:
Kevin Pengc05319d2021-04-22 22:59:35 +0800382 collected_stateless_services.append(service)
Mingyang Suna1ca6112021-01-11 11:34:59 +0800383
Kevin Pengc05319d2021-04-22 22:59:35 +0800384 if len(collected_stateless_services) == 0:
Mingyang Suna1ca6112021-01-11 11:34:59 +0800385 return []
386
Ken Liu861b0782021-05-22 13:15:08 +0800387 if len(collected_stateless_services) > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800388 raise Exception('Stateless service numbers range exceed {number}.'.format(number=stateless_index_max_num))
Mingyang Suna1ca6112021-01-11 11:34:59 +0800389
390 """
Kevin Pengc05319d2021-04-22 22:59:35 +0800391 Allocate an empty stateless service list to store services.
392 Use "handle - 1" as the index for service, since handle value starts from
393 1 and list index starts from 0.
Mingyang Suna1ca6112021-01-11 11:34:59 +0800394 """
Ken Liu861b0782021-05-22 13:15:08 +0800395 reordered_stateless_services = [None] * stateless_index_max_num
Kevin Pengc05319d2021-04-22 22:59:35 +0800396 auto_alloc_services = []
Mingyang Suna1ca6112021-01-11 11:34:59 +0800397
Kevin Pengc05319d2021-04-22 22:59:35 +0800398 for service in collected_stateless_services:
399 # If not set, it is "auto" by default
400 if 'stateless_handle' not in service:
401 auto_alloc_services.append(service)
402 continue
403
Mingyang Sun4ecea992021-03-30 17:56:26 +0800404 service_handle = service['stateless_handle']
Mingyang Suna1ca6112021-01-11 11:34:59 +0800405
Mingyang Sun4ecea992021-03-30 17:56:26 +0800406 # Fill in service list with specified stateless handle, otherwise skip
407 if isinstance(service_handle, int):
Ken Liu861b0782021-05-22 13:15:08 +0800408 if service_handle < 1 or service_handle > stateless_index_max_num:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800409 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800410 # Convert handle index to reordered service list index
411 service_handle = service_handle - 1
412
413 if reordered_stateless_services[service_handle] is not None:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800414 raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800415 reordered_stateless_services[service_handle] = service
Kevin Pengc05319d2021-04-22 22:59:35 +0800416 elif service_handle == 'auto':
417 auto_alloc_services.append(service)
418 else:
Kevin Peng5bc82d22021-10-19 11:18:40 +0800419 raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
Mingyang Sun4ecea992021-03-30 17:56:26 +0800420
Kevin Pengce99e5d2021-11-09 18:06:53 +0800421 STATIC_HANDLE_IDX_BIT_WIDTH = \
422 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_IDX_BIT_WIDTH'), base = 10)
423 STATIC_HANDLE_IDX_MASK = (1 << STATIC_HANDLE_IDX_BIT_WIDTH) - 1
424
425 STATIC_HANDLE_INDICATOR_OFFSET = \
426 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_INDICATOR_OFFSET'), base = 10)
427
428 STATIC_HANDLE_VER_OFFSET = \
429 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_VER_OFFSET'), base = 10)
430
431 STATIC_HANDLE_VER_BIT_WIDTH = \
432 int(get_single_macro_def_from_file(STATIC_HANDLE_CONFIG_FILE, 'STATIC_HANDLE_VER_BIT_WIDTH'), base = 10)
433 STATIC_HANDLE_VER_MASK = (1 << STATIC_HANDLE_VER_BIT_WIDTH) - 1
434
Mingyang Sun4ecea992021-03-30 17:56:26 +0800435 # Auto-allocate stateless handle and encode the stateless handle
Ken Liu861b0782021-05-22 13:15:08 +0800436 for i in range(0, stateless_index_max_num):
Mingyang Sun4ecea992021-03-30 17:56:26 +0800437 service = reordered_stateless_services[i]
438
Kevin Pengc05319d2021-04-22 22:59:35 +0800439 if service == None and len(auto_alloc_services) > 0:
440 service = auto_alloc_services.pop(0)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800441
Mingyang Sun453ad402021-03-17 17:58:33 +0800442 """
443 Encode stateless flag and version into stateless handle
Kevin Pengce99e5d2021-11-09 18:06:53 +0800444 Check STATIC_HANDLE_CONFIG_FILE for details
Mingyang Sun453ad402021-03-17 17:58:33 +0800445 """
Mingyang Sun4ecea992021-03-30 17:56:26 +0800446 stateless_handle_value = 0
447 if service != None:
Kevin Pengce99e5d2021-11-09 18:06:53 +0800448 stateless_index = (i & STATIC_HANDLE_IDX_MASK)
Mingyang Sun4ecea992021-03-30 17:56:26 +0800449 stateless_handle_value |= stateless_index
Kevin Pengce99e5d2021-11-09 18:06:53 +0800450 stateless_handle_value |= (1 << STATIC_HANDLE_INDICATOR_OFFSET)
451 stateless_version = (service['version'] & STATIC_HANDLE_VER_MASK) << STATIC_HANDLE_VER_OFFSET
Mingyang Sun453ad402021-03-17 17:58:33 +0800452 stateless_handle_value |= stateless_version
Mingyang Sun4ecea992021-03-30 17:56:26 +0800453 service['stateless_handle_value'] = '0x{0:08x}'.format(stateless_handle_value)
Ken Liu861b0782021-05-22 13:15:08 +0800454 service['stateless_handle_index'] = stateless_index
Mingyang Suna1ca6112021-01-11 11:34:59 +0800455
Mingyang Sun4ecea992021-03-30 17:56:26 +0800456 reordered_stateless_services[i] = service
457
458 return reordered_stateless_services
Mingyang Suna1ca6112021-01-11 11:34:59 +0800459
Kevin Peng655f2392019-11-27 16:33:02 +0800460def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000461 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
462 epilog='Note that environment variables in template files will be replaced with their values')
463
Kevin Peng655f2392019-11-27 16:33:02 +0800464 parser.add_argument('-o', '--outdir'
465 , dest='outdir'
Kevin Peng4fade072021-10-26 17:57:50 +0800466 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800467 , metavar='out_dir'
Kevin Peng4fade072021-10-26 17:57:50 +0800468 , help='The root directory for generated files')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800469
Kevin Peng5bc82d22021-10-19 11:18:40 +0800470 parser.add_argument('-m', '--manifest-lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100471 , nargs='+'
Kevin Peng5bc82d22021-10-19 11:18:40 +0800472 , dest='manifest_lists'
Raef Colesf42f0882020-07-10 10:01:58 +0100473 , required=True
Kevin Peng65064c52021-10-27 17:12:17 +0800474 , metavar='manifest list'
475 , help='A list of Secure Partition manifest lists and their original paths.\n\
476 The manifest lists might be processed by CMake and\n\
477 the path might be different to the original one\n\
478 The format must be [list A, orignal path A, list B, orignal path B, ...]')
Kevin Peng655f2392019-11-27 16:33:02 +0800479
480 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100481 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800482 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100483 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800484 , metavar='file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100485 , help='These files descripe the file list to generate')
Kevin Peng655f2392019-11-27 16:33:02 +0800486
487 args = parser.parse_args()
Kevin Peng655f2392019-11-27 16:33:02 +0800488
Kevin Peng65064c52021-10-27 17:12:17 +0800489 if len(args.manifest_lists) % 2 != 0:
490 print('Invalid structure in manifest lists.\n'
491 'Each element shall consist of a manifest list and its original path')
492 exit(1)
493
Kevin Peng655f2392019-11-27 16:33:02 +0800494 return args
495
496ENV = Environment(
497 loader = TemplateLoader(),
498 autoescape = select_autoescape(['html', 'xml']),
499 lstrip_blocks = True,
500 trim_blocks = True,
501 keep_trailing_newline = True
502 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100503
Miklos Balint470919c2018-05-22 17:51:29 +0200504def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100505 """
506 The entry point of the script.
507
508 Generates the output files based on the templates and the manifests.
509 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800510
Kevin Peng655f2392019-11-27 16:33:02 +0800511 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800512
Kevin Peng655f2392019-11-27 16:33:02 +0800513 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800514
Kevin Peng5bc82d22021-10-19 11:18:40 +0800515 OUT_DIR = os.path.abspath(args.outdir)
Kevin Peng655f2392019-11-27 16:33:02 +0800516
Kevin Peng5bc82d22021-10-19 11:18:40 +0800517 manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
518 gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800519
Shawn Shana9ad1e02019-08-07 15:49:48 +0800520 """
Kevin Peng655f2392019-11-27 16:33:02 +0800521 Relative path to TF-M root folder is supported in the manifests
522 and default value of manifest list and generated file list are relative to TF-M root folder as well,
523 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800524 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800525 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 +0800526 """
Kevin Peng5bc82d22021-10-19 11:18:40 +0800527 os.chdir(os.path.join(sys.path[0], '..'))
Shawn Shana9ad1e02019-08-07 15:49:48 +0800528
Kevin Peng65064c52021-10-27 17:12:17 +0800529 context = process_partition_manifests(manifest_lists)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100530
Edison Ai6e3f2a32019-06-11 15:29:05 +0800531 utilities = {}
Mingyang Suna1ca6112021-01-11 11:34:59 +0800532 utilities['donotedit_warning'] = donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200533
Kevin Peng655f2392019-11-27 16:33:02 +0800534 context['utilities'] = utilities
Mingyang Suneab7eae2021-09-30 13:06:52 +0800535
Ken Liu861b0782021-05-22 13:15:08 +0800536 gen_per_partition_files(context)
Kevin Peng5bc82d22021-10-19 11:18:40 +0800537 gen_summary_files(context, gen_file_lists)
Miklos Balint470919c2018-05-22 17:51:29 +0200538
Kevin Peng5bc82d22021-10-19 11:18:40 +0800539if __name__ == '__main__':
Miklos Balint470919c2018-05-22 17:51:29 +0200540 main()