blob: 26a57e2e5b0b666ae277015433a4029fbd54d298 [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 " ***********/"
25manifest_list_yaml_file_path = os.path.join('tools', 'tfm_manifest_list.yaml')
26
Mate Toth-Pal36f21842018-11-08 16:12:51 +010027class TemplateLoader(BaseLoader):
28 """
29 Template loader class.
Miklos Balint470919c2018-05-22 17:51:29 +020030
Mate Toth-Pal36f21842018-11-08 16:12:51 +010031 An instance of this class is passed to the template engine. It is
32 responsible for reading the template file
33 """
34 def __init__(self):
35 pass
Miklos Balint470919c2018-05-22 17:51:29 +020036
Mate Toth-Pal36f21842018-11-08 16:12:51 +010037 def get_source(self, environment, template):
38 """
39 This function reads the template files.
40 For detailed documentation see:
41 http://jinja.pocoo.org/docs/2.10/api/#jinja2.BaseLoader.get_source
42
43 Please note that this function always return 'false' as 'uptodate'
44 value, so the output file will always be generated.
45 """
46 if not os.path.isfile(template):
47 raise TemplateNotFound(template)
48 with open(template) as f:
49 source = f.read()
50 return source, template, False
51
Miklos Balint470919c2018-05-22 17:51:29 +020052def load_manifest_list(file):
Mate Toth-Pal36f21842018-11-08 16:12:51 +010053 """
54 Load the substitution data from the manifests.
55
56 Parameters
57 ----------
58 file : file
59 A yaml file containing the manifest list
60
61 Returns
62 -------
63 list
64 The list of the contents of the manifest files, as generated by the yaml
65 parser.
66 """
Miklos Balint470919c2018-05-22 17:51:29 +020067 db = []
Mate Toth-Pal1bad7592019-10-21 08:56:49 +020068 manifest_list = yaml.safe_load(file)
Miklos Balint470919c2018-05-22 17:51:29 +020069 for item in manifest_list["manifest_list"]:
Shawn Shana9ad1e02019-08-07 15:49:48 +080070 manifest_path = os.path.expandvars(item['manifest'])
Miklos Balint470919c2018-05-22 17:51:29 +020071 try:
72 file = open(manifest_path)
Mate Toth-Pal1bad7592019-10-21 08:56:49 +020073 manifest = yaml.safe_load(file)
Miklos Balint470919c2018-05-22 17:51:29 +020074 db.append({"manifest": manifest, "attr": item})
75 except IOError:
Mate Toth-Pal36f21842018-11-08 16:12:51 +010076 raise Exception ("Manifest for "+item['name']+" cannot be opened at path "+item['manifest'])
Miklos Balint470919c2018-05-22 17:51:29 +020077
Mate Toth-Pal36f21842018-11-08 16:12:51 +010078 return db
79
Shawn Shana9ad1e02019-08-07 15:49:48 +080080def generate_manifestfilename(env, out_dir):
Edison Ai48b2d9e2019-06-24 14:39:45 +080081 """
82 Generate manifestfilename header file.
83
84 Parameters
85 ----------
86 env :
87 The instance of Environment.
Shawn Shana9ad1e02019-08-07 15:49:48 +080088 out_dir:
89 The root directory that files are generated to.
Edison Ai48b2d9e2019-06-24 14:39:45 +080090 """
Shawn Shana9ad1e02019-08-07 15:49:48 +080091
Edison Ai6e3f2a32019-06-11 15:29:05 +080092 manifest_header_list = []
Edison Ai48b2d9e2019-06-24 14:39:45 +080093 with open(manifest_list_yaml_file_path) as manifest_list_yaml_file:
Mate Toth-Pal1bad7592019-10-21 08:56:49 +020094 manifest_list = yaml.safe_load(manifest_list_yaml_file)
Edison Ai48b2d9e2019-06-24 14:39:45 +080095 templatefile_name = 'secure_fw/services/manifestfilename.template'
96 template = env.get_template(templatefile_name)
97
98 for manifest_file in manifest_list["manifest_list"]:
Shawn Shana9ad1e02019-08-07 15:49:48 +080099 manifest_path = os.path.expandvars(manifest_file['manifest'])
Edison Ai48b2d9e2019-06-24 14:39:45 +0800100 file = open(manifest_path)
Mate Toth-Pal1bad7592019-10-21 08:56:49 +0200101 manifest = yaml.safe_load(file)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800102
103 utilities = {}
104 utilities['donotedit_warning']=donotedit_warning
105
106 context = {}
107 context['manifest'] = manifest
108 context['attr'] = manifest_file
109 context['utilities'] = utilities
110
Shawn Shana9ad1e02019-08-07 15:49:48 +0800111 manifest_dir, manifest_name = os.path.split(manifest_path)
Jaykumar Pitambarbhai Patel48d298b2019-10-10 17:15:34 +0530112 outfile_name = manifest_name.replace('yaml', 'h').replace('json', 'h')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800113 context['file_name'] = outfile_name.replace('.h', '')
Shawn Shana9ad1e02019-08-07 15:49:48 +0800114 outfile_name = os.path.join(manifest_dir, "psa_manifest", outfile_name)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800115
Shawn Shana9ad1e02019-08-07 15:49:48 +0800116 manifest_header_list.append(outfile_name)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800117
Shawn Shana9ad1e02019-08-07 15:49:48 +0800118 if out_dir is not None:
119 outfile_name = os.path.join(out_dir, outfile_name)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800120
Shawn Shana9ad1e02019-08-07 15:49:48 +0800121 outfile_path = os.path.dirname(outfile_name)
122 if not os.path.exists(outfile_path):
123 os.makedirs(outfile_path)
Edison Ai48b2d9e2019-06-24 14:39:45 +0800124
Shawn Shana9ad1e02019-08-07 15:49:48 +0800125 print ("Generating " + outfile_name)
126
127 outfile = io.open(outfile_name, "w", newline='\n')
Edison Ai48b2d9e2019-06-24 14:39:45 +0800128 outfile.write(template.render(context))
129 outfile.close()
Edison Ai6e3f2a32019-06-11 15:29:05 +0800130 return manifest_header_list
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100131
Miklos Balint470919c2018-05-22 17:51:29 +0200132def main():
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100133 """
134 The entry point of the script.
135
136 Generates the output files based on the templates and the manifests.
137 """
Shawn Shana9ad1e02019-08-07 15:49:48 +0800138
139 parser = argparse.ArgumentParser(description='Parse secure partition manifest list and generate files listed by the file list')
140 parser.add_argument('-o', '--outdir'
141 , dest='outdir'
142 , required=False
143 , default=None
144 , metavar='out_dir'
145 , help='The root directory for generated files, the default is TF-M base folder.')
146
147 args = parser.parse_args()
148
149 out_dir = args.outdir
150
151 # Arguments could be relative path.
152 # Convert to absolute path as we are going to change directory later
153 if out_dir is not None:
154 out_dir = os.path.abspath(out_dir)
155 """
156 Relative path to TF-M base folder is supported in the manifests
157 and default value of manifest list and generated file list are relative to TF-M base folder as well,
158 so first change directory to TF-M base folder.
159 By doing this, the script can be executed anywhere
160 The script is located in <TF-M base folder>/tools, so sys.path[0]<location of the script>/.. is TF-M base folder.
161 """
162 os.chdir(os.path.join(sys.path[0], ".."))
163
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100164 env = Environment(
165 loader = TemplateLoader(),
166 autoescape = select_autoescape(['html', 'xml']),
167 lstrip_blocks = True,
168 trim_blocks = True,
169 keep_trailing_newline = True
170 )
171
Edison Ai6e3f2a32019-06-11 15:29:05 +0800172 # Generate manifestfilename
Shawn Shana9ad1e02019-08-07 15:49:48 +0800173 manifest_header_list = generate_manifestfilename(env, out_dir)
Edison Ai6e3f2a32019-06-11 15:29:05 +0800174 utilities = {}
175 context = {}
176
Edison Ai48b2d9e2019-06-24 14:39:45 +0800177 with open(manifest_list_yaml_file_path) as manifest_list_yaml_file:
Miklos Balint470919c2018-05-22 17:51:29 +0200178 # Read manifest list file, build database
179 db = load_manifest_list(manifest_list_yaml_file)
180
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100181 utilities['donotedit_warning']=donotedit_warning
Edison Ai6e3f2a32019-06-11 15:29:05 +0800182 utilities['manifest_header_list']=manifest_header_list
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100183
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100184 context['manifests'] = db
185 context['utilities'] = utilities
186
Miklos Balint3a05c9d2018-05-31 09:31:27 +0200187 with open(os.path.join('tools', 'tfm_generated_file_list.yaml')) \
188 as file_list_yaml_file:
189 # read list of files that need to be generated from templates using db
Mate Toth-Pal1bad7592019-10-21 08:56:49 +0200190 file_list_yaml = yaml.safe_load(file_list_yaml_file)
Miklos Balint3a05c9d2018-05-31 09:31:27 +0200191 file_list = file_list_yaml["file_list"]
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100192 for file in file_list:
Shawn Shana9ad1e02019-08-07 15:49:48 +0800193 outfile_name = os.path.expandvars(file["output"])
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100194 templatefile_name = outfile_name + '.template'
195
Shawn Shana9ad1e02019-08-07 15:49:48 +0800196 if out_dir is not None:
197 outfile_name = os.path.join(out_dir, outfile_name)
198
199 outfile_path = os.path.dirname(outfile_name)
200 if not os.path.exists(outfile_path):
201 os.makedirs(outfile_path)
202
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100203 print ("Generating " + outfile_name)
204
205 template = env.get_template(templatefile_name)
206
207 outfile = io.open(outfile_name, "w", newline='\n')
208 outfile.write(template.render(context))
209 outfile.close()
Edison Ai48b2d9e2019-06-24 14:39:45 +0800210
Mate Toth-Pal36f21842018-11-08 16:12:51 +0100211 print ("Generation of files done")
Miklos Balint470919c2018-05-22 17:51:29 +0200212
213if __name__ == "__main__":
214 main()