Skip to content

Commit

Permalink
Make QEMU exit when a test panics (#19)
Browse files Browse the repository at this point in the history
This PR submitted by @HadrienG2 makes QEMU exit with an error code when a panic happens. This is done by using the ISA debug port.

Should help with running tests automatically.
  • Loading branch information
HadrienG2 authored and GabrielMajeri committed Sep 20, 2018
1 parent 183dd33 commit d89e95e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 5 deletions.
6 changes: 6 additions & 0 deletions uefi-services/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ edition = "2018"

[dependencies]
rlibc = "1"
x86_64 = "0.2"

uefi = { path = ".." }
uefi-alloc = { path = "../uefi-alloc" }
uefi-logger = { path = "../uefi-logger" }
log = { version = "0.4", default-features = false }

[features]
# Signals the implementation that QEMU's exit port hack is enabled and assigned
# to the f4 CPU port.
qemu-f4-exit = []
32 changes: 30 additions & 2 deletions uefi-services/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ fn init_alloc() {
uefi_alloc::init(st.boot);
}



#[lang = "eh_personality"]
fn eh_personality() {}

Expand All @@ -104,9 +106,35 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! {
}
}

loop {
// TODO: add a timeout then shutdown.
// Give the user some time to read the message
if let Some(st) = unsafe { SYSTEM_TABLE } {
// FIXME: Check if boot-time services have been exited too
st.boot.stall(10_000_000);
} else {
let mut dummy = 0u64;
// FIXME: May need different counter values in debug & release builds
for i in 0..300_000_000 {
unsafe { core::ptr::write_volatile(&mut dummy, i); }
}
}

// If running inside of QEMU and the f4 port hack is enabled, use it to
// signal the error to the parent shell and exit
if cfg!(feature = "qemu-f4-exit") {
use x86_64::instructions::port::Port;
let mut port = Port::<u32>::new(0xf4);
unsafe { port.write(42); }
}

// If the system table is available, use UEFI's standard shutdown mechanism
if let Some(st) = unsafe { SYSTEM_TABLE } {
use uefi::table::runtime::ResetType;
st.runtime.reset(ResetType::Shutdown, uefi::Status::Aborted, None)
}

// If we don't have any shutdown mechanism handy, the best we can do is loop
error!("Could not shut down, please power off the system manually...");
loop { }
}

#[alloc_error_handler]
Expand Down
3 changes: 3 additions & 0 deletions uefi-test-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ uefi-services = { path = "../uefi-services" }
uefi-exts = { path = "../uefi-exts" }

log = { version = "0.4", default-features = false }

[features]
qemu-f4-exit = ["uefi-services/qemu-f4-exit"]
9 changes: 6 additions & 3 deletions uefi-test-runner/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ def run_xbuild(*flags):

sp.run(cmd).check_returncode()

def build():
def build(*test_flags):
'Builds the tests and examples.'

run_xbuild('--package', 'uefi-test-runner')
run_xbuild('--package', 'uefi-test-runner', *test_flags)
run_xbuild('--package', 'uefi', '--examples')

# Copy the built test runner file to the right directory for running tests.
Expand Down Expand Up @@ -72,7 +72,7 @@ def run_qemu():
'Runs the code in QEMU.'

# Rebuild all the changes.
build()
build('--features', 'qemu-f4-exit')

ovmf_code, ovmf_vars = OVMF_DIR / 'OVMF_CODE.fd', OVMF_DIR / 'OVMF_VARS.fd'

Expand Down Expand Up @@ -105,6 +105,9 @@ def run_qemu():
# Mount the built examples directory.
'-drive', f'format=raw,file=fat:rw:{examples_dir}',

# Map the QEMU exit signal to port f4
'-device', 'isa-debug-exit,iobase=0xf4,iosize=0x04',

# OVMF debug builds can output information to a serial `debugcon`.
# Only enable when debugging UEFI boot:
#'-debugcon', 'file:debug.log', '-global', 'isa-debugcon.iobase=0x402',
Expand Down

0 comments on commit d89e95e

Please sign in to comment.