diff options
Diffstat (limited to 'tools/sptool/sptool.py')
-rwxr-xr-x | tools/sptool/sptool.py | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/tools/sptool/sptool.py b/tools/sptool/sptool.py new file mode 100755 index 0000000..ae7df92 --- /dev/null +++ b/tools/sptool/sptool.py @@ -0,0 +1,145 @@ +#!/usr/bin/python3 +# Copyright (c) 2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +# +# Copyright 2022 The Hafnium Authors. +# +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file or at +# https://opensource.org/licenses/BSD-3-Clause. + +""" +Script which generates a Secure Partition package. +https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager.html#secure-partition-packages +""" + +import argparse +from collections import namedtuple +import sys +from shutil import copyfileobj +import os + +HF_PAGE_SIZE = 0x1000 # bytes +HEADER_ELEMENT_BYTES = 4 # bytes +MANIFEST_IMAGE_SPLITTER=':' +PM_OFFSET_DEFAULT = "0x1000" +IMG_OFFSET_DEFAULT = "0x4000" + +def split_dtb_bin(i : str): + return i.split(MANIFEST_IMAGE_SPLITTER) + +def align_to_page(n): + return HF_PAGE_SIZE * \ + (round(n / HF_PAGE_SIZE) + \ + (1 if n % HF_PAGE_SIZE else 0)) + +def to_bytes(value): + return int(value).to_bytes(HEADER_ELEMENT_BYTES, 'little') + +class SpPkg: + def __init__(self, pm_path : str, img_path : str, pm_offset: int, + img_offset: int): + if not os.path.isfile(pm_path) or not os.path.isfile(img_path): + raise Exception(f"Parameters should be path. \ + manifest: {pm_path}; img: {img_path}") + self.pm_path = pm_path + self.img_path = img_path + self._SpPkgHeader = namedtuple("SpPkgHeader", + ("magic", "version", + "pm_offset", "pm_size", + "img_offset", "img_size")) + + if pm_offset >= img_offset: + raise ValueError("pm_offset must be smaller than img_offset") + + is_hfpage_aligned = lambda val : val % HF_PAGE_SIZE == 0 + if not is_hfpage_aligned(pm_offset) or not is_hfpage_aligned(img_offset): + raise ValueError(f"Offsets provided need to be page aligned: pm-{pm_offset}, img-{img_offset}") + + if img_offset - pm_offset < self.pm_size: + raise ValueError(f"pm_offset and img_offset do not fit the specified file:{pm_path})") + + self.pm_offset = pm_offset + self.img_offset = img_offset + + def __str__(self): + return \ + f'''--SP package Info-- + header:{self.header} + pm: {self.pm_path} + img: {self.img_path} + ''' + + @property + def magic(self): + return "SPKG".encode() + + @property + def version(self): + return 0x2 + + @property + def pm_size(self): + return os.path.getsize(self.pm_path) + + @property + def img_size(self): + return os.path.getsize(self.img_path) + + @property + def header(self): + return self._SpPkgHeader( + self.magic, + self.version, + self.pm_offset, + self.pm_size, + self.img_offset, + self.img_size) + + @property + def header_size(self): + return len(self._SpPkgHeader._fields) + + def generate(self, f_out : str): + with open(f_out, "wb+") as output: + for h in self.header: + to_write = h if type(h) is bytes else to_bytes(h) + output.write(to_write) + output.seek(self.pm_offset) + with open(self.pm_path, "rb") as pm: + copyfileobj(pm, output) + output.seek(self.img_offset) + with open(self.img_path, "rb") as img: + copyfileobj(img, output) + +def Main(): + parser = argparse.ArgumentParser() + parser.add_argument("-i", required=True, + help="path to partition's image and manifest separated by a colon.") + parser.add_argument("--pm-offset", required=False, default=PM_OFFSET_DEFAULT, + help="set partitition manifest offset.") + parser.add_argument("--img-offset", required=False, default=IMG_OFFSET_DEFAULT, + help="set partition image offset.") + parser.add_argument("-o", required=True, help="set output file path.") + parser.add_argument("-v", required=False, action="store_true", + help="print package information.") + args = parser.parse_args() + + if not os.path.exists(os.path.dirname(args.o)): + raise Exception("Provide a valid output file path!\n") + + image_path, manifest_path = split_dtb_bin(args.i) + pm_offset = int(args.pm_offset, 0) + img_offset = int(args.img_offset, 0) + pkg = SpPkg(manifest_path, image_path, pm_offset, img_offset) + pkg.generate(args.o) + + if args.v is True: + print(pkg) + + return 0 + +if __name__ == "__main__": + sys.exit(Main()) |