From c7d92071e1dd11c45999457b16554b4abaa73b28 Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 2 Aug 2026 15:21:34 +0200 Subject: v0.5.5: crash reports go to a dedicated CRASHLOG USB stick The fault handler now writes crash.log to the volume labeled CRASHLOG (label-selected via fat::crash_vol), falling back to slot 0. On real hardware the boot USB may be unwritable, so a second stick labeled CRASHLOG survives the write; the shell auto-prints the previous crash report from it at next boot (read_crash_log resolves /disk//crash.log through the FAT path, since Disk nodes hold no cached children). - fat.rs: volume_label() + crash_vol() (no allocation) - fs.rs: write_crash_log targets crash_vol(); read_crash_log prefers the CRASHLOG disk node; drop now-unused first_disk() - mkdisk.sh: --label option - test-fault.sh: boots with a dedicated CRASHLOG stick (mkfs -F 32 -n CRASHLOG), verifies crash.log lands there and NOT on the ESP --- rsdos/src/main.rs | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'rsdos/src/main.rs') diff --git a/rsdos/src/main.rs b/rsdos/src/main.rs index 2717dff..4521a42 100644 --- a/rsdos/src/main.rs +++ b/rsdos/src/main.rs @@ -81,6 +81,9 @@ fn panic(info: &PanicInfo) -> ! { core::str::from_utf8(&stage_buf[..stage_n]).unwrap_or(""), ]; rsnix::gop::dump_lines(&lines); + // Persist to the disk so the report survives the reboot on real + // hardware (no serial console). Best-effort; heap-free lines. + rsnix::fs::write_crash_log(&lines); loop { unsafe { core::arch::asm!("cli; hlt"); @@ -107,6 +110,31 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut // Keep the runtime-services table for later (ResetSystem → poweroff). rsnix::power::init(st.runtime_services); + // Capture the kernel's own image range BEFORE ExitBootServices: the + // heap and page allocators must never hand out the running kernel's + // code/data/bss pages (a heap allocation landing on the .bss corrupts + // statics like the FAT ACTIVE_VOL — observed as a dead filesystem in + // the fault path). + unsafe { + let mut li: *mut core::ffi::c_void = core::ptr::null_mut(); + let li_guid = rsnix::uefi::EFI_LOADED_IMAGE_PROTOCOL_GUID; + if (bs.handle_protocol)(image_handle, &li_guid as *const rsnix::uefi::Guid, &mut li) + == rsnix::uefi::EFI_SUCCESS + && !li.is_null() + { + let p = &*(li as *const rsnix::uefi::LoadedImageProtocol); + rsnix::memory::set_kernel_image_range(p.image_base as usize, p.image_size as usize); + rsnix::serial_println!( + "mem: kernel image 0x{:x}..0x{:x} ({} KiB) reserved", + p.image_base as usize, + p.image_base as usize + p.image_size as usize, + p.image_size as usize / 1024 + ); + } else { + rsnix::serial_println!("mem: WARNING — kernel image range unknown"); + } + } + // ---- Phase 1: UEFI boot services alive ---- // Print banner via UEFI console @@ -208,7 +236,14 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut dump_memory_summary(); if rsnix::memory::self_test() { - rsnix::serial_println!("heap: self-test OK (alloc/free/coalesce)"); + let hs = rsnix::memory::heap_stats(); + rsnix::serial_println!( + "heap: self-test OK (0x{:x}..0x{:x} {} KiB free={} KiB)", + hs.heap_start, + hs.heap_end, + hs.heap_size / 1024, + hs.free_bytes / 1024 + ); } else { rsnix::serial_println!("heap: self-test FAILED"); } -- cgit v1.2.3