From: Ahmad Fatoum <[email protected]> arm64 machine_restart() calls efi_reboot() before falling back to PSCI whenever EFI runtime services are available, so rebooting the booted Debian kernel calls barebox's ResetSystem implementation, which lives entirely in the .efi_runtime code section.
This way, we have a test that verifies we can call into efi_runtime section both at boot and at runtime. QEMU would restart the VM on a successful reset, so the test expects the barebox banner to reappear on the console. Assisted-by: Claude:fable-5 Signed-off-by: Ahmad Fatoum <[email protected]> --- test/py/test_linux_efiloader.py | 57 +++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/test/py/test_linux_efiloader.py b/test/py/test_linux_efiloader.py index a76e55a91e52..eae6703e9d49 100644 --- a/test/py/test_linux_efiloader.py +++ b/test/py/test_linux_efiloader.py @@ -26,13 +26,7 @@ def get_dmesg(shell, grep=None): return stdout [email protected]_feature(['bootable', 'efi', 'testfs']) [email protected]('efiloader', [False, True]) -def test_boot_manual_with_initrd(strategy, barebox, env, efiloader, debian_iso): - """Test booting Debian kernel directly without GRUB""" - - barebox.run_check(f"global.bootm.efi={'required' if efiloader else 'disabled'}") - +def configure_bootm(strategy, barebox): def get_option(strategy, opt): config = strategy.target.env.config return config.get_target_option(strategy.target.name, opt) @@ -57,6 +51,16 @@ def test_boot_manual_with_initrd(strategy, barebox, env, efiloader, debian_iso): # Speed up subsequent runs a bit barebox.run_check("global linux.bootargs.noapparmor=apparmor=0") + [email protected]_feature(['bootable', 'efi', 'testfs']) [email protected]('efiloader', [False, True]) +def test_boot_manual_with_initrd(strategy, barebox, env, efiloader, debian_iso): + """Test booting Debian kernel directly without GRUB""" + + barebox.run_check(f"global.bootm.efi={'required' if efiloader else 'disabled'}") + + configure_bootm(strategy, barebox) + # Boot the kernel - it should use EFI stub by default with strategy.boot_kernel(bootm=True) as shell: shell.run_check("grep -q apparmor=0 /proc/cmdline") @@ -127,3 +131,42 @@ def check_efivars_filesystem_not_empty(shell): assert ret == 0 assert len(stdout), "EFI variables directory is empty" + + [email protected]_feature(['bootable', 'efi', 'testfs']) +def test_efi_reset_system(strategy, barebox, env, debian_iso): + """Test rebooting Linux via barebox's EFI ResetSystem runtime service + + arm64 machine_restart() calls efi_reboot() before falling back to + PSCI whenever EFI runtime services are available, so a reboot from + the booted kernel calls into the barebox .efi_runtime code section + after ExitBootServices. + """ + + barebox.run_check("global.bootm.efi=required") + + configure_bootm(strategy, barebox) + + with strategy.boot_kernel(bootm=True) as shell: + # ensure the kernel did not give up on EFI runtime services + check_expected_efi_messages(shell, env) + stdout, _, _ = shell.run("dmesg | grep 'Runtime Services are disabled'") + assert stdout == [], "kernel disabled EFI runtime services" + + strategy.console.sendline("reboot -f") + + # QEMU reboots the VM on a successful reset, so barebox comes + # back up on the same console + _, before, _, _ = strategy.console.expect( + [r"barebox 2\d{3}"], timeout=120) + + # A faulting ResetSystem would be caught by the kernel, which + # then complains and falls back to PSCI. That also reboots, so + # check the console log to tell the two apart. + before = before.decode("utf-8", errors="replace") + for pattern in ["Synchronous exception in EFI runtime service", + "Unable to handle kernel", + "Internal error", + "Runtime Services are disabled"]: + assert pattern not in before, \ + f"kernel reported EFI runtime fault: {pattern}" -- 2.47.3
