Skip to content

Commit f974e9b

Browse files
raymo200915trini
authored andcommitted
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>
1 parent 183299d commit f974e9b

2 files changed

Lines changed: 116 additions & 0 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
test_fw_handoff
2+
===============
3+
4+
.. automodule:: test_fw_handoff
5+
:synopsis:
6+
:member-order: bysource
7+
:members:
8+
:undoc-members:

test/py/tests/test_fw_handoff.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# SPDX-License-Identifier: GPL-2.0+
2+
#
3+
# Copyright (c) 2025 Linaro Limited
4+
# Author: Raymond Mao <raymond.mao@linaro.org>
5+
#
6+
# Validate Firmware Handoff from TF-A and OP-TEE
7+
8+
"""
9+
Note: This test relies on boardenv_* containing configuration values to define
10+
whether Firmware Handoff is enabled for testing. Without this, this test
11+
will be automatically skipped.
12+
13+
For example:
14+
15+
.. code-block:: python
16+
17+
# Boolean indicating whether Firmware Handoff is enabled on this board.
18+
# This variable may be omitted if its value is False.
19+
env__firmware_handoff_enabled = True
20+
"""
21+
22+
import pytest
23+
import re
24+
25+
def _norm_ws(s: str) -> str:
26+
"""Normalize whitespace for robust comparisons."""
27+
return re.sub(r"\s+", " ", s).strip()
28+
29+
@pytest.mark.buildconfigspec("bloblist")
30+
@pytest.mark.buildconfigspec("cmd_bloblist")
31+
@pytest.mark.buildconfigspec("of_control")
32+
@pytest.mark.buildconfigspec("cmd_fdt")
33+
def test_fw_handoff_dt(ubman):
34+
"""Validate FDT handoff via bloblist."""
35+
36+
fh_en = ubman.config.env.get('env__firmware_handoff_enabled', False)
37+
if not fh_en:
38+
pytest.skip('Firmware Handoff is disabled')
39+
40+
bloblist = ubman.run_command("bloblist list")
41+
blob_fdt = re.search(r"^([0-9a-fA-F]+)\s+[0-9a-fA-F]+\s+1\s+Control FDT\s*$",
42+
bloblist, re.MULTILINE)
43+
assert blob_fdt, "Control FDT entry not found in bloblist"
44+
45+
blob_fdt_addr = int(blob_fdt.group(1), 16)
46+
ubman.run_command(f"fdt addr {blob_fdt_addr:x}")
47+
48+
reserved_a = ubman.run_command("fdt print /reserved-memory")
49+
firmware_a = ubman.run_command("fdt print /firmware")
50+
51+
fdt_addr_out = ubman.run_command("echo $fdt_addr")
52+
fdt_addr_match = re.search(r"(?:0x)?([0-9a-fA-F]+)", fdt_addr_out)
53+
assert fdt_addr_match, "Could not parse $fdt_addr"
54+
55+
fdt_addr = int(fdt_addr_match.group(1), 16)
56+
ubman.run_command(f"fdt addr {fdt_addr:x}")
57+
58+
reserved_b = ubman.run_command("fdt print /reserved-memory")
59+
firmware_b = ubman.run_command("fdt print /firmware")
60+
61+
# Normalize whitespace & compare
62+
assert _norm_ws(reserved_a) == _norm_ws(reserved_b), \
63+
"reserved-memory blocks differ between Control FDT and $fdt_addr FDT"
64+
assert _norm_ws(firmware_a) == _norm_ws(firmware_b), \
65+
"firmware blocks differ between Control FDT and $fdt_addr FDT"
66+
67+
@pytest.mark.buildconfigspec("bloblist")
68+
@pytest.mark.buildconfigspec("cmd_bloblist")
69+
@pytest.mark.buildconfigspec("cmd_memory")
70+
def test_fw_handoff_eventlog(ubman):
71+
"""Validate TPM event log handoff via bloblist."""
72+
73+
fh_en = ubman.config.env.get('env__firmware_handoff_enabled', False)
74+
if not fh_en:
75+
pytest.skip('Firmware Handoff is disabled')
76+
77+
# Get the address and size of eventlog from the bloblist
78+
bloblist_output = ubman.run_command("bloblist list")
79+
evt_addr = None
80+
evt_size = None
81+
for line in bloblist_output.splitlines():
82+
if "TPM event log" in line:
83+
parts = line.strip().split()
84+
evt_addr = int(parts[0], 16)
85+
evt_size = int(parts[1], 16)
86+
break
87+
88+
assert evt_addr is not None and evt_size is not None, \
89+
"TPM event log not found in bloblist"
90+
91+
# Read byte from memory and extract printable ASCII from each line
92+
md_output = ubman.run_command(f"md.b {evt_addr:x} {evt_size}")
93+
ascii_log = ""
94+
for line in md_output.splitlines():
95+
match = re.search(r'([0-9a-f]+:.*?)((?:\s[0-9a-f]{2}){1,16})\s+(.*)', line)
96+
if match:
97+
ascii_part = match.group(3).strip()
98+
ascii_log += ascii_part
99+
100+
# The events created by TF-A are expected
101+
expected_keywords = [
102+
"SECURE_RT_EL3",
103+
"SECURE_RT_EL1_OPTEE",
104+
"SECURE_RT_EL1_OPTEE_EXTRA1"
105+
]
106+
107+
for keyword in expected_keywords:
108+
assert keyword in ascii_log, f"Missing expected event: {keyword}"

0 commit comments

Comments
 (0)