summaryrefslogtreecommitdiffstats
path: root/tools/qrcheck/src
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-08-03 02:23:35 +0200
committersalmonik <salmonik@tuta.io>2026-08-03 02:23:35 +0200
commit9fde94d068f87b34e0bc6bfa48388d89bb54f1e4 (patch)
treea5a4ce95363e7a316a23371489f2b0b85c1a8735 /tools/qrcheck/src
parentv0.5.7: fix vt verify content check — expect BLANK (0x70020), not zero (diff)
downloadrs-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.rs58
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"]
13mod qr;
14
15fn 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}