mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 01:54:22 +00:00
feat(tlc): add --align argument
Extended the command line interface to receive an alignment argument. TLC tool will align the data of the TEs accordingly. Signed-off-by: J-Alves <joao.alves@arm.com> Change-Id: I281b0b4c1851d58377bf6b31fcee03ee2f53367b
This commit is contained in:
parent
03c2660f75
commit
c4c8e26a69
4 changed files with 83 additions and 15 deletions
|
@ -17,6 +17,7 @@ from unittest import mock
|
||||||
import pytest
|
import pytest
|
||||||
import yaml
|
import yaml
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
|
from conftest import generate_random_bytes
|
||||||
|
|
||||||
from tlc.cli import cli
|
from tlc.cli import cli
|
||||||
from tlc.te import TransferEntry
|
from tlc.te import TransferEntry
|
||||||
|
@ -32,6 +33,22 @@ def test_create_empty_tl(tmpdir):
|
||||||
assert TransferList.fromfile(test_file) is not None
|
assert TransferList.fromfile(test_file) is not None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("align", [4, 6, 12, 13])
|
||||||
|
def test_create_with_align(align, tlcrunner, tmpdir):
|
||||||
|
tl_file = tmpdir.join("tl.bin").strpath
|
||||||
|
tlcrunner.invoke(cli, ["create", "-s", "10000", "-a", align, tl_file])
|
||||||
|
|
||||||
|
blob = tmpdir.join("blob.bin")
|
||||||
|
|
||||||
|
blob.write_binary(generate_random_bytes(0x200))
|
||||||
|
tlcrunner.invoke(cli, ["add", "--entry", 1, blob.strpath, tl_file])
|
||||||
|
|
||||||
|
tl = TransferList.fromfile(tl_file)
|
||||||
|
te = tl.entries[-1]
|
||||||
|
assert tl.alignment == align
|
||||||
|
assert (te.offset + te.hdr_size) % (1 << align) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_create_with_fdt(tmpdir):
|
def test_create_with_fdt(tmpdir):
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
fdt = tmpdir.join("fdt.dtb")
|
fdt = tmpdir.join("fdt.dtb")
|
||||||
|
@ -69,6 +86,20 @@ def test_add_multiple_entries(tlcrunner, tlc_entries, tmptlstr):
|
||||||
assert len(tl.entries) == len(tlc_entries)
|
assert len(tl.entries) == len(tlc_entries)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("align", [4, 6, 12, 13])
|
||||||
|
def test_cli_add_entry_with_align(align, tlcrunner, tmpdir, tmptlstr):
|
||||||
|
blob = tmpdir.join("blob.bin")
|
||||||
|
blob.write_binary(bytes(0x100))
|
||||||
|
|
||||||
|
tlcrunner.invoke(cli, ["add", "--align", align, "--entry", 1, blob, tmptlstr])
|
||||||
|
tl = TransferList.fromfile(tmptlstr)
|
||||||
|
te = tl.entries[-1]
|
||||||
|
|
||||||
|
print(tl, *(te for te in tl.entries), sep="\n---------------\n")
|
||||||
|
assert (te.offset + te.hdr_size) % (1 << align) == 0
|
||||||
|
assert tl.alignment == align
|
||||||
|
|
||||||
|
|
||||||
def test_info(tlcrunner, tmptlstr, tmpfdt):
|
def test_info(tlcrunner, tmptlstr, tmpfdt):
|
||||||
tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
|
tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
|
||||||
tlcrunner.invoke(cli, ["add", "--fdt", tmpfdt.strpath, tmptlstr])
|
tlcrunner.invoke(cli, ["add", "--fdt", tmpfdt.strpath, tmptlstr])
|
||||||
|
|
|
@ -157,7 +157,7 @@ def test_single_te_transfer_list(tag_id, data, tmpdir):
|
||||||
assert f.read(te.data_size) == te.data
|
assert f.read(te.data_size) == te.data
|
||||||
|
|
||||||
|
|
||||||
def test_write_multiple_tes_to_file(tmpdir, random_entries):
|
def test_write_multiple_tes_to_file(tmpdir, random_entries, random_entry):
|
||||||
"""Check that we can create a TL with multiple TE's."""
|
"""Check that we can create a TL with multiple TE's."""
|
||||||
test_file = tmpdir.join("test_tl_blob.bin")
|
test_file = tmpdir.join("test_tl_blob.bin")
|
||||||
tl = TransferList(0x4000)
|
tl = TransferList(0x4000)
|
||||||
|
@ -166,6 +166,10 @@ def test_write_multiple_tes_to_file(tmpdir, random_entries):
|
||||||
for tag_id, data in _test_entries:
|
for tag_id, data in _test_entries:
|
||||||
tl.add_transfer_entry(tag_id, data)
|
tl.add_transfer_entry(tag_id, data)
|
||||||
|
|
||||||
|
# Add a few entries with special alignment requirements
|
||||||
|
blob_id, blob = random_entry(0x200)
|
||||||
|
tl.add_transfer_entry(blob_id, blob, data_align=12)
|
||||||
|
|
||||||
tl.write_to_file(test_file)
|
tl.write_to_file(test_file)
|
||||||
|
|
||||||
with open(test_file, "rb") as f:
|
with open(test_file, "rb") as f:
|
||||||
|
@ -180,6 +184,13 @@ def test_write_multiple_tes_to_file(tmpdir, random_entries):
|
||||||
data_size = int.from_bytes(f.read(4), "little")
|
data_size = int.from_bytes(f.read(4), "little")
|
||||||
assert f.read(data_size) == data
|
assert f.read(data_size) == data
|
||||||
|
|
||||||
|
f.seek(int(math.ceil(f.tell() / (1 << 12)) * (1 << 12)) - 8)
|
||||||
|
assert int.from_bytes(f.read(3), "little") == blob_id
|
||||||
|
assert int.from_bytes(f.read(1), "little") == TransferEntry.hdr_size
|
||||||
|
# Make sure the data in the TE matches the data in the original case
|
||||||
|
data_size = int.from_bytes(f.read(4), "little")
|
||||||
|
assert f.read(data_size) == blob
|
||||||
|
|
||||||
# padding is added to align TE's, make sure padding is added to the size of
|
# padding is added to align TE's, make sure padding is added to the size of
|
||||||
# the TL by checking we don't overflow.
|
# the TL by checking we don't overflow.
|
||||||
assert f.tell() <= tl.size
|
assert f.tell() <= tl.size
|
||||||
|
|
|
@ -26,6 +26,14 @@ def cli():
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@click.argument("filename", type=click.Path(dir_okay=False))
|
@click.argument("filename", type=click.Path(dir_okay=False))
|
||||||
|
@click.option(
|
||||||
|
"-a",
|
||||||
|
"--align",
|
||||||
|
type=int,
|
||||||
|
default=3,
|
||||||
|
show_default=True,
|
||||||
|
help="Set alignment in powers of 2 (e.g., -a 3 for 8 byte alignment).",
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"-s", "--size", default=0x1000, type=int, help="Maximum size of the Transfer List"
|
"-s", "--size", default=0x1000, type=int, help="Maximum size of the Transfer List"
|
||||||
)
|
)
|
||||||
|
@ -51,7 +59,7 @@ def cli():
|
||||||
type=click.Path(exists=True),
|
type=click.Path(exists=True),
|
||||||
help="Create the transfer list from a YAML config file.",
|
help="Create the transfer list from a YAML config file.",
|
||||||
)
|
)
|
||||||
def create(filename, size, fdt, entry, flags, from_yaml):
|
def create(filename, align, size, fdt, entry, flags, from_yaml):
|
||||||
"""Create a new Transfer List."""
|
"""Create a new Transfer List."""
|
||||||
try:
|
try:
|
||||||
if from_yaml:
|
if from_yaml:
|
||||||
|
@ -60,12 +68,12 @@ def create(filename, size, fdt, entry, flags, from_yaml):
|
||||||
|
|
||||||
tl = TransferList.from_dict(config)
|
tl = TransferList.from_dict(config)
|
||||||
else:
|
else:
|
||||||
tl = TransferList(size)
|
tl = TransferList(size, alignment=align)
|
||||||
|
|
||||||
entry = (*entry, (1, fdt)) if fdt else entry
|
entry = (*entry, (1, fdt)) if fdt else entry
|
||||||
|
|
||||||
for id, path in entry:
|
for id, path in entry:
|
||||||
tl.add_transfer_entry_from_file(id, path)
|
tl.add_transfer_entry_from_file(id, path, data_align=align)
|
||||||
except MemoryError as mem_excp:
|
except MemoryError as mem_excp:
|
||||||
raise MemoryError(
|
raise MemoryError(
|
||||||
"TL max size exceeded, consider increasing with the option -s"
|
"TL max size exceeded, consider increasing with the option -s"
|
||||||
|
@ -133,19 +141,24 @@ def remove(filename, tags):
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
|
@click.option(
|
||||||
|
"-a",
|
||||||
|
"--align",
|
||||||
|
type=int,
|
||||||
|
help="Set alignment in powers of 2 (e.g., -a 3 for 8 byte alignment).",
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--entry",
|
"--entry",
|
||||||
type=(int, click.Path(exists=True)),
|
type=(int, click.Path(exists=True)),
|
||||||
multiple=True,
|
multiple=True,
|
||||||
help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
|
help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
|
||||||
)
|
)
|
||||||
def add(filename, entry):
|
@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
|
||||||
|
def add(align, entry, filename):
|
||||||
"""Update an existing Transfer List with given images."""
|
"""Update an existing Transfer List with given images."""
|
||||||
tl = TransferList.fromfile(filename)
|
tl = TransferList.fromfile(filename)
|
||||||
|
|
||||||
for id, path in entry:
|
for id, path in entry:
|
||||||
tl.add_transfer_entry_from_file(id, path)
|
tl.add_transfer_entry_from_file(id, path, data_align=align)
|
||||||
|
|
||||||
tl.write_to_file(filename)
|
tl.write_to_file(filename)
|
||||||
|
|
||||||
|
|
|
@ -86,11 +86,14 @@ class TransferList:
|
||||||
granule = 8
|
granule = 8
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, max_size: int = hdr_size, flags: int = TRANSFER_LIST_ENABLE_CHECKSUM
|
self,
|
||||||
|
max_size: int = hdr_size,
|
||||||
|
flags: int = TRANSFER_LIST_ENABLE_CHECKSUM,
|
||||||
|
alignment: int = 3,
|
||||||
) -> None:
|
) -> None:
|
||||||
assert max_size >= self.hdr_size
|
assert max_size >= self.hdr_size
|
||||||
self.checksum: int = 0
|
self.checksum: int = 0
|
||||||
self.alignment: int = 3
|
self.alignment: int = alignment
|
||||||
self.size = self.hdr_size
|
self.size = self.hdr_size
|
||||||
self.total_size = max_size
|
self.total_size = max_size
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
|
@ -163,10 +166,14 @@ class TransferList:
|
||||||
# get settings from config and set defaults
|
# get settings from config and set defaults
|
||||||
max_size = config.get("max_size", 0x1000)
|
max_size = config.get("max_size", 0x1000)
|
||||||
has_checksum = config.get("has_checksum", True)
|
has_checksum = config.get("has_checksum", True)
|
||||||
|
align = config.get("alignment", None)
|
||||||
|
|
||||||
flags = TRANSFER_LIST_ENABLE_CHECKSUM if has_checksum else 0
|
flags = TRANSFER_LIST_ENABLE_CHECKSUM if has_checksum else 0
|
||||||
|
|
||||||
tl = cls(max_size, flags)
|
if align:
|
||||||
|
tl = cls(max_size, flags, alignment=align)
|
||||||
|
else:
|
||||||
|
tl = cls(max_size, flags)
|
||||||
|
|
||||||
for entry in config["entries"]:
|
for entry in config["entries"]:
|
||||||
tl.add_transfer_entry_from_dict(entry)
|
tl.add_transfer_entry_from_dict(entry)
|
||||||
|
@ -327,8 +334,12 @@ class TransferList:
|
||||||
te_format = transfer_entry_formats[tag_id]
|
te_format = transfer_entry_formats[tag_id]
|
||||||
tag_name = te_format["tag_name"]
|
tag_name = te_format["tag_name"]
|
||||||
|
|
||||||
|
align = entry.get("alignment", None)
|
||||||
|
|
||||||
if "blob_file_path" in entry:
|
if "blob_file_path" in entry:
|
||||||
return self.add_transfer_entry_from_file(tag_id, entry["blob_file_path"])
|
return self.add_transfer_entry_from_file(
|
||||||
|
tag_id, entry["blob_file_path"], data_align=align
|
||||||
|
)
|
||||||
elif tag_name == "tpm_event_log_table":
|
elif tag_name == "tpm_event_log_table":
|
||||||
with open(entry["event_log"], "rb") as f:
|
with open(entry["event_log"], "rb") as f:
|
||||||
event_log_data = f.read()
|
event_log_data = f.read()
|
||||||
|
@ -336,7 +347,7 @@ class TransferList:
|
||||||
flags_bytes = entry["flags"].to_bytes(4, "little")
|
flags_bytes = entry["flags"].to_bytes(4, "little")
|
||||||
data = flags_bytes + event_log_data
|
data = flags_bytes + event_log_data
|
||||||
|
|
||||||
return self.add_transfer_entry(tag_id, data)
|
return self.add_transfer_entry(tag_id, data, data_align=align)
|
||||||
elif tag_name == "exec_ep_info":
|
elif tag_name == "exec_ep_info":
|
||||||
return self.add_entry_point_info_transfer_entry(entry)
|
return self.add_entry_point_info_transfer_entry(entry)
|
||||||
elif "format" in te_format and "fields" in te_format:
|
elif "format" in te_format and "fields" in te_format:
|
||||||
|
@ -347,9 +358,11 @@ class TransferList:
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Invalid transfer entry {entry}.")
|
raise ValueError(f"Invalid transfer entry {entry}.")
|
||||||
|
|
||||||
def add_transfer_entry_from_file(self, tag_id: int, path: Path) -> TransferEntry:
|
def add_transfer_entry_from_file(
|
||||||
|
self, tag_id: int, path: Path, data_align: int = 0
|
||||||
|
) -> TransferEntry:
|
||||||
with open(path, "rb") as f:
|
with open(path, "rb") as f:
|
||||||
return self.add_transfer_entry(tag_id, f.read())
|
return self.add_transfer_entry(tag_id, f.read(), data_align=data_align)
|
||||||
|
|
||||||
def write_to_file(self, file: Path) -> None:
|
def write_to_file(self, file: Path) -> None:
|
||||||
"""Write the contents of the TL to a file."""
|
"""Write the contents of the TL to a file."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue