blob: 9ea5f7df6190b10f7615ed2d33671f5a228ee777 [file] [log] [blame]
Miklos Balint470919c2018-05-22 17:51:29 +02001#-------------------------------------------------------------------------------
Mate Toth-Pal36f21842018-11-08 16:12:51 +01002# Copyright (c) 2018-2019, 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
Mate Toth-Pal36f21842018-11-08 16:12:51 +010012from jinja2 import Environment, BaseLoader, select_autoescape
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
87 templatefile_name = 'secure_fw/services/manifestfilename.template'
88 template = ENV.get_template(templatefile_name)
89
90 for manifest_item in manifest_list:
91 manifest_path = os.path.expandvars(manifest_item['manifest'])
92 file = open(manifest_path)
93 manifest = yaml.safe_load(file)
94
95 db.append({"manifest": manifest, "attr": manifest_item})
96
97 utilities = {}
98 utilities['donotedit_warning']=donotedit_warning
99
100 context = {}
101 context['manifest'] = manifest
102 context['attr'] = manifest_item
103 context['utilities'] = utilities
104
105 manifest_dir, manifest_name = os.path.split(manifest_path)
106 outfile_name = manifest_name.replace('yaml', 'h').replace('json', 'h')
107 context['file_name'] = outfile_name.replace('.h', '')
108 outfile_name = os.path.join(manifest_dir, "psa_manifest", outfile_name)
109
110 manifest_header_list.append(outfile_name)
111
112 if OUT_DIR is not None:
113 outfile_name = os.path.join(OUT_DIR, outfile_name)
114
115 outfile_path = os.path.dirname(outfile_name)
116 if not os.path.exists(outfile_path):
117 os.makedirs(outfile_path)
118
119 print ("Generating " + outfile_name)
120
121 outfile = io.open(outfile_name, "w", newline='\n')
122 outfile.write(template.render(context))
123 outfile.close()
124
125 return manifest_header_list, db
126
127def gen_files(context, gen_file_list, append):
128 """
129 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800130
131 Parameters
132 ----------
Kevin Peng655f2392019-11-27 16:33:02 +0800133 gen_file_list:
134 The list of files to generate
135 append:
136 To append the manifest to original or not
Edison Ai48b2d9e2019-06-24 14:39:45 +0800137 """
Kevin Peng655f2392019-11-27 16:33:02 +0800138 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800139
Kevin Peng655f2392019-11-27 16:33:02 +0800140 if append:
141 # read default file list first
142 with open(DEFAULT_GEN_FILE_LIST) as file_list_yaml_file:
143 file_list_yaml = yaml.safe_load(file_list_yaml_file)
144 file_list.extend(file_list_yaml["file_list"])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800145
Kevin Peng655f2392019-11-27 16:33:02 +0800146 with open(gen_file_list) as file_list_yaml_file:
147 # read list of files that need to be generated from templates using db
148 file_list_yaml = yaml.safe_load(file_list_yaml_file)
149 file_list.extend(file_list_yaml["file_list"])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800150
Kevin Peng655f2392019-11-27 16:33:02 +0800151 for file in file_list:
152 outfile_name = os.path.expandvars(file["output"])
153 templatefile_name = outfile_name + '.template'
Edison Ai48b2d9e2019-06-24 14:39:45 +0800154
Kevin Peng655f2392019-11-27 16:33:02 +0800155 if OUT_DIR is not None:
156 outfile_name = os.path.join(OUT_DIR, outfile_name)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800157
Kevin Peng655f2392019-11-27 16:33:02 +0800158 outfile_path = os.path.dirname(outfile_name)
159 if not os.path.exists(outfile_path):
160 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800161
Kevin Peng655f2392019-11-27 16:33:02 +0800162 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800163
Kevin Peng655f2392019-11-27 16:33:02 +0800164 outfile = io.open(outfile_name, "w", newline='\n')
165 outfile.write(template.render(context))
166 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800167
Kevin Peng655f2392019-11-27 16:33:02 +0800168 print ("Generation of files done")
Edison Ai48b2d9e2019-06-24 14:39:45 +0800169
Kevin Peng655f2392019-11-27 16:33:02 +0800170def parse_args():
171 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list')
172 parser.add_argument('-o', '--outdir'
173 , dest='outdir'
174 , required=False
175 , default=None
176 , metavar='out_dir'
177 , help='The root directory for generated files, the default is TF-M root folder.')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800178
Kevin Peng655f2392019-11-27 16:33:02 +0800179 parser.add_argument('-m', '--manifest'
180 , nargs='*'
181 , dest='manifest_args'
182 , required=False
183 , default=[]
184 , metavar='manifest'
185 , help='The secure partition manifest list file to parse, the default is '+ DEFAULT_MANIFEST_LIST + '. \
186 Or the manifest can be append to the default one by explicitly \"append\" it:\
187 -m manifest_to_append append')
188
189 parser.add_argument('-f', '--file-list'
190 , nargs='*'
191 , dest='gen_file_args'
192 , required=False
193 , default=[]
194 , metavar='file-list'
195 , help='The file descripes the file list to generate, the default is ' + DEFAULT_GEN_FILE_LIST + '. \
196 Or the file list can be append to the default one by explicitly \"append\" it:\
197 -f files_to_append append')
198
199 args = parser.parse_args()
200 manifest_args = args.manifest_args
201 gen_file_args = args.gen_file_args
202
203 if len(manifest_args) > 2 or len(gen_file_args) > 2:
204 parser.print_help()
205 exit(1)
206
207 if len(manifest_args) == 2 and (manifest_args[1] != 'append' and manifest_args[1] != ''):
208 parser.print_help()
209 exit(1)
210
211 if len(gen_file_args) == 2 and (gen_file_args[1] != 'append' and gen_file_args[1] != ''):
212 parser.print_help()
213 exit(1)
214
215 return args
216
217ENV = Environment(
218 loader = TemplateLoader(),
219 autoescape = select_autoescape(['html', 'xml']),
220 lstrip_blocks = True,
221 trim_blocks = True,
222 keep_trailing_newline = True
223 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100224
Miklos Balint470919c2018-05-22 17:51:29 +0200225def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100226 """
227 The entry point of the script.
228
229 Generates the output files based on the templates and the manifests.
230 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800231
Kevin Peng655f2392019-11-27 16:33:02 +0800232 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800233
Kevin Peng655f2392019-11-27 16:33:02 +0800234 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800235
Kevin Peng655f2392019-11-27 16:33:02 +0800236 manifest_args = args.manifest_args
237 gen_file_args = args.gen_file_args
238 OUT_DIR = args.outdir
239 append_manifest = False
240 append_gen_file = False
241
242 if len(manifest_args) == 2 and manifest_args[1] == 'append':
243 append_manifest = True
244
245 if len(gen_file_args) == 2 and gen_file_args[1] == 'append':
246 append_gen_file = True
247
248 if len(manifest_args) == 0:
249 manifest_list = DEFAULT_MANIFEST_LIST
250 else:
251 """
252 Only convert to abs path when value is not default
253 Because the default value is a fixed relative path to TF-M root folder,
254 it will be various to different execution path if converted to absolute path.
255 The same for gen_file_list
256 """
257 manifest_list = os.path.abspath(args.manifest_args[0])
258 if len(gen_file_args) == 0:
259 gen_file_list = DEFAULT_GEN_FILE_LIST
260 else:
261 gen_file_list = os.path.abspath(args.gen_file_args[0])
Shawn Shana9ad1e02019-08-07 15:49:48 +0800262
263 # Arguments could be relative path.
Kevin Peng655f2392019-11-27 16:33:02 +0800264 # Convert to absolute path as we are going to change diretory later
265 if OUT_DIR is not None:
266 OUT_DIR = os.path.abspath(OUT_DIR)
267
Shawn Shana9ad1e02019-08-07 15:49:48 +0800268 """
Kevin Peng655f2392019-11-27 16:33:02 +0800269 Relative path to TF-M root folder is supported in the manifests
270 and default value of manifest list and generated file list are relative to TF-M root folder as well,
271 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800272 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800273 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 +0800274 """
275 os.chdir(os.path.join(sys.path[0], ".."))
276
Kevin Peng655f2392019-11-27 16:33:02 +0800277 manifest_header_list, db = process_manifest(manifest_list, append_manifest)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100278
Edison Ai6e3f2a32019-06-11 15:29:05 +0800279 utilities = {}
280 context = {}
281
Kevin Peng655f2392019-11-27 16:33:02 +0800282 utilities['donotedit_warning']=donotedit_warning
283 utilities['manifest_header_list']=manifest_header_list
Miklos Balint470919c2018-05-22 17:51:29 +0200284
Kevin Peng655f2392019-11-27 16:33:02 +0800285 context['manifests'] = db
286 context['utilities'] = utilities
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100287
Kevin Peng655f2392019-11-27 16:33:02 +0800288 gen_files(context, gen_file_list, append_gen_file)
Miklos Balint470919c2018-05-22 17:51:29 +0200289
290if __name__ == "__main__":
291 main()