| # 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}" |