nx_printer_fw_sim_test.nx source
↩ module page · 66 lines · 3588 B
1// nx_printer_fw_sim_test.nx -- the NEVER-BRICK gate (#26, brand-critical) for the firmware-flash simulator.
2// Proves MECHANICALLY (not by promise) that the A/B flash can never brick the virtual printer, by injecting
3// power loss at EVERY step x EVERY firmware quality and asserting the device ALWAYS boots something. A naive
4// in-place flash is the negative control: it CAN brick, so the gate is proven to DETECT bricking.
5// Unique exit codes:
6// 1 EXHAUSTIVE: A/B flash never bricks (2 sig x 2 boots x 5 power-loss-steps = 20 scenarios)
7// 2-5 specific outcomes (good->new active; mid-write->old; bad-sig->old rejected; bad-boot->rolled back)
8// 10 NEGATIVE CONTROL: naive in-place flash CAN brick (single-bank, power loss mid-write)
9// 11 and the SAFE A/B flash does NOT brick that same single-bank/power-loss case
10// expect_exit: 0 ; license_tier: ORIGINAL ; genealogy_id: project-printer-management-ipp-sclass-2026-06-20
11
12import "nx_syscalls.nx"
13import "nx_printer_fw_sim.nx"
14
15func t_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
16
17// init: bank A bootable + active, bank B absent; then A/B-flash a new image and boot. Returns fw_boot result.
18func scenario(st: *i64, sig: i64, boots: i64, step: i64) -> i64 {
19 st[0] = 0
20 fw_set_bank(st, 0, 1, 1, 1, 1)
21 fw_set_bank(st, 1, 0, 0, 0, 0)
22 fw_flash_ab(st, 2, sig, boots, step)
23 return fw_boot(st)
24}
25
26func main() -> i64 {
27 let st: *i64 = sys_mmap(128) as *i64
28
29 // ===== EXHAUSTIVE never-brick: 2 sig x 2 boots x 5 power-loss steps, ALL must stay bootable =====
30 var sig: i64 = 0
31 while sig <= 1 {
32 var boots: i64 = 0
33 while boots <= 1 {
34 var step: i64 = 0
35 while step <= 4 {
36 if scenario(st, sig, boots, step) == NX_FW_BRICKED { return 1 }
37 step = step + 1
38 }
39 boots = boots + 1
40 }
41 sig = sig + 1
42 }
43
44 // ===== specific expected outcomes =====
45 if scenario(st, 1, 1, 0) != 1 { return 2 } // good fw, no power loss -> new fw (bank B) active + boots
46 if scenario(st, 1, 1, 1) != 0 { return 3 } // power loss mid-write -> inactive corrupt, old (bank A) still boots
47 if scenario(st, 0, 1, 0) != 0 { return 4 } // bad signature -> rejected before flip, old (A) still boots
48 if scenario(st, 1, 0, 0) != 0 { return 5 } // sig ok but image doesn't boot -> bootloader rolls back to A
49
50 // ===== NEGATIVE CONTROL: a NAIVE in-place flash CAN brick (single bank, power loss mid-write) =====
51 st[0] = 0
52 fw_set_bank(st, 0, 1, 1, 1, 1) // only bank A present
53 fw_set_bank(st, 1, 0, 0, 0, 0) // bank B absent (no fallback)
54 fw_flash_naive(st, 2, 1, 1, 1) // power loss step 1 -> corrupts the ACTIVE bank
55 if fw_boot(st) != NX_FW_BRICKED { return 10 } // the naive flash MUST be able to brick (gate discriminates)
56
57 // ...and the SAFE A/B flash on the exact same single-bank/power-loss case does NOT brick:
58 st[0] = 0
59 fw_set_bank(st, 0, 1, 1, 1, 1)
60 fw_set_bank(st, 1, 0, 0, 0, 0)
61 fw_flash_ab(st, 2, 1, 1, 1) // power loss mid-write hits the INACTIVE bank -> A intact
62 if fw_boot(st) == NX_FW_BRICKED { return 11 }
63
64 t_puts("nx_printer_fw_sim: PASS A/B flash NEVER bricks across 20 power-loss x firmware-quality scenarios (good->new, mid-write->old, bad-sig->rejected, bad-boot->rolled-back); naive in-place flash CAN brick (neg control). #26 proven mechanically -- real flashing stays gated.\n")
65 return 0
66}