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>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
test_fw_handoff
|
||||
===============
|
||||
|
||||
.. automodule:: test_fw_handoff
|
||||
:synopsis:
|
||||
:member-order: bysource
|
||||
:members:
|
||||
:undoc-members:
|
||||
@@ -0,0 +1,108 @@
|
||||
# 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}"
|
||||
Reference in New Issue
Block a user