1 use crate::{boot, println};
2 use cfg_if::cfg_if;
3
4 #[panic_handler]
panic_handler(info: &core::panic::PanicInfo) -> !5 fn panic_handler(info: &core::panic::PanicInfo) -> ! {
6 println!("[PANIC]: {}", info);
7
8 // Give the user some time to read the message
9 if boot::are_boot_services_active() {
10 boot::stall(10_000_000);
11 } else {
12 let mut dummy = 0u64;
13 // FIXME: May need different counter values in debug & release builds
14 for i in 0..300_000_000 {
15 unsafe {
16 core::ptr::write_volatile(&mut dummy, i);
17 }
18 }
19 }
20
21 cfg_if! {
22 if #[cfg(all(target_arch = "x86_64", feature = "qemu"))] {
23 // If running in QEMU, use the f4 exit port to signal the error and exit
24 use qemu_exit::QEMUExit;
25 let custom_exit_success = 3;
26 let qemu_exit_handle = qemu_exit::X86::new(0xF4, custom_exit_success);
27 qemu_exit_handle.exit_failure();
28 } else {
29 // If the system table is available, use UEFI's standard shutdown mechanism
30 if let Some(st) = crate::table::system_table_raw() {
31 if !unsafe { st.as_ref().runtime_services }.is_null() {
32 crate::runtime::reset(crate::runtime::ResetType::SHUTDOWN, crate::Status::ABORTED, None);
33 }
34 }
35
36 // If we don't have any shutdown mechanism handy, the best we can do is loop
37 log::error!("Could not shut down, please power off the system manually...");
38
39 cfg_if! {
40 if #[cfg(target_arch = "x86_64")] {
41 loop {
42 unsafe {
43 // Try to at least keep CPU from running at 100%
44 core::arch::asm!("hlt", options(nomem, nostack));
45 }
46 }
47 } else if #[cfg(target_arch = "aarch64")] {
48 loop {
49 unsafe {
50 // Try to at least keep CPU from running at 100%
51 core::arch::asm!("hlt 420", options(nomem, nostack));
52 }
53 }
54 } else {
55 loop {
56 // just run forever dammit how do you return never anyway
57 }
58 }
59 }
60 }
61 }
62 }
63