u-boot/test/py/tests/test_fw_handoff.py
Raymond Mao f974e9b626 pytest: add test script to validate Firmware Handoff
Add test cases to validate FDT and TPM eventlog handoff from TF-A
and OP-TEE via bloblist.

For FDT, the nodes 'reserved-memory' and 'firmware' appended by
OP-TEE indicates a successful handoff.

For TPM eventlog, the events 'SECURE_RT_EL3', 'SECURE_RT_EL1_OPTEE'
and 'SECURE_RT_EL1_OPTEE_EXTRA1' created by TF-A indicates a
successful handoff.

Signed-off-by: Raymond Mao <raymond.mao@linaro.org>
Reviewed-by: Tom Rini <trini@konsulko.com>
2025-11-04 10:59:41 -06:00

109 lines
3.7 KiB
Python

# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (c) 2025 Linaro Limited
# Author: Raymond Mao <raymond.mao@linaro.org>
#
# Validate Firmware Handoff from TF-A and OP-TEE
"""
Note: This test relies on boardenv_* containing configuration values to define
whether Firmware Handoff is enabled for testing. Without this, this test
will be automatically skipped.
For example:
.. code-block:: python
# Boolean indicating whether Firmware Handoff is enabled on this board.
# This variable may be omitted if its value is False.
env__firmware_handoff_enabled = True
"""
import pytest
import re
def _norm_ws(s: str) -> str:
"""Normalize whitespace for robust comparisons."""
return re.sub(r"\s+", " ", s).strip()
@pytest.mark.buildconfigspec("bloblist")
@pytest.mark.buildconfigspec("cmd_bloblist")
@pytest.mark.buildconfigspec("of_control")
@pytest.mark.buildconfigspec("cmd_fdt")
def test_fw_handoff_dt(ubman):
"""Validate FDT handoff via bloblist."""
fh_en = ubman.config.env.get('env__firmware_handoff_enabled', False)
if not fh_en:
pytest.skip('Firmware Handoff is disabled')
bloblist = ubman.run_command("bloblist list")
blob_fdt = re.search(r"^([0-9a-fA-F]+)\s+[0-9a-fA-F]+\s+1\s+Control FDT\s*$",
bloblist, re.MULTILINE)
assert blob_fdt, "Control FDT entry not found in bloblist"
blob_fdt_addr = int(blob_fdt.group(1), 16)
ubman.run_command(f"fdt addr {blob_fdt_addr:x}")
reserved_a = ubman.run_command("fdt print /reserved-memory")
firmware_a = ubman.run_command("fdt print /firmware")
fdt_addr_out = ubman.run_command("echo $fdt_addr")
fdt_addr_match = re.search(r"(?:0x)?([0-9a-fA-F]+)", fdt_addr_out)
assert fdt_addr_match, "Could not parse $fdt_addr"
fdt_addr = int(fdt_addr_match.group(1), 16)
ubman.run_command(f"fdt addr {fdt_addr:x}")
reserved_b = ubman.run_command("fdt print /reserved-memory")
firmware_b = ubman.run_command("fdt print /firmware")
# Normalize whitespace & compare
assert _norm_ws(reserved_a) == _norm_ws(reserved_b), \
"reserved-memory blocks differ between Control FDT and $fdt_addr FDT"
assert _norm_ws(firmware_a) == _norm_ws(firmware_b), \
"firmware blocks differ between Control FDT and $fdt_addr FDT"
@pytest.mark.buildconfigspec("bloblist")
@pytest.mark.buildconfigspec("cmd_bloblist")
@pytest.mark.buildconfigspec("cmd_memory")
def test_fw_handoff_eventlog(ubman):
"""Validate TPM event log handoff via bloblist."""
fh_en = ubman.config.env.get('env__firmware_handoff_enabled', False)
if not fh_en:
pytest.skip('Firmware Handoff is disabled')
# Get the address and size of eventlog from the bloblist
bloblist_output = ubman.run_command("bloblist list")
evt_addr = None
evt_size = None
for line in bloblist_output.splitlines():
if "TPM event log" in line:
parts = line.strip().split()
evt_addr = int(parts[0], 16)
evt_size = int(parts[1], 16)
break
assert evt_addr is not None and evt_size is not None, \
"TPM event log not found in bloblist"
# Read byte from memory and extract printable ASCII from each line
md_output = ubman.run_command(f"md.b {evt_addr:x} {evt_size}")
ascii_log = ""
for line in md_output.splitlines():
match = re.search(r'([0-9a-f]+:.*?)((?:\s[0-9a-f]{2}){1,16})\s+(.*)', line)
if match:
ascii_part = match.group(3).strip()
ascii_log += ascii_part
# The events created by TF-A are expected
expected_keywords = [
"SECURE_RT_EL3",
"SECURE_RT_EL1_OPTEE",
"SECURE_RT_EL1_OPTEE_EXTRA1"
]
for keyword in expected_keywords:
assert keyword in ascii_log, f"Missing expected event: {keyword}"