summaryrefslogtreecommitdiffstats
path: root/rsdos
diff options
context:
space:
mode:
Diffstat (limited to 'rsdos')
-rw-r--r--rsdos/src/main.rs46
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).
13struct PanicBuf<'a> {
14 b: &'a mut [u8],
15 n: usize,
16}
17
18impl 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]
12fn panic(info: &PanicInfo) -> ! { 28fn 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}",