blob: 949bd9932a6e35b624a1b7fa4a52d8b8b2be943d [file] [log] [blame]
J-Alvesf39076d2022-03-02 14:01:42 +00001#!/usr/bin/env python3
2#
3# Copyright 2022 The Hafnium Authors.
4#
5# Use of this source code is governed by a BSD-style
6# license that can be found in the LICENSE file or at
7# https://opensource.org/licenses/BSD-3-Clause.
8
9"""
10Script which generates a Secure Partition package.
11https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager.html#secure-partition-packages
12"""
13
14import argparse
15from collections import namedtuple
16import sys
17from shutil import copyfileobj
18import os
19
20HF_PAGE_SIZE = 0x1000 # bytes
21HEADER_ELEMENT_BYTES = 4 # bytes
22MANIFEST_IMAGE_SPLITTER=':'
23PM_OFFSET_DEFAULT = "0x1000"
24IMG_OFFSET_DEFAULT = "0x4000"
25
26def split_dtb_bin(i : str):
27 return i.split(MANIFEST_IMAGE_SPLITTER)
28
29def align_to_page(n):
30 return HF_PAGE_SIZE * \
31 (round(n / HF_PAGE_SIZE) + \
32 (1 if n % HF_PAGE_SIZE else 0))
33
34def to_bytes(value):
35 return int(value).to_bytes(HEADER_ELEMENT_BYTES, 'little')
36
37class SpPkg:
38 def __init__(self, pm_path : str, img_path : str, pm_offset: int,
39 img_offset: int):
40 if not os.path.isfile(pm_path) or not os.path.isfile(img_path):
41 raise Exception(f"Parameters should be path. \
42 manifest: {pm_path}; img: {img_path}")
43 self.pm_path = pm_path
44 self.img_path = img_path
45 self._SpPkgHeader = namedtuple("SpPkgHeader",
46 ("magic", "version",
47 "pm_offset", "pm_size",
48 "img_offset", "img_size"))
49
50 if pm_offset >= img_offset:
51 raise ValueError("pm_offset must be smaller than img_offset")
52
53 is_hfpage_aligned = lambda val : val % HF_PAGE_SIZE == 0
54 if not is_hfpage_aligned(pm_offset) or not is_hfpage_aligned(img_offset):
55 raise ValueError(f"Offsets provided need to be page aligned: pm-{pm_offset}, img-{img_offset}")
56
57 if img_offset - pm_offset < self.pm_size:
58 raise ValueError(f"pm_offset and img_offset do not fit the specified file:{pm_path})")
59
60 self.pm_offset = pm_offset
61 self.img_offset = img_offset
62
63 def __str__(self):
64 return \
65 f'''--SP package Info--
66 header:{self.header}
67 pm: {self.pm_path}
68 img: {self.img_path}
69 '''
70
71 @property
72 def magic(self):
73 return "SPKG".encode()
74
75 @property
76 def version(self):
77 return 0x2
78
79 @property
80 def pm_size(self):
81 return os.path.getsize(self.pm_path)
82
83 @property
84 def img_size(self):
85 return os.path.getsize(self.img_path)
86
87 @property
88 def header(self):
89 return self._SpPkgHeader(
90 self.magic,
91 self.version,
92 self.pm_offset,
93 self.pm_size,
94 self.img_offset,
95 self.img_size)
96
97 @property
98 def header_size(self):
99 return len(self._SpPkgHeader._fields)
100
101 def generate(self, f_out : str):
102 with open(f_out, "wb+") as output:
103 for h in self.header:
104 to_write = h if type(h) is bytes else to_bytes(h)
105 output.write(to_write)
106 output.seek(self.pm_offset)
107 with open(self.pm_path, "rb") as pm:
108 copyfileobj(pm, output)
109 output.seek(self.img_offset)
110 with open(self.img_path, "rb") as img:
111 copyfileobj(img, output)
112
113def Main():
114 parser = argparse.ArgumentParser()
115 parser.add_argument("-i", required=True,
116 help="path to partition's image and manifest separated by a colon.")
117 parser.add_argument("--pm-offset", required=False, default=PM_OFFSET_DEFAULT,
118 help="set partitition manifest offset.")
119 parser.add_argument("--img-offset", required=False, default=IMG_OFFSET_DEFAULT,
120 help="set partition image offset.")
121 parser.add_argument("-o", required=True, help="set output file path.")
122 parser.add_argument("-v", required=False, action="store_true",
123 help="print package information.")
124 args = parser.parse_args()
125
126 if not os.path.exists(os.path.dirname(args.o)):
127 raise Exception("Provide a valid output file path!\n")
128
129 image_path, manifest_path = split_dtb_bin(args.i)
130 pm_offset = int(args.pm_offset, 0)
131 img_offset = int(args.img_offset, 0)
132 pkg = SpPkg(manifest_path, image_path, pm_offset, img_offset)
133 pkg.generate(args.o)
134
135 if args.v is True:
136 print(pkg)
137
138 return 0
139
140if __name__ == "__main__":
141 sys.exit(Main())