blob: 2cc96cb2130e40cbdbfad8134c2ac22487b4c048 [file] [log] [blame]
Manish Pandey3f90ad72020-01-14 11:52:05 +00001#!/usr/bin/python3
Anders Dellien836c64f2022-01-07 13:26:29 +00002# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
Manish Pandey3f90ad72020-01-14 11:52:05 +00003#
4# SPDX-License-Identifier: BSD-3-Clause
5
6"""
7This script is invoked by Make system and generates secure partition makefile.
8It expects platform provided secure partition layout file which contains list
9of Secure Partition Images and Partition manifests(PM).
10Layout file can exist outside of TF-A tree and the paths of Image and PM files
11must be relative to it.
12
13This script parses the layout file and generates a make file which updates
Manish Pandeyaaaeb312020-05-26 23:59:36 +010014FDT_SOURCES, FIP_ARGS, CRT_ARGS and SPTOOL_ARGS which are used in later build
15steps.
Imre Kis3f370fd2022-02-08 18:06:18 +010016If the SP entry in the layout file has a "uuid" field the scripts gets the UUID
17from there, otherwise it parses the associated partition manifest and extracts
18the UUID from there.
Manish Pandey3f90ad72020-01-14 11:52:05 +000019
20param1: Generated mk file "sp_gen.mk"
21param2: "SP_LAYOUT_FILE", json file containing platform provided information
22param3: plat out directory
Ruari Phipps571ed6b2020-07-24 16:20:57 +010023param4: CoT parameter
Manish Pandey3f90ad72020-01-14 11:52:05 +000024
25Generated "sp_gen.mk" file contains triplet of following information for each
26Secure Partition entry
27 FDT_SOURCES += sp1.dts
28 SPTOOL_ARGS += -i sp1.bin:sp1.dtb -o sp1.pkg
29 FIP_ARGS += --blob uuid=XXXXX-XXX...,file=sp1.pkg
Manish Pandeyaaaeb312020-05-26 23:59:36 +010030 CRT_ARGS += --sp-pkg1 sp1.pkg
Manish Pandey3f90ad72020-01-14 11:52:05 +000031
32A typical SP_LAYOUT_FILE file will look like
33{
34 "SP1" : {
35 "image": "sp1.bin",
36 "pm": "test/sp1.dts"
37 },
38
39 "SP2" : {
40 "image": "sp2.bin",
Imre Kis3f370fd2022-02-08 18:06:18 +010041 "pm": "test/sp2.dts",
42 "uuid": "1b1820fe-48f7-4175-8999-d51da00b7c9f"
Manish Pandey3f90ad72020-01-14 11:52:05 +000043 }
44
45 ...
46}
47
48"""
49
Manish Pandey3f90ad72020-01-14 11:52:05 +000050import json
51import os
52import re
53import sys
54import uuid
J-Alvesd10fb032022-03-21 14:11:43 +000055from spactions import SpSetupActions
Manish Pandey3f90ad72020-01-14 11:52:05 +000056
Ruari Phipps571ed6b2020-07-24 16:20:57 +010057MAX_SP = 8
J-Alvesd10fb032022-03-21 14:11:43 +000058UUID_LEN = 4
Manish Pandey3f90ad72020-01-14 11:52:05 +000059
J-Alvesd10fb032022-03-21 14:11:43 +000060# Some helper functions to access args propagated to the action functions in
61# SpSetupActions framework.
Manish Pandey3f90ad72020-01-14 11:52:05 +000062
J-Alvesd10fb032022-03-21 14:11:43 +000063def check_sp_mk_gen(args :dict):
64 if "sp_gen_mk" not in args.keys():
65 raise Exception(f"Path to file sp_gen.mk needs to be in 'args'.")
Ruari Phipps571ed6b2020-07-24 16:20:57 +010066
J-Alvesd10fb032022-03-21 14:11:43 +000067def check_out_dir(args :dict):
68 if "out_dir" not in args.keys() or not os.path.isdir(args["out_dir"]):
69 raise Exception("Define output folder with \'out_dir\' key.")
Ruari Phipps571ed6b2020-07-24 16:20:57 +010070
J-Alvesd10fb032022-03-21 14:11:43 +000071def check_sp_layout_dir(args :dict):
72 if "sp_layout_dir" not in args.keys() or not os.path.isdir(args["sp_layout_dir"]):
73 raise Exception("Define output folder with \'sp_layout_dir\' key.")
Ruari Phipps571ed6b2020-07-24 16:20:57 +010074
J-Alvesd10fb032022-03-21 14:11:43 +000075def write_to_sp_mk_gen(content, args :dict):
76 check_sp_mk_gen(args)
77 with open(args["sp_gen_mk"], "a") as f:
78 f.write(f"{content}\n")
Manish Pandey3f90ad72020-01-14 11:52:05 +000079
J-Alvesd10fb032022-03-21 14:11:43 +000080def get_sp_manifest_full_path(sp_node, args :dict):
81 check_sp_layout_dir(args)
82 return os.path.join(args["sp_layout_dir"], get_file_from_layout(sp_node["pm"]))
Manish Pandey3f90ad72020-01-14 11:52:05 +000083
J-Alvesd10fb032022-03-21 14:11:43 +000084def get_sp_img_full_path(sp_node, args :dict):
85 check_sp_layout_dir(args)
86 return os.path.join(args["sp_layout_dir"], get_file_from_layout(sp_node["image"]))
87
88def get_sp_pkg(sp, args :dict):
89 check_out_dir(args)
90 return os.path.join(args["out_dir"], f"{sp}.pkg")
91
92def is_line_in_sp_gen(line, args :dict):
93 with open(args["sp_gen_mk"], "r") as f:
94 sppkg_rule = [l for l in f if line in l]
95 return len(sppkg_rule) is not 0
Olivier Deprez18909842021-05-11 09:43:37 +020096
J-Alvesd10fb032022-03-21 14:11:43 +000097def get_file_from_layout(node):
98 ''' Helper to fetch a file path from sp_layout.json. '''
99 if type(node) is dict and "file" in node.keys():
100 return node["file"]
101 return node
Manish Pandey3f90ad72020-01-14 11:52:05 +0000102
J-Alvesd10fb032022-03-21 14:11:43 +0000103def get_offset_from_layout(node):
104 ''' Helper to fetch an offset from sp_layout.json. '''
105 if type(node) is dict and "offset" in node.keys():
106 return int(node["offset"], 0)
107 return None
108
109def get_image_offset(node):
110 ''' Helper to fetch image offset from sp_layout.json '''
111 return get_offset_from_layout(node["image"])
112
113def get_pm_offset(node):
114 ''' Helper to fetch pm offset from sp_layout.json '''
115 return get_offset_from_layout(node["pm"])
116
117@SpSetupActions.sp_action(global_action=True)
118def check_max_sps(sp_layout, _, args :dict):
119 ''' Check validate the maximum number of SPs is respected. '''
120 if len(sp_layout.keys()) > MAX_SP:
121 raise Exception(f"Too many SPs in SP layout file. Max: {MAX_SP}")
122 return args
Manish Pandey3f90ad72020-01-14 11:52:05 +0000123
J-Alvesd10fb032022-03-21 14:11:43 +0000124@SpSetupActions.sp_action
125def gen_fdt_sources(sp_layout, sp, args :dict):
126 ''' Generate FDT_SOURCES values for a given SP. '''
127 manifest_path = get_sp_manifest_full_path(sp_layout[sp], args)
128 write_to_sp_mk_gen(f"FDT_SOURCES += {manifest_path}", args)
129 return args
Manish Pandeyaaaeb312020-05-26 23:59:36 +0100130
J-Alvesd10fb032022-03-21 14:11:43 +0000131@SpSetupActions.sp_action
132def gen_sptool_args(sp_layout, sp, args):
133 ''' Generate sptool arguments to generate SP Pkg for a given SP. '''
134 check_out_dir(args)
135 check_sp_layout_dir(args)
136 sp_pkg = get_sp_pkg(sp, args)
137 sp_dtb_name = os.path.basename(sp_layout[sp]["pm"])[:-1] + "b"
138 sp_dtb = os.path.join(args["out_dir"], f"fdts/{sp_dtb_name}")
139 sp_bin = os.path.join(args["sp_layout_dir"], sp_layout[sp]["image"])
140 write_to_sp_mk_gen(f"SPTOOL_ARGS += -i {sp_bin}:{sp_dtb} -o {sp_pkg}\n", args)
141 return args
142
143@SpSetupActions.sp_action(global_action=True, exec_order=1)
144def check_dualroot(sp_layout, _, args :dict):
145 ''' Validate the amount of SPs from SiP and Platform owners. '''
146 if not args.get("dualroot"):
147 return args
148 args["split"] = int(MAX_SP / 2)
149 owners = [sp_layout[sp].get("owner") for sp in sp_layout]
150 args["plat_max_count"] = owners.count("Plat")
151 # If it is owned by the platform owner, it is assigned to the SiP.
152 args["sip_max_count"] = len(sp_layout.keys()) - args["plat_max_count"]
153 if args["sip_max_count"] > args["split"] or args["sip_max_count"] > args["split"]:
154 print(f"WARN: SiP Secure Partitions should not be more than {args['split']}")
155 # Counters for gen_crt_args.
156 args["sip_count"] = 1
157 args["plat_count"] = 1
158 return args
159
160@SpSetupActions.sp_action
161def gen_crt_args(sp_layout, sp, args :dict):
162 ''' Append CRT_ARGS. '''
163 # If "dualroot" is configured, 'sp_pkg_idx' depends on whether the SP is owned
164 # by the "SiP" or the "Plat".
165 if args.get("dualroot"):
166 # If the owner is not specified as "Plat", default to "SiP".
167 if sp_layout[sp].get("owner") == "Plat":
168 if args["plat_count"] > args["plat_max_count"]:
169 raise ValueError("plat_count can't surpass plat_max_count in args.")
170 sp_pkg_idx = args["plat_count"] + args["split"]
171 args["plat_count"] += 1
172 else:
173 if args["sip_count"] > args["sip_max_count"]:
174 raise ValueError("sip_count can't surpass sip_max_count in args.")
175 sp_pkg_idx = args["sip_count"]
176 args["sip_count"] += 1
177 else:
178 sp_pkg_idx = [k for k in sp_layout.keys()].index(sp) + 1
179 write_to_sp_mk_gen(f"CRT_ARGS += --sp-pkg{sp_pkg_idx} {get_sp_pkg(sp, args)}\n", args)
180 return args
181
182@SpSetupActions.sp_action
183def gen_fiptool_args(sp_layout, sp, args :dict):
184 ''' Generate arguments for the FIP Tool. '''
185 if "uuid" in sp_layout[sp]:
186 # Extract the UUID from the JSON file if the SP entry has a 'uuid' field
187 uuid_std = uuid.UUID(data[key]['uuid'])
188 else:
189 with open(get_sp_manifest_full_path(sp_layout[sp], args), "r") as pm_f:
190 uuid_lines = [l for l in pm_f if 'uuid' in l]
191 assert(len(uuid_lines) is 1)
192 # The uuid field in SP manifest is the little endian representation
193 # mapped to arguments as described in SMCCC section 5.3.
194 # Convert each unsigned integer value to a big endian representation
195 # required by fiptool.
196 uuid_parsed = re.findall("0x([0-9a-f]+)", uuid_lines[0])
197 y = list(map(bytearray.fromhex, uuid_parsed))
198 z = [int.from_bytes(i, byteorder='little', signed=False) for i in y]
199 uuid_std = uuid.UUID(f'{z[0]:08x}{z[1]:08x}{z[2]:08x}{z[3]:08x}')
200 write_to_sp_mk_gen(f"FIP_ARGS += --blob uuid={str(uuid_std)},file={get_sp_pkg(sp, args)}\n", args)
201 return args
202
203def init_sp_actions(sys):
204 sp_layout_file = os.path.abspath(sys.argv[2])
205 with open(sp_layout_file) as json_file:
206 sp_layout = json.load(json_file)
207 # Initialize arguments for the SP actions framework
208 args = {}
209 args["sp_gen_mk"] = os.path.abspath(sys.argv[1])
210 args["sp_layout_dir"] = os.path.dirname(sp_layout_file)
211 args["out_dir"] = os.path.abspath(sys.argv[3])
212 args["dualroot"] = sys.argv[4] == "dualroot"
213 #Clear content of file "sp_gen.mk".
214 with open(args["sp_gen_mk"], "w"):
215 None
216 return args, sp_layout
Ruari Phipps571ed6b2020-07-24 16:20:57 +0100217
J-Alvesd10fb032022-03-21 14:11:43 +0000218if __name__ == "__main__":
219 args, sp_layout = init_sp_actions(sys)
220 SpSetupActions.run_actions(sp_layout, args)