1use crate::cpu::instructions;
8use crate::lib::panic_codes::PanicCode;
9use crate::lib::types::fmt_buffer::FmtBuffer;
10use crate::SIMPLE_STATE;
11use core::panic::PanicInfo;
12use core::sync::atomic::{AtomicU8, Ordering};
13
14static PANIC_TRIGGERED: AtomicU8 = AtomicU8::new(0);
18
19#[repr(u8)]
21enum PanicTriggered {
22 WasKernelPanicTriggered = 1 << 0,
23 WasRustPanicTriggered = 1 << 1
24}
25
26#[cold]
28pub fn kernel_panic(panic_code: PanicCode, panic_message: &str) -> ! {
29 instructions::disable_interrupts();
30
31 if PANIC_TRIGGERED.load(Ordering::Acquire) & PanicTriggered::WasKernelPanicTriggered as u8 != 0 {
32 core::hint::cold_path();
33 loop {
34 instructions::halt_cpu();
35 }
36 }
37 PANIC_TRIGGERED.fetch_or(PanicTriggered::WasKernelPanicTriggered as u8, Ordering::AcqRel);
38
39 unsafe { force_unlock_loggers(); }
41
42 if SIMPLE_STATE.is_uart_initialized() {
43 use crate::drivers::tty::uart::UartOps;
44
45 let mut uart = unsafe { SIMPLE_STATE.uart().lock() };
47
48 let _ = uart.write_string("\nKernel Panic! :(\n");
49 let _ = uart.write_string("Panic Code: ");
50 let _ = uart.write_string(panic_code.as_str());
51 let _ = uart.write_string("\nPanic Type: ");
52 let _ = uart.write_string(panic_code.get_error_type_str());
53 let _ = uart.write_string("\n\n");
54 let _ = uart.write_string(panic_message);
55 }
56
57 if SIMPLE_STATE.is_basic_fb_initialized() && SIMPLE_STATE.is_basic_fb_psf2_font_initialized() {
58 let fb = unsafe { SIMPLE_STATE.basic_fb().lock() };
60 let font = unsafe { SIMPLE_STATE.basic_fb_psf2_font() };
62
63 let mut x: usize = 0;
64 let mut y: usize = 0;
65
66 fb.clear();
67 font.draw_string(&*fb, "Kernel Panic! :(\n", &mut x, &mut y, Some(0x00FF0000));
68 font.draw_string(&*fb, "Panic Code: ", &mut x, &mut y, None);
69 font.draw_string(&*fb, panic_code.as_str(), &mut x, &mut y, None);
70 font.draw_string(&*fb, "\nPanic Type: ", &mut x, &mut y, None);
71 font.draw_string(&*fb, panic_code.get_error_type_str(), &mut x, &mut y, None);
72 font.draw_string(&*fb, "\n\n", &mut x, &mut y, None);
73 font.draw_string(&*fb, panic_message, &mut x, &mut y, None);
74 }
75
76 instructions::halt_forever();
77}
78
79#[panic_handler]
81fn panic(panic_info: &PanicInfo) -> ! {
82 use core::fmt::Write;
83
84 instructions::disable_interrupts();
85
86 if PANIC_TRIGGERED.load(Ordering::Acquire) & PanicTriggered::WasRustPanicTriggered as u8 != 0 {
87 core::hint::cold_path();
88 loop {
89 instructions::halt_cpu();
90 }
91 }
92 PANIC_TRIGGERED.fetch_or(PanicTriggered::WasRustPanicTriggered as u8, Ordering::AcqRel);
93
94 unsafe { force_unlock_loggers(); }
96
97 let mut message_buf: FmtBuffer<512> = FmtBuffer::new();
98 if panic_info.message().as_str().is_none() {
99 let _ = write!(message_buf, "(No panic message given)\n\n");
100 } else {
101 let _ = write!(message_buf, "Panic Message: {}\n\n", panic_info.message());
102 }
103
104 let mut location_buf: FmtBuffer<256> = FmtBuffer::new();
105 if panic_info.location().is_none() {
106 let _ = write!(location_buf, "(No panic location given)");
107 } else {
108 let location = panic_info.location().unwrap();
109 let _ = write!(location_buf, "{}\n on line {}", location.file(), location.line());
110 }
111
112 if SIMPLE_STATE.is_uart_initialized() {
113 use crate::drivers::tty::uart::UartOps;
114
115 let mut uart = unsafe { SIMPLE_STATE.uart().lock() };
117
118 let _ = uart.write_string("\nKernel Panic! :(\n");
119 let _ = uart.write_string("[!] This panic was triggered by Rust (runtime error or panic!() called)\n\n");
120 let _ = uart.write_string(message_buf.as_str());
121 let _ = uart.write_string(location_buf.as_str());
122 }
123
124 if SIMPLE_STATE.is_basic_fb_initialized() && SIMPLE_STATE.is_basic_fb_psf2_font_initialized() {
125 let fb = unsafe { SIMPLE_STATE.basic_fb().lock() };
127 let font = unsafe { SIMPLE_STATE.basic_fb_psf2_font() };
129
130 let mut x: usize = 0;
131 let mut y: usize = 0;
132
133 fb.clear();
134 font.draw_string(&*fb, "Kernel Panic! :(\n", &mut x, &mut y, Some(0x00FF0000));
135 font.draw_string(&*fb, "[!] This panic was triggered by Rust (runtime error or panic!() called)\n\n", &mut x, &mut y, None);
136 font.draw_string(&*fb, message_buf.as_str(), &mut x, &mut y, None);
137 font.draw_string(&*fb, location_buf.as_str(), &mut x, &mut y, None);
138 }
139
140 instructions::halt_forever();
141}
142
143unsafe fn force_unlock_loggers() {
149 unsafe {
150 if SIMPLE_STATE.is_uart_initialized() {
151 SIMPLE_STATE.uart().force_unlock();
152 }
153 if SIMPLE_STATE.is_basic_fb_initialized() && SIMPLE_STATE.is_basic_fb_psf2_font_initialized() {
154 SIMPLE_STATE.basic_fb().force_unlock();
155 }
156 }
157}