mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-08 05:43:53 +00:00
feat(sptool): python version of the sptool
To cope with the changes/design decisions in the implementation of boot protocol, from FF-A v1.1 specification in the S-EL2 SPM, we have changed the format of the sp pkg header. These changes need to be reflected in the sptool, used for packaging the SP binary, and the SP's FF-A manifest. Now the SP pkg can contain the boot information blob as defined by the FF-A specification. To cater for these changes, bring to the TF-A project an equivalent to the tool used in the Hafnium project. Signed-off-by: J-Alves <joao.alves@arm.com> Change-Id: I046f5d6e3c2ef0ba6c87f65302e127dedef34c28
This commit is contained in:
parent
a96a07bfb6
commit
2e82874cc9
1 changed files with 145 additions and 0 deletions
145
tools/sptool/sptool.py
Executable file
145
tools/sptool/sptool.py
Executable file
|
@ -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())
|
Loading…
Add table
Reference in a new issue