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