mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-18 02:24:18 +00:00

To facillitate our testing, add some fixtures to make it easier to generate transfer entry data. Change-Id: Ieb76e54e69f410f4f7e1b55fc2cff282e592d1a4 Signed-off-by: Harrison Mutai <harrison.mutai@arm.com>
235 lines
6.7 KiB
Python
235 lines
6.7 KiB
Python
#!/usr/bin/env python3
|
|
|
|
#
|
|
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
|
#
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
|
|
"""Contains unit tests for the types TransferEntry and TransferList."""
|
|
|
|
import math
|
|
|
|
import pytest
|
|
|
|
from tlc.te import TransferEntry
|
|
from tlc.tl import TransferList
|
|
|
|
large_data = 0xDEADBEEF.to_bytes(4, "big")
|
|
small_data = 0x1234.to_bytes(3, "big")
|
|
test_entries = [
|
|
(0, b""),
|
|
(1, small_data),
|
|
(1, large_data),
|
|
(0xFFFFFF, small_data),
|
|
(0xFFFFFF, large_data),
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"size,csum",
|
|
[
|
|
(-1, None),
|
|
(0x18, 0x9E),
|
|
(0x1000, 0xA6),
|
|
(0x2000, 0x96),
|
|
(0x4000, 0x76),
|
|
],
|
|
)
|
|
def test_make_transfer_list(size, csum):
|
|
if size < 8:
|
|
with pytest.raises(AssertionError):
|
|
tl = TransferList(size)
|
|
else:
|
|
tl = TransferList(size)
|
|
|
|
assert tl.signature == 0x4A0FB10B
|
|
assert not tl.entries
|
|
assert tl.sum_of_bytes() == 0
|
|
assert tl.checksum == csum
|
|
|
|
|
|
@pytest.mark.parametrize(("tag_id", "data"), test_entries)
|
|
def test_add_transfer_entry(tag_id, data):
|
|
tl = TransferList(0x1000)
|
|
te = TransferEntry(tag_id, len(data), data)
|
|
|
|
tl.add_transfer_entry(tag_id, data)
|
|
|
|
assert te in tl.entries
|
|
assert tl.size == TransferList.hdr_size + te.size
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("tag_id", "data"),
|
|
[
|
|
(-1, None), # tag out of range
|
|
(1, None), # no data provided
|
|
(1, bytes(8000)), # very large data > total size
|
|
(0x100000, b"0dd0edfe"), # tag out of range
|
|
],
|
|
)
|
|
def test_add_out_of_range_transfer_entry(tag_id, data):
|
|
tl = TransferList()
|
|
|
|
with pytest.raises(Exception):
|
|
tl.add_transfer_entry(tag_id, data)
|
|
|
|
|
|
@pytest.mark.parametrize(("tag_id", "data"), test_entries)
|
|
def test_calculate_te_sum_of_bytes(tag_id, data):
|
|
te = TransferEntry(tag_id, len(data), data)
|
|
csum = (
|
|
sum(data)
|
|
+ sum(len(data).to_bytes(4, "big"))
|
|
+ te.hdr_size
|
|
+ sum(tag_id.to_bytes(4, "big"))
|
|
) % 256
|
|
assert te.sum_of_bytes == csum
|
|
|
|
|
|
@pytest.mark.parametrize(("tag_id", "data"), test_entries)
|
|
def test_calculate_tl_checksum(tag_id, data):
|
|
tl = TransferList(0x1000)
|
|
|
|
tl.add_transfer_entry(tag_id, data)
|
|
assert tl.sum_of_bytes() == 0
|
|
|
|
|
|
def test_empty_transfer_list_blob(tmpdir):
|
|
"""Check that we can correctly create a transfer list header."""
|
|
test_file = tmpdir.join("test_tl_blob.bin")
|
|
tl = TransferList()
|
|
tl.write_to_file(test_file)
|
|
|
|
with open(test_file, "rb") as f:
|
|
assert f.read(tl.hdr_size) == tl.header_to_bytes()
|
|
|
|
|
|
@pytest.mark.parametrize(("tag_id", "data"), test_entries)
|
|
def test_single_te_transfer_list(tag_id, data, tmpdir):
|
|
"""Check that we can create a complete TL with a single TE."""
|
|
test_file = tmpdir.join("test_tl_blob.bin")
|
|
tl = TransferList(0x1000)
|
|
|
|
tl.add_transfer_entry(tag_id, data)
|
|
tl.write_to_file(test_file)
|
|
|
|
te = tl.entries[0]
|
|
|
|
with open(test_file, "rb") as f:
|
|
assert f.read(tl.hdr_size) == tl.header_to_bytes()
|
|
assert int.from_bytes(f.read(3), "little") == te.id
|
|
assert int.from_bytes(f.read(1), "little") == te.hdr_size
|
|
assert int.from_bytes(f.read(4), "little") == te.data_size
|
|
assert f.read(te.data_size) == te.data
|
|
|
|
|
|
def test_write_multiple_tes_to_file(tmpdir, random_entries):
|
|
"""Check that we can create a TL with multiple TE's."""
|
|
test_file = tmpdir.join("test_tl_blob.bin")
|
|
tl = TransferList(0x4000)
|
|
_test_entries = random_entries()
|
|
|
|
for tag_id, data in _test_entries:
|
|
tl.add_transfer_entry(tag_id, data)
|
|
|
|
tl.write_to_file(test_file)
|
|
|
|
with open(test_file, "rb") as f:
|
|
assert f.read(tl.hdr_size) == tl.header_to_bytes()
|
|
# Ensure that TE's have the correct alignment
|
|
for tag_id, data in _test_entries:
|
|
f.seek(int(math.ceil(f.tell() / 8) * 8))
|
|
|
|
assert int.from_bytes(f.read(3), "little") == tag_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) == data
|
|
|
|
|
|
def test_read_empty_transfer_list_from_file(tmpdir):
|
|
test_file = tmpdir.join("test_tl_blob.bin")
|
|
original_tl = TransferList(0x1000)
|
|
original_tl.write_to_file(test_file)
|
|
|
|
# Read the contents of the file we just wrote
|
|
tl = TransferList.fromfile(test_file)
|
|
assert tl.header_to_bytes() == original_tl.header_to_bytes()
|
|
assert tl.sum_of_bytes() == 0
|
|
|
|
|
|
def test_read_single_transfer_list_from_file(tmpdir):
|
|
test_file = tmpdir.join("test_tl_blob.bin")
|
|
original_tl = TransferList(0x1000)
|
|
|
|
original_tl.add_transfer_entry(test_entries[0][0], test_entries[0][1])
|
|
original_tl.write_to_file(test_file)
|
|
|
|
# Read the contents of the file we just wrote
|
|
tl = TransferList.fromfile(test_file)
|
|
assert tl.entries
|
|
|
|
te = tl.entries[0]
|
|
assert te.id == test_entries[0][0]
|
|
assert te.data == test_entries[0][1]
|
|
assert tl.sum_of_bytes() == 0
|
|
|
|
|
|
def test_read_multiple_transfer_list_from_file(tmpdir):
|
|
test_file = tmpdir.join("test_tl_blob.bin")
|
|
original_tl = TransferList(0x1000)
|
|
|
|
for tag_id, data in test_entries:
|
|
original_tl.add_transfer_entry(tag_id, data)
|
|
|
|
original_tl.write_to_file(test_file)
|
|
|
|
# Read the contents of the file we just wrote
|
|
tl = TransferList.fromfile(test_file)
|
|
|
|
# The TE we derive from the file might have a an associated offset, compare
|
|
# the TE's based on the header in bytes, which doesn't account for this.
|
|
for te0, te1 in zip(tl.entries, original_tl.entries):
|
|
assert te0.header_to_bytes() == te1.header_to_bytes()
|
|
|
|
assert tl.sum_of_bytes() == 0
|
|
|
|
|
|
@pytest.mark.parametrize("tag", [tag for tag, _ in test_entries])
|
|
def test_remove_tag_from_file(tag):
|
|
tl = TransferList(0x1000)
|
|
|
|
for tag_id, data in test_entries:
|
|
tl.add_transfer_entry(tag_id, data)
|
|
|
|
removed_entries = list(filter(lambda te: te.id == tag, tl.entries))
|
|
original_size = tl.size
|
|
tl.remove_tag(tag)
|
|
|
|
assert not any(tag == te.id for te in tl.entries)
|
|
assert tl.size == original_size - sum(map(lambda te: te.size, removed_entries))
|
|
|
|
|
|
def test_get_fdt_offset(tmpdir):
|
|
tl = TransferList(0x1000)
|
|
tl.add_transfer_entry(1, 0xEDFE0DD0.to_bytes(4, "big"))
|
|
f = tmpdir.join("blob.bin")
|
|
|
|
tl.write_to_file(f)
|
|
|
|
blob_tl = TransferList.fromfile(f)
|
|
|
|
assert blob_tl.hdr_size + TransferEntry.hdr_size == blob_tl.get_entry_data_offset(1)
|
|
|
|
|
|
def test_get_missing_fdt_offset(tmpdir):
|
|
tl = TransferList(0x1000)
|
|
f = tmpdir.join("blob.bin")
|
|
|
|
tl.write_to_file(f)
|
|
blob_tl = TransferList.fromfile(f)
|
|
|
|
with pytest.raises(ValueError):
|
|
blob_tl.get_entry_data_offset(1)
|