diff options
Diffstat (limited to 'rsdos/src/main.rs')
| -rw-r--r-- | rsdos/src/main.rs | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/rsdos/src/main.rs b/rsdos/src/main.rs index a528810..7ca031c 100644 --- a/rsdos/src/main.rs +++ b/rsdos/src/main.rs | |||
| @@ -8,9 +8,44 @@ use rsnix::uefi::*; | |||
| 8 | // --------------------------------------------------------------------------- | 8 | // --------------------------------------------------------------------------- |
| 9 | // Panic handler | 9 | // Panic handler |
| 10 | // --------------------------------------------------------------------------- | 10 | // --------------------------------------------------------------------------- |
| 11 | |||
| 12 | /// Small fmt::Write over a byte slice (no allocation, bounded). | ||
| 13 | struct PanicBuf<'a> { | ||
| 14 | b: &'a mut [u8], | ||
| 15 | n: usize, | ||
| 16 | } | ||
| 17 | |||
| 18 | impl core::fmt::Write for PanicBuf<'_> { | ||
| 19 | fn write_str(&mut self, s: &str) -> core::fmt::Result { | ||
| 20 | let m = s.len().min(self.b.len() - self.n); | ||
| 21 | self.b[self.n..self.n + m].copy_from_slice(&s.as_bytes()[..m]); | ||
| 22 | self.n += m; | ||
| 23 | Ok(()) | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 11 | #[panic_handler] | 27 | #[panic_handler] |
| 12 | fn panic(info: &PanicInfo) -> ! { | 28 | fn panic(info: &PanicInfo) -> ! { |
| 13 | use core::fmt::Write; | 29 | use core::fmt::Write; |
| 30 | |||
| 31 | // A background task (id >= 2) panicked: die gracefully — log it, | ||
| 32 | // mark the task done, switch away. The shell keeps running and | ||
| 33 | // `jobs` shows the corpse. Panics in the shell, idle, ISR context, | ||
| 34 | // or before the scheduler exists still halt the whole system. | ||
| 35 | if rsnix::sched::is_ready() && !rsnix::sched::in_isr() && rsnix::sched::current() >= 2 { | ||
| 36 | let mut buf = [0u8; 192]; | ||
| 37 | let n = { | ||
| 38 | let mut w = PanicBuf { b: &mut buf, n: 0 }; | ||
| 39 | let _ = write!(&mut w, "{}", info.message()); | ||
| 40 | if let Some(loc) = info.location() { | ||
| 41 | let _ = write!(&mut w, " at {}:{}", loc.file(), loc.line()); | ||
| 42 | } | ||
| 43 | w.n | ||
| 44 | }; | ||
| 45 | let msg = core::str::from_utf8(&buf[..n]).unwrap_or("task panic"); | ||
| 46 | rsnix::sched::abort_current(msg); | ||
| 47 | } | ||
| 48 | |||
| 14 | rsnix::serial::write_str("\r\n*** PANIC ***\r\n"); | 49 | rsnix::serial::write_str("\r\n*** PANIC ***\r\n"); |
| 15 | let _ = write!(&mut rsnix::serial::SerialWriter, "{}\r\n", info.message()); | 50 | let _ = write!(&mut rsnix::serial::SerialWriter, "{}\r\n", info.message()); |
| 16 | if let Some(loc) = info.location() { | 51 | if let Some(loc) = info.location() { |
| @@ -114,6 +149,11 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut | |||
| 114 | rsnix::serial_println!("serial: COM1 115200 8N1"); | 149 | rsnix::serial_println!("serial: COM1 115200 8N1"); |
| 115 | rsnix::ps2::init(); | 150 | rsnix::ps2::init(); |
| 116 | rsnix::serial_println!("ps2: keyboard initialized"); | 151 | rsnix::serial_println!("ps2: keyboard initialized"); |
| 152 | if rsnix::gdt::init() { | ||
| 153 | rsnix::serial_println!("gdt: own GDT + TSS (IST: page-fault/double-fault)"); | ||
| 154 | } else { | ||
| 155 | rsnix::serial_println!("gdt: kept UEFI GDT (IST fault stacks off)"); | ||
| 156 | } | ||
| 117 | rsnix::interrupts::init(); | 157 | rsnix::interrupts::init(); |
| 118 | rsnix::serial_println!("intr: IDT loaded, PIC remapped, timer ~100 Hz"); | 158 | rsnix::serial_println!("intr: IDT loaded, PIC remapped, timer ~100 Hz"); |
| 119 | 159 | ||
| @@ -151,6 +191,12 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut | |||
| 151 | rsnix::serial_println!("pg: self-test FAILED"); | 191 | rsnix::serial_println!("pg: self-test FAILED"); |
| 152 | } | 192 | } |
| 153 | 193 | ||
| 194 | // Scheduler init needs the page allocator (idle task's stack + guard | ||
| 195 | // page) and the adopted page tables, so it runs after the memory | ||
| 196 | // subsystem is fully up. The tick (interrupts::init) is already | ||
| 197 | // live, which is what `sleep`/wake scheduling depends on. | ||
| 198 | rsnix::sched::init(); | ||
| 199 | |||
| 154 | let t = rsnix::rtc::now(); | 200 | let t = rsnix::rtc::now(); |
| 155 | rsnix::serial_println!( | 201 | rsnix::serial_println!( |
| 156 | "rtc: {}-{:02}-{:02} {:02}:{:02}:{:02}", | 202 | "rtc: {}-{:02}-{:02} {:02}:{:02}:{:02}", |
