blob: 46fc36afeeff9c57694cbdd96b48149387d07283 [file] [log] [blame]
Olivier Deprez06c4cbd2020-10-02 15:31:33 +02001#!/usr/bin/env python3
2#
3# Copyright 2020 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"""Script which generates a Secure Partition package.
10https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager.html#secure-partition-packages
11"""
12
13import argparse
14import sys
15from shutil import copyfileobj
16import os
17
18HF_PAGE_SIZE = 0x1000
19HEADER_ELEMENT_BYTES = 4 # bytes
20HEADER_LEN = 6
21
22MANIFEST_IMAGE_SPLITTER=':'
23def split_dtb_bin(i : str):
24 return i.split(MANIFEST_IMAGE_SPLITTER)
25
26def align_to_page(n):
27 return HF_PAGE_SIZE * \
28 (round(n / HF_PAGE_SIZE) + \
29 (1 if n % HF_PAGE_SIZE else 0))
30
31def to_bytes(value):
32 return int(value).to_bytes(4, 'little')
33
34class sp_pkg_info:
35 def __init__(self, manifest_path : str, image_path : str, include_header = True):
36 if not os.path.isfile(manifest_path) or not os.path.isfile(image_path):
37 raise Exception(f"Parameters should be path. \
38 manifest: {manifest_path}; image: {image_path}")
39 self.manifest_path = manifest_path
40 self.image_path = image_path
41 self.include_header = include_header
42
43 def __str__(self):
44 return \
45 f'''-------------------SP package Info------------------------
46 header:{self.header}
47 manifest: {self.manifest_path}
48 image: {self.image_path}
49 '''
50
51 @property
52 def magic(self):
53 return "SPKG".encode()
54
55 @property
56 def version(self):
57 return 1
58
59 @property
60 def manifest_offset(self):
61 return self.header_size if self.include_header else 0
62
63 @property
64 def manifest_size(self):
65 return os.path.getsize(self.manifest_path)
66
67 @property
68 def image_offset(self):
69 return align_to_page(self.manifest_offset + self.manifest_size)
70
71 @property
72 def image_size(self):
73 return os.path.getsize(self.image_path)
74
75 @property
76 def header(self):
77 return [self.magic,
78 self.version,
79 self.manifest_offset,
80 self.manifest_size,
81 self.image_offset,
82 self.image_size]
83
84 @property
85 def header_size(self):
86 return (HEADER_ELEMENT_BYTES * HEADER_LEN)
87
88 def generate_package(self, f_out : str):
89 with open(f_out, "wb+") as output:
90 if self.include_header is True:
91 for h in self.header:
92 to_write = h if type(h) is bytes else to_bytes(h)
93 output.write(to_write)
94 with open(self.manifest_path, "rb") as manifest:
95 copyfileobj(manifest, output)
96 output.seek(self.image_offset, 0)
97 with open(self.image_path, "rb") as image:
98 copyfileobj(image, output)
99
100def Main():
101 parser = argparse.ArgumentParser()
102 parser.add_argument("-i", required=True,
103 help="Add Secure Partition image and Manifest blob "
104 "(specified in two paths) separated by a colon).")
105 parser.add_argument("-o", required=True, help="Set output file path.")
106 parser.add_argument("-n", required=False, action="store_true", default=False,
107 help="Generate package without header.")
108 args = parser.parse_args()
109
110 if not os.path.exists(os.path.dirname(args.o)):
111 raise Exception("Provide a valid output file path!\n")
112
113 image_path, manifest_path = split_dtb_bin(args.i)
114 pkg = sp_pkg_info(manifest_path, image_path, not args.n)
115 pkg.generate_package(args.o)
116
117 return 0
118
119if __name__ == "__main__":
120 sys.exit(Main())