code wiki / _hdl_build / nx_drv_proto_emit.nx

nx_drv_proto_emit.nx

buildroot/runtime/_hdl_build/nx_drv_proto_emit.nx

24138 B453 linesdepth 2pulls 2 transitivereach 0 importersview sourcekind tooltopic drv
docsdependenciesstructsconstsfunctions

about

nx_drv_proto_emit.nx -- DRIVER-PROTOCOL-FROM-SPEC (X-DRV-W1), the GENERIC driver emitter. The thesis (driver-as-shape-composition): a driver SPEC carries the device register map (base + offsets) AND -- crucially -- the PROTOCOL STEP-SEQUENCE itself as DATA: an op-list (the STATE_MACHINE shape). This organ WALKS that op-list and SYNTHESIZES a bare-metal rv64 driver image whose control flow IS the spec's sequence -- so a DIFFERENT protocol sequence is a DIFFERENT spec -> a DIFFERENT driver, with ZERO emitter changes. That is the emitter-of- emitters keystone (X-AUT-006c/e) COMPOSED into the device-driver layer (X-DRV-W0 HWMAP gives the bind side; this gives the protocol side). CONTRAST with nx_virtio_hs_emit: that emitter parameterises the virtio register offsets/values from a spec but HARD-CODES the protocol sequence (identity->ACK->FEAT->VQ->DESC->USED->...). Here the sequence is DATA, so virtio-blk is merely ONE spec instance (the last-mile/benchmark transport per the nishi-ecosystem-only law); a virtio-net handshake, or a future Nishi-native device protocol, is simply a different op-list. The gate proves this by emitting TWO distinct op-lists from the ONE binary and running BOTH against the real devices on the sovereign emu. SPEC FORMAT (line-based, '#'=comment): out <path> where to write the flat image (and <path>.gold) base <hex> device MMIO base (0x1000-aligned -> lui t2) op verify <regoff> <const> LW reg ; li const ; bne -> fail (signed read-back) op verifyu <regoff> <const> LWU reg ; li const ; bne -> fail (unsigned/address read-back) op write <regoff> <val> li val ; SW reg (also: notify = a write) op notify <regoff> <val> alias for write (device kick) op read <regoff> LW reg (exercise a RO register, value discarded) op checkbit <regoff> <mask> LW reg ; li mask ; and ; beq x0 -> fail (bit-stuck proof) op setbase <addr> li32u t5 = addr (membase for the following memstore ops) op memstore <memoff> <f3> <val> li val ; S[f3] val, memoff(t5) (f3: 1=SH 2=SW; ring/desc lay) op emit <literal-to-eol> write the literal bytes over the UART (the transcript token) The image always ends with the SiFive finisher (clean halt). Any verify/checkbit that fails BRANCHES PAST the rest of the op-list to the finisher, so the transcript loses its tail -- that is the tamper handle the gate exploits. nx_drv_proto_emit <specpath> -> the spec's `out` (flat rv64 image) + <out>.gold (golden transcript = the concatenation of the emit literals, in op order). VERDICT log -> knowledge/status/driver_spec.log. Sovereign: syscalls only, no gcc/.sh. license_tier: ORIGINAL

dependencies 1 imports · 0 importers

nx_syscalls.nx nx_drv_proto_emit.nx

imports: nx_syscalls.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main dp_p sys_write sys_exit sys_mmap sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_close dp_log sys_openat_append dp_fp sys_write ↻ dp_fn sys_mmap ↻ sys_write ↻ sys_close ↻ dp_num_field sys_mmap ↻ dp_parse_num dp_str_field dp_kw dp_parse_num ↻ dp_emit_image dp_w32 dp_lui dp_op_verify dp_w32 ↻ dp_load dp_li32 dp_w32 ↻ dp_lui ↻ dp_addi dp_branch dp_op_write dp_li32 ↻ dp_w32 ↻ dp_store

structs

none

consts

39const DP_MAGIC_16384: i64 = 16384
42const DP_UART: i64 = 0x10000000 // NS16550A THR (write a byte = transmit)
43const DP_FIN: i64 = 0x100000 // SiFive test finisher (write to exit)
44const DP_PASS: i64 = 0x5555 // FINISHER_PASS low half -> clean halt
46const RV_X0: i64 = 0
47const RV_T0: i64 = 5 // UART base
48const RV_T1: i64 = 6 // scratch / transcript byte / write value
49const RV_T2: i64 = 7 // device MMIO base
50const RV_T3: i64 = 28 // loaded register value (actual)
51const RV_T4: i64 = 29 // expected constant
52const RV_T5: i64 = 30 // finisher base / membase (set by setbase)
55const OP_VERIFY: i64 = 1 // a0=regoff a1=const (signed LW)
56const OP_VERIFYU: i64 = 2 // a0=regoff a1=const (unsigned LWU)
57const OP_WRITE: i64 = 3 // a0=regoff a1=val
58const OP_READ: i64 = 4 // a0=regoff
59const OP_CHECKBIT: i64 = 5 // a0=regoff a1=mask
60const OP_SETBASE: i64 = 6 // a0=addr (li32u t5)
61const OP_MEMSTORE: i64 = 7 // a0=memoff a1=f3 a2=val
62const OP_EMIT: i64 = 8 // a0=tail-offset a1=len
64const DP_MAXOP: i64 = 256
65const DP_TAILCAP: i64 = 2048

functions

68func dp_lui(rd: i64, imm20: i64) -> i64 { return ((imm20 & 0xFFFFF) << 12) | (rd << 7) | 0x37 }
69func dp_addi(rd: i64, rs1: i64, imm: i64) -> i64 { return ((imm & 0xFFF) << 20) | (rs1 << 15) | (rd << 7) | 0x13 }
71func dp_load(rd: i64, rs1: i64, f3: i64, imm: i64) -> i64 { return ((imm & 0xFFF) << 20) | (rs1 << 15) | (f3 << 12) | (rd << 7) | 0x03 }
73func dp_store(rs2: i64, rs1: i64, f3: i64, imm: i64) -> i64
79func dp_branch(rs1: i64, rs2: i64, f3: i64, imm: i64) -> i64
87func dp_jal(rd: i64, imm: i64) -> i64
called by 1: dp_emit_finisher
95func dp_and(rd: i64, rs1: i64, rs2: i64) -> i64 { return (rs2 << 20) | (rs1 << 15) | (7 << 12) | (rd << 7) | 0x33 }
called by 1: dp_op_checkbit
97func dp_shift(rd: i64, rs1: i64, f3: i64, shamt: i64) -> i64 { return ((shamt & 0x3f) << 20) | (rs1 << 15) | (f3 << 12) | (rd << 7) | 0x13 }
called by 1: dp_li32u
99func dp_w32(buf: *u8, off: i64, w: i64) -> i64
110func dp_li32(buf: *u8, off: i64, rd: i64, val: i64) -> i64
121func dp_li32u(buf: *u8, off: i64, rd: i64, val: i64) -> i64
called by 1: dp_emit_image calls 3: dp_li32dp_w32dp_shift
129func dp_emit_bytes(buf: *u8, off: i64, s: *u8, n: i64) -> i64
called by 1: dp_emit_image calls 3: dp_w32dp_addidp_store
142func dp_op_verify(buf: *u8, off: i64, regoff: i64, expected: i64, f3sel: i64, fail_off: i64) -> i64
151func dp_op_write(buf: *u8, off: i64, regoff: i64, val: i64) -> i64
called by 1: dp_emit_image calls 3: dp_li32dp_w32dp_store
158func dp_op_read(buf: *u8, off: i64, regoff: i64) -> i64
called by 1: dp_emit_image calls 2: dp_w32dp_load
163func dp_op_checkbit(buf: *u8, off: i64, regoff: i64, mask: i64, fail_off: i64) -> i64
173func dp_op_memstore(buf: *u8, off: i64, memoff: i64, f3: i64, val: i64) -> i64
called by 1: dp_emit_image calls 3: dp_li32dp_w32dp_store
180func dp_emit_finisher(buf: *u8, off: i64) -> i64
191func dp_emit_image(buf: *u8, base: i64, opc: *i64, oa0: *i64, oa1: *i64, oa2: *i64, nop: i64, tail: *u8, fail_off: i64) -> i64
213func dp_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
called by 1: main calls 1: sys_write
214func dp_fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
called by 1: dp_log calls 1: sys_write
215func dp_fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 }
called by 2: dp_logmain calls 2: sys_mmapsys_write
219func dp_parse_num(buf: *u8, p: i64, le: i64, endp: *i64) -> i64
called by 2: dp_num_fieldmain
251func dp_num_field(buf: *u8, ls: i64, le: i64, key: *u8, out: *i64) -> i64
called by 1: main calls 2: sys_mmapdp_parse_num
264func dp_str_field(buf: *u8, ls: i64, le: i64, key: *u8, out: *u8) -> i64
called by 1: main
279func dp_kw(buf: *u8, p: i64, le: i64, kw: *u8) -> i64
called by 1: main
291func dp_log(name: *u8, bytes: i64, golden: *u8, verdict: *u8) -> i64
302func main(argc: i64, argv: *i64) -> i64