summaryrefslogtreecommitdiffstats
path: root/rsnix/src/vt.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-08-03 00:21:52 +0200
committersalmonik <salmonik@tuta.io>2026-08-03 00:21:52 +0200
commit834b931d068a9a76e2c2a85267f24a22e93276cf (patch)
tree55fec8d47398a51a0c40dec8fba4f9664a12233a /rsnix/src/vt.rs
parentv0.5.7: vt verify also as a boot marker (real hardware has no serial) (diff)
downloadrs-dos-834b931d068a9a76e2c2a85267f24a22e93276cf.tar.gz
rs-dos-834b931d068a9a76e2c2a85267f24a22e93276cf.zip
v0.5.7: guard dumps block-header math + 16-word window; vt content verify; shadow marker
The klog -t 2 crash drops a 126-byte String (the vt verify klog line) whose data ptr 0x40444970 points into the first-heap-block region whose content is the firmware 0x00AAAAAA scrub — a stale pointer, not a real allocation (back-pointer slot never written). Upgrades so the next real-hardware crash shows the full picture: - guard: explicit candidate block bases (b=ptr-24 / b16=ptr-32) with their size/free fields, plus a 16-word window (mem..mem4) from ptr-0x30 instead of the old 8 words - vt::debug_verify: content probe of the cells grid (must be all-BLANK at shell entry) — catches a stale in-heap cells pointer that passes the range checks - gop: on-screen marker for shadow carved vs NO-SHADOW fallback (the scrub content at the crash ptr suggests the shadow was rejected and its block stayed free + firmware-scrubbed)
Diffstat (limited to 'rsnix/src/vt.rs')
-rw-r--r--rsnix/src/vt.rs33
1 files changed, 30 insertions, 3 deletions
diff --git a/rsnix/src/vt.rs b/rsnix/src/vt.rs
index 2d8ece6..2906258 100644
--- a/rsnix/src/vt.rs
+++ b/rsnix/src/vt.rs
@@ -172,13 +172,40 @@ pub fn debug_verify() {
172 p >= hs && p + bytes <= he 172 p >= hs && p + bytes <= he
173 }) 173 })
174 .unwrap_or(false); 174 .unwrap_or(false);
175 if c.len() != total || r.len() != total || !heap_ok { 175 // Content check: at shell entry nothing has been printed yet, so
176 // every cell must still be BLANK (all-zero). A stale cells data
177 // pointer that happens to be in-heap still passes the range
178 // checks (len/cap look fine) but its "cells" read back as the
179 // underlying memory's leftover fill — the OptiPlex shows the
180 // firmware 0x00AAAAAA scrub there. This catches that.
181 let mut content_ok = true;
182 if heap_ok && c.len() == total && total > 0 {
183 let mut i = 0usize;
184 // Sample the first cell, the last cell, and a few interior
185 // cells — reading the whole grid here would be ~60 KiB of
186 // checks at every boot for no real benefit.
187 let probes = [0usize, total / 3, (2 * total) / 3, total - 1];
188 for &p in probes.iter() {
189 if i >= probes.len() {
190 break;
191 }
192 i += 1;
193 let cell = *c.as_ptr().add(p);
194 let raw = cell.ch as u32 | ((cell.fg as u32) << 16) | ((cell.bg as u32) << 24);
195 if raw != 0 {
196 content_ok = false;
197 break;
198 }
199 }
200 }
201 if c.len() != total || r.len() != total || !heap_ok || !content_ok {
176 msg("verify: FAILED — cells/rendered not sane at shell entry"); 202 msg("verify: FAILED — cells/rendered not sane at shell entry");
177 crate::gop::boot_marker(&alloc::format!( 203 crate::gop::boot_marker(&alloc::format!(
178 "vt: cells {:#x} {}/{} FAILED", 204 "vt: cells {:#x} {}/{} {}",
179 c.as_ptr() as usize, 205 c.as_ptr() as usize,
180 c.len(), 206 c.len(),
181 total 207 total,
208 if content_ok { "range" } else { "CONTENT-GARBAGE" }
182 )); 209 ));
183 } else { 210 } else {
184 msg("verify: ok"); 211 msg("verify: ok");