blob: 79359b726e17f9b7b12b633d815bea4bd1053aff [file] [log] [blame]
use crate::{boot, println};
use cfg_if::cfg_if;
#[panic_handler]
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
println!("[PANIC]: {}", info);
// Give the user some time to read the message
if boot::are_boot_services_active() {
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);
}
}
}
cfg_if! {
if #[cfg(all(target_arch = "x86_64", feature = "qemu"))] {
// If running in QEMU, use the f4 exit port to signal the error and exit
use qemu_exit::QEMUExit;
let custom_exit_success = 3;
let qemu_exit_handle = qemu_exit::X86::new(0xF4, custom_exit_success);
qemu_exit_handle.exit_failure();
} else {
// If the system table is available, use UEFI's standard shutdown mechanism
if let Some(st) = crate::table::system_table_raw() {
if !unsafe { st.as_ref().runtime_services }.is_null() {
crate::runtime::reset(crate::runtime::ResetType::SHUTDOWN, crate::Status::ABORTED, None);
}
}
// If we don't have any shutdown mechanism handy, the best we can do is loop
log::error!("Could not shut down, please power off the system manually...");
cfg_if! {
if #[cfg(target_arch = "x86_64")] {
loop {
unsafe {
// Try to at least keep CPU from running at 100%
core::arch::asm!("hlt", options(nomem, nostack));
}
}
} else if #[cfg(target_arch = "aarch64")] {
loop {
unsafe {
// Try to at least keep CPU from running at 100%
core::arch::asm!("hlt 420", options(nomem, nostack));
}
}
} else {
loop {
// just run forever dammit how do you return never anyway
}
}
}
}
}
}