From 045c9ddf71b62dff538cd3ae1963166ab5c145a0 Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 2 Aug 2026 01:52:10 +0200 Subject: v0.5.5: visible boot progress + panic-on-screen for real hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Real hardware has no serial console: a pre-shell panic was a silent blank screen (the panic handler only wrote to serial, then cli;hlt). v0.5.4's shadow change made this window reachable — if the fb-aware page allocation or the heap fallback failed on hardware, the kernel halted before the shell banner with zero screen output. - gop::boot_marker(): every boot stage now draws straight to the framebuffer (row 0, white-on-black). The last marker visible before a hang identifies where the kernel died. - Panic handler: pre-shell panics now draw a white-on-red '*** PANIC *** at file:line' band via gop::dump_lines. - init_shadow(): heap fallback is panic-proof (try_reserve_exact + resize instead of vec![0; words] which aborts on OOM); page-alloc result defensively re-checked against the fb region; any failure degrades to no-shadow mode with a visible warning band. - Verified: full chain (rsboot -> kernel) boots with markers, shell banner renders, all 5 test suites pass. --- rsdos/src/main.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'rsdos/src/main.rs') diff --git a/rsdos/src/main.rs b/rsdos/src/main.rs index 3153930..b6393ee 100644 --- a/rsdos/src/main.rs +++ b/rsdos/src/main.rs @@ -45,6 +45,31 @@ fn panic(info: &PanicInfo) -> ! { loc.line() ); } + // Real hardware has no serial console — put the panic on the screen + // too (white-on-red band), so a pre-shell panic is not a silent + // blank screen. + let mut loc_buf = [0u8; 96]; + let mut msg_buf = [0u8; 128]; + let loc_n = { + let mut w = rsnix::strbuf::FmtBuf::new(&mut loc_buf); + if let Some(loc) = info.location() { + let _ = write!(&mut w, "at {}:{}", loc.file(), loc.line()); + } else { + let _ = write!(&mut w, "(no location)"); + } + w.len() + }; + let msg_n = { + let mut w = rsnix::strbuf::FmtBuf::new(&mut msg_buf); + let _ = write!(&mut w, "{}", info.message()); + w.len() + }; + let lines = [ + "*** PANIC ***", + core::str::from_utf8(&msg_buf[..msg_n]).unwrap_or("?"), + core::str::from_utf8(&loc_buf[..loc_n]).unwrap_or("?"), + ]; + rsnix::gop::dump_lines(&lines); loop { unsafe { core::arch::asm!("cli; hlt"); @@ -121,9 +146,11 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut } else { rsnix::serial_println!("gop: not found (0x{:x})", gop_result); } + rsnix::gop::boot_marker("rsnix v0.5.5 booting.."); rsnix::vt::init(); let (rows, cols) = rsnix::vt::size(); rsnix::serial_println!("vt: terminal ready ({}x{})", rows, cols); + rsnix::gop::boot_marker("rsnix: gop+vt ok"); // ExitBootServices — we now own the machine if unsafe { (bs.exit_boot_services)(image_handle, map_key) } != EFI_SUCCESS { @@ -158,6 +185,7 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut } rsnix::interrupts::init(); rsnix::serial_println!("intr: IDT loaded, PIC remapped, timer ~100 Hz"); + rsnix::gop::boot_marker("rsnix: serial+ps2+gdt+intr ok"); dump_memory_summary(); @@ -173,6 +201,7 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut rsnix::serial_println!("pages: init FAILED"); } rsnix::gop::init_shadow(); + rsnix::gop::boot_marker("rsnix: shadow ok"); if rsnix::memory::page_self_test() { rsnix::serial_println!("pages: self-test OK (alloc/free/runs)"); } else { @@ -228,6 +257,7 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut } rsnix::serial_println!("boot: entering shell"); + rsnix::gop::boot_marker("rsnix: boot done — shell"); if rsnix::ps2::mouse_present() { rsnix::cursor::spawn(); } else { -- cgit v1.2.3