blob: b2ce52d9a99a5c3a685f7ee8b51a2727b6d192a7 [file] [log] [blame]
Miklos Balint470919c2018-05-22 17:51:29 +02001#-------------------------------------------------------------------------------
TTornblom7f92a732020-03-05 13:12:20 +01002# Copyright (c) 2018-2020, 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:
Mate Toth-Pala99ec6b2019-05-07 11:00:56 +020017 print (str(e) + " To install it, type:")
Mate Toth-Pal36f21842018-11-08 16:12:51 +010018 print ("pip install PyYAML")
Miklos Balint470919c2018-05-22 17:51:29 +020019 exit(1)
20
Edison Ai48b2d9e2019-06-24 14:39:45 +080021donotedit_warning = \
22 "/*********** " + \
23 "WARNING: This is an auto-generated file. Do not edit!" + \
24 " ***********/"
Kevin Peng655f2392019-11-27 16:33:02 +080025
26DEFAULT_MANIFEST_LIST = os.path.join('tools', 'tfm_manifest_list.yaml')
27DEFAULT_GEN_FILE_LIST = os.path.join('tools', 'tfm_generated_file_list.yaml')
28
29OUT_DIR = None # The root directory that files are generated to
Edison Ai48b2d9e2019-06-24 14:39:45 +080030
Mate Toth-Pal36f21842018-11-08 16:12:51 +010031class TemplateLoader(BaseLoader):
32 """
33 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020034
Mate Toth-Pal36f21842018-11-08 16:12:51 +010035 An instance of this class is passed to the template engine. It is
36 responsible for reading the template file
37 """
38 def __init__(self):
39 pass
Miklos Balint470919c2018-05-22 17:51:29 +020040
Mate Toth-Pal36f21842018-11-08 16:12:51 +010041 def get_source(self, environment, template):
42 """
43 This function reads the template files.
44 For detailed documentation see:
45 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
46
47 Please note that this function always return 'false' as 'uptodate'
48 value, so the output file will always be generated.
49 """
50 if not os.path.isfile(template):
51 raise TemplateNotFound(template)
52 with open(template) as f:
53 source = f.read()
54 return source, template, False
55
Kevin Peng655f2392019-11-27 16:33:02 +080056def process_manifest(manifest_list_file, append):
Mate Toth-Pal36f21842018-11-08 16:12:51 +010057 """
Kevin Peng655f2392019-11-27 16:33:02 +080058 Parse the input manifest, generate the data base for genereated files
59 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +010060
61 Parameters
62 ----------
Kevin Peng655f2392019-11-27 16:33:02 +080063 manifest_list_file:
64 The manifest list to parse.
65 append:
66 To append the manifest to original or not.
Mate Toth-Pal36f21842018-11-08 16:12:51 +010067
68 Returns
69 -------
Kevin Peng655f2392019-11-27 16:33:02 +080070 The manifest header list and the data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +080071 """
Kevin Peng655f2392019-11-27 16:33:02 +080072
73 db = []
74 manifest_header_list = []
75 manifest_list = []
76
77 if append:
78 # Load the default manifest first
79 with open(DEFAULT_MANIFEST_LIST) as default_manifest_list_yaml_file:
80 manifest_dic = yaml.safe_load(default_manifest_list_yaml_file)
81 manifest_list.extend(manifest_dic["manifest_list"])
82
83 with open(manifest_list_file) as manifest_list_yaml_file:
84 manifest_dic = yaml.safe_load(manifest_list_yaml_file)
85 manifest_list.extend(manifest_dic["manifest_list"])
86
Ken Liu1f345b02020-05-30 21:11:05 +080087 templatefile_name = 'secure_fw/partitions/manifestfilename.template'
Kevin Peng655f2392019-11-27 16:33:02 +080088 template = ENV.get_template(templatefile_name)
89
edison.ai7b299f52020-07-16 15:44:18 +080090 print("Start to generate PSA manifests:")
Kevin Peng655f2392019-11-27 16:33:02 +080091 for manifest_item in manifest_list:
92 manifest_path = os.path.expandvars(manifest_item['manifest'])
93 file = open(manifest_path)
94 manifest = yaml.safe_load(file)
95
96 db.append({"manifest": manifest, "attr": manifest_item})
97
98 utilities = {}
99 utilities['donotedit_warning']=donotedit_warning
100
101 context = {}
102 context['manifest'] = manifest
103 context['attr'] = manifest_item
104 context['utilities'] = utilities
105
106 manifest_dir, manifest_name = os.path.split(manifest_path)
107 outfile_name = manifest_name.replace('yaml', 'h').replace('json', 'h')
108 context['file_name'] = outfile_name.replace('.h', '')
TTornblom7f92a732020-03-05 13:12:20 +0100109 outfile_name = os.path.join(manifest_dir, "psa_manifest", outfile_name).replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +0800110
111 manifest_header_list.append(outfile_name)
112
113 if OUT_DIR is not None:
114 outfile_name = os.path.join(OUT_DIR, outfile_name)
115
116 outfile_path = os.path.dirname(outfile_name)
117 if not os.path.exists(outfile_path):
118 os.makedirs(outfile_path)
119
120 print ("Generating " + outfile_name)
121
TTornblom441a0702020-04-28 12:40:42 +0200122 outfile = io.open(outfile_name, "w", newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800123 outfile.write(template.render(context))
124 outfile.close()
125
126 return manifest_header_list, db
127
128def gen_files(context, gen_file_list, append):
129 """
130 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800131
132 Parameters
133 ----------
Kevin Peng655f2392019-11-27 16:33:02 +0800134 gen_file_list:
135 The list of files to generate
136 append:
137 To append the manifest to original or not
Edison Ai48b2d9e2019-06-24 14:39:45 +0800138 """
Kevin Peng655f2392019-11-27 16:33:02 +0800139 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800140
Kevin Peng655f2392019-11-27 16:33:02 +0800141 if append:
142 # read default file list first
143 with open(DEFAULT_GEN_FILE_LIST) as file_list_yaml_file:
144 file_list_yaml = yaml.safe_load(file_list_yaml_file)
145 file_list.extend(file_list_yaml["file_list"])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800146
Kevin Peng655f2392019-11-27 16:33:02 +0800147 with open(gen_file_list) as file_list_yaml_file:
148 # read list of files that need to be generated from templates using db
149 file_list_yaml = yaml.safe_load(file_list_yaml_file)
150 file_list.extend(file_list_yaml["file_list"])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800151
edison.ai7b299f52020-07-16 15:44:18 +0800152 print("Start to generate file from the generated list:")
Kevin Peng655f2392019-11-27 16:33:02 +0800153 for file in file_list:
154 outfile_name = os.path.expandvars(file["output"])
Kevin Peng1ec5e7c2019-11-29 10:52:00 +0800155 templatefile_name = os.path.expandvars(file["template"])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800156
Kevin Peng655f2392019-11-27 16:33:02 +0800157 if OUT_DIR is not None:
158 outfile_name = os.path.join(OUT_DIR, outfile_name)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800159
edison.ai7b299f52020-07-16 15:44:18 +0800160 print ("Generating " + outfile_name)
161
Kevin Peng655f2392019-11-27 16:33:02 +0800162 outfile_path = os.path.dirname(outfile_name)
163 if not os.path.exists(outfile_path):
164 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800165
Kevin Peng655f2392019-11-27 16:33:02 +0800166 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800167
TTornblom441a0702020-04-28 12:40:42 +0200168 outfile = io.open(outfile_name, "w", newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800169 outfile.write(template.render(context))
170 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800171
Kevin Peng655f2392019-11-27 16:33:02 +0800172 print ("Generation of files done")
Edison Ai48b2d9e2019-06-24 14:39:45 +0800173
Kevin Peng655f2392019-11-27 16:33:02 +0800174def parse_args():
175 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list')
176 parser.add_argument('-o', '--outdir'
177 , dest='outdir'
178 , required=False
179 , default=None
180 , metavar='out_dir'
181 , help='The root directory for generated files, the default is TF-M root folder.')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800182
Kevin Peng655f2392019-11-27 16:33:02 +0800183 parser.add_argument('-m', '--manifest'
184 , nargs='*'
185 , dest='manifest_args'
186 , required=False
187 , default=[]
188 , metavar='manifest'
189 , help='The secure partition manifest list file to parse, the default is '+ DEFAULT_MANIFEST_LIST + '. \
190 Or the manifest can be append to the default one by explicitly \"append\" it:\
191 -m manifest_to_append append')
192
193 parser.add_argument('-f', '--file-list'
194 , nargs='*'
195 , dest='gen_file_args'
196 , required=False
197 , default=[]
198 , metavar='file-list'
199 , help='The file descripes the file list to generate, the default is ' + DEFAULT_GEN_FILE_LIST + '. \
200 Or the file list can be append to the default one by explicitly \"append\" it:\
201 -f files_to_append append')
202
203 args = parser.parse_args()
204 manifest_args = args.manifest_args
205 gen_file_args = args.gen_file_args
206
207 if len(manifest_args) > 2 or len(gen_file_args) > 2:
208 parser.print_help()
209 exit(1)
210
211 if len(manifest_args) == 2 and (manifest_args[1] != 'append' and manifest_args[1] != ''):
212 parser.print_help()
213 exit(1)
214
215 if len(gen_file_args) == 2 and (gen_file_args[1] != 'append' and gen_file_args[1] != ''):
216 parser.print_help()
217 exit(1)
218
219 return args
220
221ENV = Environment(
222 loader = TemplateLoader(),
223 autoescape = select_autoescape(['html', 'xml']),
224 lstrip_blocks = True,
225 trim_blocks = True,
226 keep_trailing_newline = True
227 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100228
Miklos Balint470919c2018-05-22 17:51:29 +0200229def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100230 """
231 The entry point of the script.
232
233 Generates the output files based on the templates and the manifests.
234 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800235
Kevin Peng655f2392019-11-27 16:33:02 +0800236 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800237
Kevin Peng655f2392019-11-27 16:33:02 +0800238 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800239
Kevin Peng655f2392019-11-27 16:33:02 +0800240 manifest_args = args.manifest_args
241 gen_file_args = args.gen_file_args
242 OUT_DIR = args.outdir
243 append_manifest = False
244 append_gen_file = False
245
246 if len(manifest_args) == 2 and manifest_args[1] == 'append':
247 append_manifest = True
248
249 if len(gen_file_args) == 2 and gen_file_args[1] == 'append':
250 append_gen_file = True
251
252 if len(manifest_args) == 0:
253 manifest_list = DEFAULT_MANIFEST_LIST
254 else:
255 """
256 Only convert to abs path when value is not default
257 Because the default value is a fixed relative path to TF-M root folder,
258 it will be various to different execution path if converted to absolute path.
259 The same for gen_file_list
260 """
261 manifest_list = os.path.abspath(args.manifest_args[0])
262 if len(gen_file_args) == 0:
263 gen_file_list = DEFAULT_GEN_FILE_LIST
264 else:
265 gen_file_list = os.path.abspath(args.gen_file_args[0])
Shawn Shana9ad1e02019-08-07 15:49:48 +0800266
267 # Arguments could be relative path.
Kevin Peng655f2392019-11-27 16:33:02 +0800268 # Convert to absolute path as we are going to change diretory later
269 if OUT_DIR is not None:
270 OUT_DIR = os.path.abspath(OUT_DIR)
271
Shawn Shana9ad1e02019-08-07 15:49:48 +0800272 """
Kevin Peng655f2392019-11-27 16:33:02 +0800273 Relative path to TF-M root folder is supported in the manifests
274 and default value of manifest list and generated file list are relative to TF-M root folder as well,
275 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800276 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800277 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 +0800278 """
279 os.chdir(os.path.join(sys.path[0], ".."))
280
Kevin Peng655f2392019-11-27 16:33:02 +0800281 manifest_header_list, db = process_manifest(manifest_list, append_manifest)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100282
Edison Ai6e3f2a32019-06-11 15:29:05 +0800283 utilities = {}
284 context = {}
285
Kevin Peng655f2392019-11-27 16:33:02 +0800286 utilities['donotedit_warning']=donotedit_warning
287 utilities['manifest_header_list']=manifest_header_list
Miklos Balint470919c2018-05-22 17:51:29 +0200288
Kevin Peng655f2392019-11-27 16:33:02 +0800289 context['manifests'] = db
290 context['utilities'] = utilities
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100291
Kevin Peng655f2392019-11-27 16:33:02 +0800292 gen_files(context, gen_file_list, append_gen_file)
Miklos Balint470919c2018-05-22 17:51:29 +0200293
294if __name__ == "__main__":
295 main()