diff options
| author | salmonik <salmonik@tuta.io> | 2026-08-02 15:21:34 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-08-02 15:21:34 +0200 |
| commit | c7d92071e1dd11c45999457b16554b4abaa73b28 (patch) | |
| tree | aff7c7f19adcffe1dd91e1c2514af02c77fd524e /rsdos/src/main.rs | |
| parent | v0.5.5: fix real-hardware boot crash — shadow back in heap as first allocation (diff) | |
| download | rs-dos-c7d92071e1dd11c45999457b16554b4abaa73b28.tar.gz rs-dos-c7d92071e1dd11c45999457b16554b4abaa73b28.zip | |
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/<uid>/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
Diffstat (limited to 'rsdos/src/main.rs')
| -rw-r--r-- | rsdos/src/main.rs | 37 |
1 files changed, 36 insertions, 1 deletions
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) -> ! { | |||
| 81 | core::str::from_utf8(&stage_buf[..stage_n]).unwrap_or(""), | 81 | core::str::from_utf8(&stage_buf[..stage_n]).unwrap_or(""), |
| 82 | ]; | 82 | ]; |
| 83 | rsnix::gop::dump_lines(&lines); | 83 | rsnix::gop::dump_lines(&lines); |
| 84 | // Persist to the disk so the report survives the reboot on real | ||
| 85 | // hardware (no serial console). Best-effort; heap-free lines. | ||
| 86 | rsnix::fs::write_crash_log(&lines); | ||
| 84 | loop { | 87 | loop { |
| 85 | unsafe { | 88 | unsafe { |
| 86 | core::arch::asm!("cli; hlt"); | 89 | core::arch::asm!("cli; hlt"); |
| @@ -107,6 +110,31 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut | |||
| 107 | // Keep the runtime-services table for later (ResetSystem → poweroff). | 110 | // Keep the runtime-services table for later (ResetSystem → poweroff). |
| 108 | rsnix::power::init(st.runtime_services); | 111 | rsnix::power::init(st.runtime_services); |
| 109 | 112 | ||
| 113 | // Capture the kernel's own image range BEFORE ExitBootServices: the | ||
| 114 | // heap and page allocators must never hand out the running kernel's | ||
| 115 | // code/data/bss pages (a heap allocation landing on the .bss corrupts | ||
| 116 | // statics like the FAT ACTIVE_VOL — observed as a dead filesystem in | ||
| 117 | // the fault path). | ||
| 118 | unsafe { | ||
| 119 | let mut li: *mut core::ffi::c_void = core::ptr::null_mut(); | ||
| 120 | let li_guid = rsnix::uefi::EFI_LOADED_IMAGE_PROTOCOL_GUID; | ||
| 121 | if (bs.handle_protocol)(image_handle, &li_guid as *const rsnix::uefi::Guid, &mut li) | ||
| 122 | == rsnix::uefi::EFI_SUCCESS | ||
| 123 | && !li.is_null() | ||
| 124 | { | ||
| 125 | let p = &*(li as *const rsnix::uefi::LoadedImageProtocol); | ||
| 126 | rsnix::memory::set_kernel_image_range(p.image_base as usize, p.image_size as usize); | ||
| 127 | rsnix::serial_println!( | ||
| 128 | "mem: kernel image 0x{:x}..0x{:x} ({} KiB) reserved", | ||
| 129 | p.image_base as usize, | ||
| 130 | p.image_base as usize + p.image_size as usize, | ||
| 131 | p.image_size as usize / 1024 | ||
| 132 | ); | ||
| 133 | } else { | ||
| 134 | rsnix::serial_println!("mem: WARNING — kernel image range unknown"); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 110 | // ---- Phase 1: UEFI boot services alive ---- | 138 | // ---- Phase 1: UEFI boot services alive ---- |
| 111 | 139 | ||
| 112 | // Print banner via UEFI console | 140 | // Print banner via UEFI console |
| @@ -208,7 +236,14 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut | |||
| 208 | dump_memory_summary(); | 236 | dump_memory_summary(); |
| 209 | 237 | ||
| 210 | if rsnix::memory::self_test() { | 238 | if rsnix::memory::self_test() { |
| 211 | rsnix::serial_println!("heap: self-test OK (alloc/free/coalesce)"); | 239 | let hs = rsnix::memory::heap_stats(); |
| 240 | rsnix::serial_println!( | ||
| 241 | "heap: self-test OK (0x{:x}..0x{:x} {} KiB free={} KiB)", | ||
| 242 | hs.heap_start, | ||
| 243 | hs.heap_end, | ||
| 244 | hs.heap_size / 1024, | ||
| 245 | hs.free_bytes / 1024 | ||
| 246 | ); | ||
| 212 | } else { | 247 | } else { |
| 213 | rsnix::serial_println!("heap: self-test FAILED"); | 248 | rsnix::serial_println!("heap: self-test FAILED"); |
| 214 | } | 249 | } |
