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 --- shell/src/lib.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'shell/src') diff --git a/shell/src/lib.rs b/shell/src/lib.rs index b2c4a1b..a32d259 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -41,6 +41,24 @@ pub fn run() -> ! { env!("CARGO_PKG_VERSION") )); + // A crash report from a previous run survives on the disk (the fault + // handler writes crash.log on the mounted volume before halting; real + // hardware has no serial console). Surface it so the user can report it. + if let Some(h) = rsnix::fs::read_crash_log() { + term_println("!!! PREVIOUS CRASH REPORT:"); + let mut buf = [0u8; 256]; + if let Ok(n) = rsnix::fs::read(h, &mut buf, 0) + && n > 0 { + let s = core::str::from_utf8(&buf[..n]).unwrap_or("?"); + for line in s.split('\n') { + if !line.is_empty() { + term_println(line); + } + } + } + term_println("!!! end of crash report"); + } + loop { // Push any deferred scrolls so the prompt renders on a current // framebuffer (e.g. after a streaming command's batch of output). @@ -722,6 +740,7 @@ write `{} TIL `", "kill" => cmd_kill(&parsed), "demo" => cmd_demo(&parsed), "fault" => cmd_fault(), + "crashlog" => cmd_crashlog(), "stall" => cmd_stall(&parsed), _ => term_err(&alloc::format!("unknown command: {}", cmd)), } @@ -820,6 +839,14 @@ fn cmd_fault() { } } +/// Debug hook: run the crash-log FAT write from the *shell* context (not +/// the fault ISR) to compare behaviour. +fn cmd_crashlog() { + let lines = ["!!! test crashlog write", "second line", "third line"]; + rsnix::fs::write_crash_log(&lines); + term_println("crashlog: done"); +} + /// Set the display-store stall (cycles per word) — diagnostics knob that /// simulates the per-write cost of an uncached real-GPU framebuffer so /// the preemptive scheduler races long scroll pushes like on real -- cgit v1.2.3