From f846a9551bf30d61026fa9c9ccea78479ced321b Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 2 Aug 2026 23:28:29 +0200 Subject: v0.5.7: drop test-poison hooks; vt heap-struct verify at shell entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OptiPlex's first banner write #GPs when the vt cells VecData holds firmware 0xAA fill instead of a real buffer pointer. The poison/fill test hooks (stack + free-heap + free-page 0x00AAAAAA) were removed from the release image — they changed boot behavior and may walk a corrupt free list over live blocks. Added vt::debug_verify() (cells/rendered ptr/cap/len + in-heap check) at shell entry: the next real-hardware boot shows whether the corruption is present at shell entry or lands during the banner write. --- rsnix/src/vt.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'rsnix/src/vt.rs') diff --git a/rsnix/src/vt.rs b/rsnix/src/vt.rs index 4578f6c..6343b78 100644 --- a/rsnix/src/vt.rs +++ b/rsnix/src/vt.rs @@ -138,6 +138,48 @@ pub fn size() -> (usize, usize) { unsafe { (ROWS, COLS) } } +/// Shell-entry self-check: dump the vt grid's heap structs so a real- +/// hardware boot shows whether the cells VecData / data arrays are sane +/// at shell entry (the OptiPlex's first banner write #GPs when the +/// cells buffer holds firmware 0xAA fill instead of real pointers). +pub fn debug_verify() { + unsafe { + let total = ROWS * COLS; + let msg = |m: &str| { + crate::serial_println!("vt: {}", m); + }; + if CELLS.is_null() || RENDERED.is_null() { + msg("verify: cells/renderd NULL — vt::init did not run"); + return; + } + let c = &*(CELLS as *const Vec); + let r = &*(RENDERED as *const Vec); + msg(&alloc::format!( + "verify: cells ptr={:#x} cap={:#x} len={:#x} rendered ptr={:#x} cap={:#x} len={:#x} want={:#x}", + c.as_ptr() as usize, + c.capacity(), + c.len(), + r.as_ptr() as usize, + r.capacity(), + r.len(), + total + )); + // The cells array must cover rows*cols and be inside the heap. + let heap_ok = crate::memory::heap_range() + .map(|(hs, he)| { + let p = c.as_ptr() as usize; + let bytes = c.capacity().saturating_mul(core::mem::size_of::()); + p >= hs && p + bytes <= he + }) + .unwrap_or(false); + if c.len() != total || r.len() != total || !heap_ok { + msg("verify: FAILED — cells/rendered not sane at shell entry"); + } else { + msg("verify: ok"); + } + } +} + pub fn set_cursor_visible(v: bool) { sync_scroll(); unsafe { -- cgit v1.2.3