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