diff options
Diffstat (limited to 'test/py')
| -rw-r--r-- | test/py/multiplexed_log.py | 8 | ||||
| -rw-r--r-- | test/py/requirements.txt | 2 | ||||
| -rw-r--r-- | test/py/tests/test_efi_secboot/conftest.py | 5 | ||||
| -rw-r--r-- | test/py/tests/test_efi_secboot/test_signed.py | 9 | ||||
| -rw-r--r-- | test/py/tests/test_efi_secboot/test_signed_intca.py | 9 | ||||
| -rw-r--r-- | test/py/tests/test_efi_secboot/test_unsigned.py | 9 | ||||
| -rw-r--r-- | test/py/tests/test_fw_handoff.py | 108 | ||||
| -rw-r--r-- | test/py/tests/test_of_migrate.py | 105 |
8 files changed, 144 insertions, 111 deletions
diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py index 63237594bb4..68dc183e463 100644 --- a/test/py/multiplexed_log.py +++ b/test/py/multiplexed_log.py @@ -138,10 +138,10 @@ class RunAndLog(object): self.logfile.write(self, msg) try: - p = subprocess.Popen(cmd, cwd=cwd, - stdin=subprocess.PIPE if stdin else None, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) - (stdout, stderr) = p.communicate(input=stdin) + p = subprocess.run(cmd, cwd=cwd, capture_output=True, input=stdin, + env=env) + stdout = p.stdout + stderr = p.stderr if stdout is not None: stdout = stdout.decode('utf-8') if stderr is not None: diff --git a/test/py/requirements.txt b/test/py/requirements.txt index 804a427b351..f9eac7901fb 100644 --- a/test/py/requirements.txt +++ b/test/py/requirements.txt @@ -1,5 +1,5 @@ filelock==3.0.12 pycryptodomex==3.21.0 -pytest==6.2.5 +pytest==8.4.2 pytest-xdist==2.5.0 FATtools==1.0.42 diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py index aa9a3536296..76b8f9fa0a3 100644 --- a/test/py/tests/test_efi_secboot/conftest.py +++ b/test/py/tests/test_efi_secboot/conftest.py @@ -162,9 +162,12 @@ def efi_boot_env_intca(request, ubman): # PK check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_PK/ -keyout PK.key -out PK.crt -nodes -days 365' % mnt_point, shell=True) - check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt PK.esl; %ssign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth' + check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt PK.esl; %ssign-efi-sig-list -t "2020-04-01" -c PK.crt -k PK.key PK PK.esl PK.auth' % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), shell=True) + # PK_null for deletion + check_call('cd %s; touch PK_null.esl; %ssign-efi-sig-list -c PK.crt -k PK.key PK PK_null.esl PK_null.auth' + % (mnt_point, EFITOOLS_PATH), shell=True) # KEK check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_KEK/ -keyout KEK.key -out KEK.crt -nodes -days 365' % mnt_point, shell=True) diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py index e8aaef7090c..9e6d3fdf8d8 100644 --- a/test/py/tests/test_efi_secboot/test_signed.py +++ b/test/py/tests/test_efi_secboot/test_signed.py @@ -369,3 +369,12 @@ class TestEfiSignedImage(object): assert(not 'hELLO, world!' in ''.join(output)) assert('\'HELLO1\' failed' in ''.join(output)) assert('efi_bootmgr_load() returned: 26' in ''.join(output)) + + with ubman.log.section('Test Case 8c'): + # Test Case 8c, Uninstall PK + output = ubman.run_command_list([ + 'fatload host 0:1 4000000 PK_null.auth', + 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK', + 'printenv -e -n PK']) + assert 'Failed to set EFI variable' not in ''.join(output) + assert '\"PK\" not defined' in ''.join(output) diff --git a/test/py/tests/test_efi_secboot/test_signed_intca.py b/test/py/tests/test_efi_secboot/test_signed_intca.py index 58f7be03b8b..06d86baef19 100644 --- a/test/py/tests/test_efi_secboot/test_signed_intca.py +++ b/test/py/tests/test_efi_secboot/test_signed_intca.py @@ -133,3 +133,12 @@ class TestEfiSignedImageIntca(object): 'efidebug test bootmgr']) assert '\'HELLO_abc\' failed' in ''.join(output) assert 'efi_bootmgr_load() returned: 26' in ''.join(output) + + with ubman.log.section('Test Case 3c'): + # Test Case 3c, Uninstall PK + output = ubman.run_command_list([ + 'fatload host 0:1 4000000 PK_null.auth', + 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK', + 'printenv -e -n PK']) + assert 'Failed to set EFI variable' not in ''.join(output) + assert '\"PK\" not defined' in ''.join(output) diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py index bd6e1b2dadd..2b86dc44cff 100644 --- a/test/py/tests/test_efi_secboot/test_unsigned.py +++ b/test/py/tests/test_efi_secboot/test_unsigned.py @@ -115,3 +115,12 @@ class TestEfiUnsignedImage(object): 'efidebug test bootmgr']) assert 'efi_bootmgr_load() returned: 26' in ''.join(output) assert 'Hello, world!' not in ''.join(output) + + with ubman.log.section('Test Case 3c'): + # Test Case 3c, Uninstall PK + output = ubman.run_command_list([ + 'fatload host 0:1 4000000 PK_null.auth', + 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK', + 'printenv -e -n PK']) + assert 'Failed to set EFI variable' not in ''.join(output) + assert '\"PK\" not defined' in ''.join(output) diff --git a/test/py/tests/test_fw_handoff.py b/test/py/tests/test_fw_handoff.py new file mode 100644 index 00000000000..45f154665ef --- /dev/null +++ b/test/py/tests/test_fw_handoff.py @@ -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}" diff --git a/test/py/tests/test_of_migrate.py b/test/py/tests/test_of_migrate.py deleted file mode 100644 index ab89332331e..00000000000 --- a/test/py/tests/test_of_migrate.py +++ /dev/null @@ -1,105 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Copyright 2023 Google LLC -# Written by Simon Glass <sjg@chromium.org> - -"""Test handling of unmigrated u-boot,dm- tags""" - -import os -import pytest - -import utils - -# This is needed for Azure, since the default '..' directory is not writeable -TMPDIR1 = '/tmp/test_no_migrate' -TMPDIR2 = '/tmp/test_no_migrate_spl' -TMPDIR3 = '/tmp/test_migrate' - -def build_for_migrate(ubman, replace_pair, board, tmpdir, disable_migrate=True): - """Build an updated U-Boot with a slightly modified device tree - - Args: - ubman (ConsoleBase): U-Boot console - replace_pair (tuple): - String to find - String to replace it with - board (str): Board to build - tmpdir (str): Temporary directory to use - disable_migrate (bool): True to disable CONFIG_OF_TAG_MIGRATE in build - """ - srcdir = ubman.config.source_dir - build_dir = ubman.config.build_dir - - # Get the source for the existing dts - dt_dir = os.path.join(build_dir, 'arch', 'sandbox', 'dts') - orig_fname = os.path.join(dt_dir, 'sandbox.dtb') - out_dts = os.path.join(dt_dir, 'sandbox_out.dts') - utils.run_and_log(ubman, ['dtc', orig_fname, '-I', 'dtb', '-O', 'dts', - '-o', out_dts]) - - # Update it to use an old tag - with open(out_dts) as inf: - data = inf.read() - data = data.replace(*replace_pair) - - dts_fname = os.path.join(dt_dir, 'sandbox_oldtag.dts') - with open(dts_fname, 'w') as outf: - print(data, file=outf) - dtb_fname = os.path.join(dt_dir, 'sandbox_oldtag.dtb') - utils.run_and_log(ubman, ['dtc', dts_fname, '-o', dtb_fname]) - - migrate = ['-a', '~CONFIG_OF_TAG_MIGRATE'] if disable_migrate else [] - - # Build sandbox with this new dtb, turning off OF_TAG_MIGRATE - env = dict(os.environ) - env['EXT_DTB'] = dtb_fname - env['DEVICE_TREE'] = 'sandbox_new' - env['NO_LTO'] = '1' # Speed up build - out = utils.run_and_log( - ubman, ['./tools/buildman/buildman', '-m', '--board', board, - *migrate, '-w', '-o', tmpdir], ignore_errors=True, env=env) - return out - -@pytest.mark.slow -@pytest.mark.boardspec('sandbox') -def test_of_no_migrate(ubman): - """Test sandbox with old boot phase tags like u-boot,dm-pre-proper""" - - build_for_migrate(ubman, ['bootph-some-ram', 'u-boot,dm-pre-proper'], - 'sandbox', TMPDIR1) - - # It should fail to run, since the lcd device will not be bound before - # relocation. so won't get its frame-buffer memory - out = utils.run_and_log( - ubman, [os.path.join(TMPDIR1, 'u-boot'), '-D', '-c', 'help'], - ignore_errors=True) - assert "Video device 'lcd' cannot allocate frame buffer memory" in out - - -@pytest.mark.slow -@pytest.mark.boardspec('sandbox_spl') -@pytest.mark.boardspec('spl_of_platdata_inst') -@pytest.mark.boardspec('!sandbox_tpl') -def test_of_no_migrate_spl(ubman): - """Test sandbox with old boot phase tags like u-boot,dm-spl""" - - out = build_for_migrate(ubman, ['bootph-pre-ram', 'u-boot,dm-spl'], - 'sandbox_spl', TMPDIR2) - - # It should fail to build, since the SPL DT will not include 'spl-test' - # node, among others - assert "undefined type ‘struct dtd_sandbox_spl_test’" in out - - -@pytest.mark.slow -@pytest.mark.boardspec('sandbox') -def test_of_migrate(ubman): - """Test sandbox shows a message when tags were migrated""" - - build_for_migrate(ubman, ['bootph-some-ram', 'u-boot,dm-pre-proper'], - 'sandbox', TMPDIR3, disable_migrate=False) - - # It should show a migration message - out = utils.run_and_log( - ubman, [os.path.join(TMPDIR3, 'u-boot'), '-D', '-c', 'help'], - ignore_errors=True) - assert "Warning: Device tree includes old 'u-boot,dm-' tags" in out |
