diff options
| author | salmonik <salmonik@tuta.io> | 2026-08-03 02:23:35 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-08-03 02:23:35 +0200 |
| commit | 9fde94d068f87b34e0bc6bfa48388d89bb54f1e4 (patch) | |
| tree | a5a4ce95363e7a316a23371489f2b0b85c1a8735 /tools/qrcheck/src | |
| parent | v0.5.7: fix vt verify content check — expect BLANK (0x70020), not zero (diff) | |
| download | rs-dos-9fde94d068f87b34e0bc6bfa48388d89bb54f1e4.tar.gz rs-dos-9fde94d068f87b34e0bc6bfa48388d89bb54f1e4.zip | |
v0.5.8: heap-free QR encoder + crash-dump QR on framebuffer
Real hardware has no serial console, so a kernel crash only leaves a
frozen screen. Every dump_lines() report now also renders the crash
text as a scannable QR below the white-on-red band (photograph the
screen instead of relaying text).
- rsnix/src/qr.rs: from-scratch no_std/no_alloc byte-mode QR encoder
(EC-L, v1..v40, .bss statics only — safe on the fault path):
RS over GF(256), codeword interleave, zigzag placement, 8 masks with
N1-N4 penalty auto-selection, format/version info.
- gop.rs: dump_qr() joins dump lines into a static buffer, truncates
with '...' at the v40-L capacity, encodes, and renders centered
black-on-white with a 4-module quiet zone.
- tools/qrcheck: host harness (embedds qr.rs) + qrcheck.py cross-check
against segno's placement primitives. Verified bit-exact: 12
versions x 8 masks forced, plus auto-mask choice matches segno's
penalty evaluation. Caught 3 encoder bugs (multi-block interleave
offsets, transposed version info, mask eval ordering).
- QEMU e2e: page-fault dump screendump decodes via zbarimg, content
matches the serial log line-for-line.
- test-msg.sh and test-fault.sh both PASS; debug+release 0 warnings.
Diffstat (limited to '')
| -rw-r--r-- | tools/qrcheck/src/main.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/tools/qrcheck/src/main.rs b/tools/qrcheck/src/main.rs new file mode 100644 index 0000000..d294485 --- /dev/null +++ b/tools/qrcheck/src/main.rs | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | //! Host-side cross-check tool for the kernel QR encoder. | ||
| 2 | //! | ||
| 3 | //! Usage: `qrcheck TEXT [VERSION] [MASK]` | ||
| 4 | //! - with VERSION+MASK: force both and dump the matrix (compared against | ||
| 5 | //! segno by `tools/qrcheck.py`); | ||
| 6 | //! - with neither: auto-pick version and best mask, print `v<ver> m<mask>`. | ||
| 7 | //! | ||
| 8 | //! Output: first line `v<N> m<N|999>`, then one line per matrix row of | ||
| 9 | //! `#` (dark) / `.` (light). | ||
| 10 | #![allow(static_mut_refs)] | ||
| 11 | |||
| 12 | #[path = "../../../rsnix/src/qr.rs"] | ||
| 13 | mod qr; | ||
| 14 | |||
| 15 | fn main() { | ||
| 16 | let args: Vec<String> = std::env::args().collect(); | ||
| 17 | if args.get(1).map(String::as_str) == Some("--raw") { | ||
| 18 | let text = args.get(2).map(String::as_str).unwrap_or("hello"); | ||
| 19 | let version: usize = args.get(3).and_then(|s| s.parse().ok()).unwrap_or(0); | ||
| 20 | let v = if version > 0 { | ||
| 21 | qr::encode_at(text.as_bytes(), version, Some(0)) | ||
| 22 | } else { | ||
| 23 | qr::encode(text.as_bytes()) | ||
| 24 | }; | ||
| 25 | if v == 0 { | ||
| 26 | eprintln!("FAIL"); | ||
| 27 | std::process::exit(1); | ||
| 28 | } | ||
| 29 | for b in qr::codeword_stream() { | ||
| 30 | print!("{:02x}", b); | ||
| 31 | } | ||
| 32 | println!(); | ||
| 33 | return; | ||
| 34 | } | ||
| 35 | let text = args.get(1).map(String::as_str).unwrap_or("hello world"); | ||
| 36 | let version: usize = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(0); | ||
| 37 | let mask: Option<usize> = args.get(3).and_then(|s| s.parse().ok()); | ||
| 38 | |||
| 39 | let v = if version > 0 { | ||
| 40 | qr::encode_at(text.as_bytes(), version, mask) | ||
| 41 | } else { | ||
| 42 | qr::encode(text.as_bytes()) | ||
| 43 | }; | ||
| 44 | if v == 0 { | ||
| 45 | eprintln!("FAIL: cannot encode {} bytes at v{}", text.len(), version); | ||
| 46 | std::process::exit(1); | ||
| 47 | } | ||
| 48 | let size = qr::size(); | ||
| 49 | let m = if let Some(m) = mask { m } else { qr::last_mask() }; | ||
| 50 | println!("v{} m{}", v, m); | ||
| 51 | for y in 0..size { | ||
| 52 | let mut row = String::with_capacity(size); | ||
| 53 | for x in 0..size { | ||
| 54 | row.push(if qr::module(x, y) { '#' } else { '.' }); | ||
| 55 | } | ||
| 56 | println!("{}", row); | ||
| 57 | } | ||
| 58 | } | ||
