blob: 795d90a0424491b194037494818993ec38148e62 [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
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
Mate Toth-Pal36f21842018-11-08 16:12:51 +010028class TemplateLoader(BaseLoader):
29 """
30 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020031
Mate Toth-Pal36f21842018-11-08 16:12:51 +010032 An instance of this class is passed to the template engine. It is
33 responsible for reading the template file
34 """
35 def __init__(self):
36 pass
Miklos Balint470919c2018-05-22 17:51:29 +020037
Mate Toth-Pal36f21842018-11-08 16:12:51 +010038 def get_source(self, environment, template):
39 """
40 This function reads the template files.
41 For detailed documentation see:
42 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
43
44 Please note that this function always return 'false' as 'uptodate'
45 value, so the output file will always be generated.
46 """
47 if not os.path.isfile(template):
48 raise TemplateNotFound(template)
49 with open(template) as f:
50 source = f.read()
51 return source, template, False
52
Raef Colesf42f0882020-07-10 10:01:58 +010053def process_manifest(manifest_list_files):
Mate Toth-Pal36f21842018-11-08 16:12:51 +010054 """
Kevin Peng655f2392019-11-27 16:33:02 +080055 Parse the input manifest, generate the data base for genereated files
56 and generate manifest header files.
Mate Toth-Pal36f21842018-11-08 16:12:51 +010057
58 Parameters
59 ----------
Raef Colesf42f0882020-07-10 10:01:58 +010060 manifest_list_files:
61 The manifest lists to parse.
Mate Toth-Pal36f21842018-11-08 16:12:51 +010062
63 Returns
64 -------
Kevin Peng655f2392019-11-27 16:33:02 +080065 The manifest header list and the data base.
Edison Ai48b2d9e2019-06-24 14:39:45 +080066 """
Kevin Peng655f2392019-11-27 16:33:02 +080067
68 db = []
Kevin Peng655f2392019-11-27 16:33:02 +080069 manifest_list = []
70
Raef Colesf42f0882020-07-10 10:01:58 +010071 for f in manifest_list_files:
72 with open(f) as manifest_list_yaml_file:
73 manifest_dic = yaml.safe_load(manifest_list_yaml_file)
Kevin Peng655f2392019-11-27 16:33:02 +080074 manifest_list.extend(manifest_dic["manifest_list"])
75
Mingyang Sund20999f2020-10-15 14:53:12 +080076 manifesttemplate = ENV.get_template('secure_fw/partitions/manifestfilename.template')
77 memorytemplate = ENV.get_template('secure_fw/partitions/partition_intermedia.template')
Kevin Peng655f2392019-11-27 16:33:02 +080078
edison.ai7b299f52020-07-16 15:44:18 +080079 print("Start to generate PSA manifests:")
Kevin Peng655f2392019-11-27 16:33:02 +080080 for manifest_item in manifest_list:
Raef Coles558487a2020-10-29 13:09:44 +000081 # Replace environment variables in the manifest path
Kevin Peng655f2392019-11-27 16:33:02 +080082 manifest_path = os.path.expandvars(manifest_item['manifest'])
83 file = open(manifest_path)
84 manifest = yaml.safe_load(file)
85
Kevin Peng655f2392019-11-27 16:33:02 +080086 utilities = {}
87 utilities['donotedit_warning']=donotedit_warning
88
89 context = {}
90 context['manifest'] = manifest
91 context['attr'] = manifest_item
92 context['utilities'] = utilities
93
94 manifest_dir, manifest_name = os.path.split(manifest_path)
95 outfile_name = manifest_name.replace('yaml', 'h').replace('json', 'h')
96 context['file_name'] = outfile_name.replace('.h', '')
TTornblom7f92a732020-03-05 13:12:20 +010097 outfile_name = os.path.join(manifest_dir, "psa_manifest", outfile_name).replace('\\', '/')
Mingyang Sund20999f2020-10-15 14:53:12 +080098 intermediafile_name = os.path.join(manifest_dir, "auto_generated", 'intermedia_' + context['file_name'] + '.c').replace('\\', '/')
Kevin Peng655f2392019-11-27 16:33:02 +080099
Mingyang Sun4f012692020-10-16 14:04:49 +0800100 """
101 Remove the `source_path` portion of the filepaths, so that it can be
102 interpreted as a relative path from the OUT_DIR.
103 """
104 if 'source_path' in manifest_item:
Raef Coles558487a2020-10-29 13:09:44 +0000105 # Replace environment variables in the source path
106 source_path = os.path.expandvars(manifest_item['source_path'])
107 outfile_name = os.path.relpath(outfile_name, start = source_path)
Mingyang Sund20999f2020-10-15 14:53:12 +0800108 intermediafile_name = os.path.relpath(intermediafile_name, start = source_path)
Mingyang Sun4f012692020-10-16 14:04:49 +0800109
Mark Horvathbb3d37f2020-09-03 18:02:58 +0200110 db.append({"manifest": manifest, "attr": manifest_item, "header_file": outfile_name})
Kevin Peng655f2392019-11-27 16:33:02 +0800111
112 if OUT_DIR is not None:
113 outfile_name = os.path.join(OUT_DIR, outfile_name)
Mingyang Sund20999f2020-10-15 14:53:12 +0800114 intermediafile_name = os.path.join(OUT_DIR, intermediafile_name)
Kevin Peng655f2392019-11-27 16:33:02 +0800115
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)
Mingyang Sund20999f2020-10-15 14:53:12 +0800123 outfile.write(manifesttemplate.render(context))
Kevin Peng655f2392019-11-27 16:33:02 +0800124 outfile.close()
125
Mingyang Sund20999f2020-10-15 14:53:12 +0800126 intermediafile_path = os.path.dirname(intermediafile_name)
127 if not os.path.exists(intermediafile_path):
128 os.makedirs(intermediafile_path)
129
130 print ("Generating " + intermediafile_name)
131
132 memoutfile = io.open(intermediafile_name, "w", newline=None)
133 memoutfile.write(memorytemplate.render(context))
134 memoutfile.close()
135
Mark Horvathbb3d37f2020-09-03 18:02:58 +0200136 return db
Kevin Peng655f2392019-11-27 16:33:02 +0800137
Raef Colesf42f0882020-07-10 10:01:58 +0100138def gen_files(context, gen_file_lists):
Kevin Peng655f2392019-11-27 16:33:02 +0800139 """
140 Generate files according to the gen_file_list
Edison Ai48b2d9e2019-06-24 14:39:45 +0800141
142 Parameters
143 ----------
Raef Colesf42f0882020-07-10 10:01:58 +0100144 gen_file_lists:
145 The lists of files to generate
Edison Ai48b2d9e2019-06-24 14:39:45 +0800146 """
Kevin Peng655f2392019-11-27 16:33:02 +0800147 file_list = []
Shawn Shana9ad1e02019-08-07 15:49:48 +0800148
Raef Colesf42f0882020-07-10 10:01:58 +0100149 for f in gen_file_lists:
150 with open(f) as file_list_yaml_file:
Kevin Peng655f2392019-11-27 16:33:02 +0800151 file_list_yaml = yaml.safe_load(file_list_yaml_file)
152 file_list.extend(file_list_yaml["file_list"])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800153
edison.ai7b299f52020-07-16 15:44:18 +0800154 print("Start to generate file from the generated list:")
Kevin Peng655f2392019-11-27 16:33:02 +0800155 for file in file_list:
Raef Coles558487a2020-10-29 13:09:44 +0000156 # Replace environment variables in the output filepath
Kevin Peng655f2392019-11-27 16:33:02 +0800157 outfile_name = os.path.expandvars(file["output"])
Raef Coles558487a2020-10-29 13:09:44 +0000158 # Replace environment variables in the template filepath
Kevin Peng1ec5e7c2019-11-29 10:52:00 +0800159 templatefile_name = os.path.expandvars(file["template"])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800160
Kevin Peng655f2392019-11-27 16:33:02 +0800161 if OUT_DIR is not None:
162 outfile_name = os.path.join(OUT_DIR, outfile_name)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800163
edison.ai7b299f52020-07-16 15:44:18 +0800164 print ("Generating " + outfile_name)
165
Kevin Peng655f2392019-11-27 16:33:02 +0800166 outfile_path = os.path.dirname(outfile_name)
167 if not os.path.exists(outfile_path):
168 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800169
Kevin Peng655f2392019-11-27 16:33:02 +0800170 template = ENV.get_template(templatefile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800171
TTornblom441a0702020-04-28 12:40:42 +0200172 outfile = io.open(outfile_name, "w", newline=None)
Kevin Peng655f2392019-11-27 16:33:02 +0800173 outfile.write(template.render(context))
174 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800175
Kevin Peng655f2392019-11-27 16:33:02 +0800176 print ("Generation of files done")
Edison Ai48b2d9e2019-06-24 14:39:45 +0800177
Kevin Peng655f2392019-11-27 16:33:02 +0800178def parse_args():
Raef Coles558487a2020-10-29 13:09:44 +0000179 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list',
180 epilog='Note that environment variables in template files will be replaced with their values')
181
Kevin Peng655f2392019-11-27 16:33:02 +0800182 parser.add_argument('-o', '--outdir'
183 , dest='outdir'
184 , required=False
185 , default=None
186 , metavar='out_dir'
187 , help='The root directory for generated files, the default is TF-M root folder.')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800188
Kevin Peng655f2392019-11-27 16:33:02 +0800189 parser.add_argument('-m', '--manifest'
Raef Colesf42f0882020-07-10 10:01:58 +0100190 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800191 , dest='manifest_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100192 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800193 , metavar='manifest'
Raef Colesf42f0882020-07-10 10:01:58 +0100194 , help='A set of secure partition manifest lists to parse')
Kevin Peng655f2392019-11-27 16:33:02 +0800195
196 parser.add_argument('-f', '--file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100197 , nargs='+'
Kevin Peng655f2392019-11-27 16:33:02 +0800198 , dest='gen_file_args'
Raef Colesf42f0882020-07-10 10:01:58 +0100199 , required=True
Kevin Peng655f2392019-11-27 16:33:02 +0800200 , metavar='file-list'
Raef Colesf42f0882020-07-10 10:01:58 +0100201 , help='These files descripe the file list to generate')
Kevin Peng655f2392019-11-27 16:33:02 +0800202
203 args = parser.parse_args()
204 manifest_args = args.manifest_args
205 gen_file_args = args.gen_file_args
206
Kevin Peng655f2392019-11-27 16:33:02 +0800207 return args
208
209ENV = Environment(
210 loader = TemplateLoader(),
211 autoescape = select_autoescape(['html', 'xml']),
212 lstrip_blocks = True,
213 trim_blocks = True,
214 keep_trailing_newline = True
215 )
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100216
Miklos Balint470919c2018-05-22 17:51:29 +0200217def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100218 """
219 The entry point of the script.
220
221 Generates the output files based on the templates and the manifests.
222 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800223
Kevin Peng655f2392019-11-27 16:33:02 +0800224 global OUT_DIR
Shawn Shana9ad1e02019-08-07 15:49:48 +0800225
Kevin Peng655f2392019-11-27 16:33:02 +0800226 args = parse_args()
Shawn Shana9ad1e02019-08-07 15:49:48 +0800227
Kevin Peng655f2392019-11-27 16:33:02 +0800228 manifest_args = args.manifest_args
229 gen_file_args = args.gen_file_args
230 OUT_DIR = args.outdir
Kevin Peng655f2392019-11-27 16:33:02 +0800231
Raef Coles558487a2020-10-29 13:09:44 +0000232 manifest_list = [os.path.abspath(x) for x in args.manifest_args]
233 gen_file_list = [os.path.abspath(x) for x in args.gen_file_args]
Shawn Shana9ad1e02019-08-07 15:49:48 +0800234
235 # Arguments could be relative path.
Kevin Peng655f2392019-11-27 16:33:02 +0800236 # Convert to absolute path as we are going to change diretory later
237 if OUT_DIR is not None:
238 OUT_DIR = os.path.abspath(OUT_DIR)
239
Shawn Shana9ad1e02019-08-07 15:49:48 +0800240 """
Kevin Peng655f2392019-11-27 16:33:02 +0800241 Relative path to TF-M root folder is supported in the manifests
242 and default value of manifest list and generated file list are relative to TF-M root folder as well,
243 so first change directory to TF-M root folder.
Shawn Shana9ad1e02019-08-07 15:49:48 +0800244 By doing this, the script can be executed anywhere
Kevin Peng655f2392019-11-27 16:33:02 +0800245 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 +0800246 """
247 os.chdir(os.path.join(sys.path[0], ".."))
248
Mark Horvathbb3d37f2020-09-03 18:02:58 +0200249 db = process_manifest(manifest_list)
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100250
Edison Ai6e3f2a32019-06-11 15:29:05 +0800251 utilities = {}
252 context = {}
253
Kevin Peng655f2392019-11-27 16:33:02 +0800254 utilities['donotedit_warning']=donotedit_warning
Miklos Balint470919c2018-05-22 17:51:29 +0200255
Kevin Peng655f2392019-11-27 16:33:02 +0800256 context['manifests'] = db
257 context['utilities'] = utilities
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100258
Raef Colesf42f0882020-07-10 10:01:58 +0100259 gen_files(context, gen_file_list)
Miklos Balint470919c2018-05-22 17:51:29 +0200260
261if __name__ == "__main__":
262 main()