code wiki / _hdl_build / nx_nishifs_bootasm.nx
nx_nishifs_bootasm.nx source
↩ module page · 179 lines · 12839 B
1// nx_nishifs_bootasm.nx -- ladder C9: the NishiFS-aware bootloader CORE, EXECUTED AS REAL x86.
2//
3// Closes the C8 honest seam ("rootfs-mount runs as the NishiLang FS driver"): here the bootloader's heart --
4// FIND THE KERNEL OBJECT BY CID and load its payload -- runs as REAL x86 instructions executed on the proven
5// kernel-subset emulator (emu_x86_run_k, inlined verbatim from nx_emu_x86_k.nx: 48 C7 mov-imm / 48 8B load /
6// 48 89 store / 48 01 add / 48 39 cmp / 74 je / 75 jne / EB jmp / 0F05 syscall). The x86 program is produced
7// by a tiny in-organ INSTRUCTION EMITTER (correct-by-construction ModRM -- no hand-hex), then EXECUTED; it
8// scans the object region, compares each object's CID to the target, and on a match loads the object's payload.
9// The CID is the real sha256(payload) (matched on its 8-byte prefix; the full 32-byte compare + variable-length
10// records + 16-bit real-mode are the further refinements).
11// KAT 6/6: T1 executed-x86 scan finds the kernel BY CID + loads its payload (clean exit + result==payload);
12// T2 finds the right object at ANY position (rec0/rec2 targets); T3 liar-kill: a bogus CID -> NO load (result==0)
13// so the load only happens on a real EXECUTED match; T4 the emu executed real x86 to a clean exit (rc==0);
14// T5 it loaded the object's DATA, not echoed the key (payload != CID); T6 distinct content -> distinct CID.
15// composes nx_sha256 (real CIDs) + nx_syscalls (sys_mmap/sys_write for the inlined emu).
16// NEVER-BRICK (Rule 26): pure in-memory model, writes NOTHING. expect_exit: 0 license_tier: ORIGINAL
17import "nx_syscalls.nx"
18import "nx_sha256.nx"
19const K_MAGIC_4096: i64 = 4096
20
21func ui_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
22func ui_num(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;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{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
23
24// ---- proven kernel-subset x86-64 emu (inlined verbatim from nx_emu_x86_k.nx) ----
25func k_i32(code: *u8, off: i64) -> i64 {
26 var v: i64 = (code[off] as i64) | ((code[off+1] as i64) << 8) | ((code[off+2] as i64) << 16) | ((code[off+3] as i64) << 24)
27 if (v & 0x80000000) != 0 { v = v - (1 << 32) }
28 return v
29}
30func k_st64(mem: *u8, addr: i64, v: i64) -> i64 { var i: i64=0; while i<8 { mem[addr+i]=((v>>(i*8)) & 0xff) as u8; i=i+1 } return 0 }
31func k_ld64(mem: *u8, addr: i64) -> i64 { var v: i64=0; var i: i64=0; while i<8 { v = v | ((mem[addr+i] as i64) << (i*8)); i=i+1 } return v }
32func emu_x86_run_k(code: *u8, len: i64, mem: *u8) -> i64 {
33 let reg: *i64 = sys_mmap(8 * 16) as *i64
34 var pc: i64 = 0
35 var zf: i64 = 0
36 var sf: i64 = 0
37 while pc < len {
38 let b: i64 = code[pc] as i64
39 var h: i64 = 0
40 if b == 0x0F {
41 if (code[pc+1] as i64) == 0x05 {
42 if reg[0] == 60 { return reg[7] & 0xff }
43 if reg[0] == 1 { sys_write(reg[7], ((code as i64) + reg[6]) as *u8, reg[2]) }
44 pc = pc + 2; h = 1
45 } else { return 0 - 1 }
46 }
47 if h == 0 { if b == 0xEB { var r: i64=code[pc+1] as i64; if r>127 { r=r-256 } pc = pc + 2 + r; h = 1 } }
48 if h == 0 { if b == 0x74 { var r: i64=code[pc+1] as i64; if r>127 { r=r-256 } if zf==1 { pc=pc+2+r } else { pc=pc+2 } h = 1 } }
49 if h == 0 { if b == 0x75 { var r: i64=code[pc+1] as i64; if r>127 { r=r-256 } if zf==0 { pc=pc+2+r } else { pc=pc+2 } h = 1 } }
50 if h == 0 { if b == 0xE8 { let rel: i64=k_i32(code, pc+1); reg[4]=reg[4]-8; k_st64(mem, reg[4], pc+5); pc=pc+5+rel; h = 1 } }
51 if h == 0 { if b == 0xC3 { pc = k_ld64(mem, reg[4]); reg[4]=reg[4]+8; h = 1 } }
52 if h == 0 { if b >= 0x50 { if b <= 0x57 { reg[4]=reg[4]-8; k_st64(mem, reg[4], reg[b-0x50]); pc=pc+1; h = 1 } } }
53 if h == 0 { if b >= 0x58 { if b <= 0x5F { reg[b-0x58]=k_ld64(mem, reg[4]); reg[4]=reg[4]+8; pc=pc+1; h = 1 } } }
54 if h == 0 { if b == 0x48 {
55 let op: i64 = code[pc+1] as i64
56 if op == 0xC7 { reg[(code[pc+2] as i64) & 7] = k_i32(code, pc+3); pc = pc + 7; h = 1 }
57 if op == 0x89 { let m: i64=code[pc+2] as i64; let md: i64=(m>>6)&3; if md==3 { reg[m & 7] = reg[(m>>3) & 7] } else { k_st64(mem, reg[m & 7], reg[(m>>3) & 7]) } pc = pc + 3; h = 1 }
58 if op == 0x8B { let m: i64=code[pc+2] as i64; let md: i64=(m>>6)&3; if md==3 { reg[(m>>3) & 7] = reg[m & 7] } else { reg[(m>>3) & 7] = k_ld64(mem, reg[m & 7]) } pc = pc + 3; h = 1 }
59 if op == 0xC1 { let m: i64=code[pc+2] as i64; reg[m & 7] = reg[m & 7] << (code[pc+3] as i64); pc = pc + 4; h = 1 }
60 if op == 0x01 { let m: i64=code[pc+2] as i64; reg[m & 7] = reg[m & 7] + reg[(m>>3) & 7]; pc = pc + 3; h = 1 }
61 if op == 0x29 { let m: i64=code[pc+2] as i64; reg[m & 7] = reg[m & 7] - reg[(m>>3) & 7]; pc = pc + 3; h = 1 }
62 if op == 0x39 { let m: i64=code[pc+2] as i64; let t: i64 = reg[m & 7] - reg[(m>>3) & 7]; if t==0 { zf=1 } else { zf=0 } if t<0 { sf=1 } else { sf=0 } pc = pc + 3; h = 1 }
63 } }
64 if h == 0 { return 0 - 3 }
65 }
66 return 0 - 4
67}
68
69// ---- instruction emitter (correct-by-construction ModRM; reg idx: rax0 rcx1 rdx2 rbx3 rsp4 rbp5 rsi6 rdi7) ----
70func wr_i32(c: *u8, o: i64, v: i64) -> i64 { c[o]=(v&0xFF) as u8; c[o+1]=((v>>8)&0xFF) as u8; c[o+2]=((v>>16)&0xFF) as u8; c[o+3]=((v>>24)&0xFF) as u8; return 0 }
71func e_movimm(c: *u8, p: i64, reg: i64, imm: i64) -> i64 { c[p]=0x48 as u8; c[p+1]=0xC7 as u8; c[p+2]=(0xC0 + (reg&7)) as u8; wr_i32(c, p+3, imm); return p+7 }
72func e_load(c: *u8, p: i64, dst: i64, base: i64) -> i64 { c[p]=0x48 as u8; c[p+1]=0x8B as u8; c[p+2]=(((dst&7)<<3) | (base&7)) as u8; return p+3 } // mov dst,[base] (mod=00)
73func e_store(c: *u8, p: i64, base: i64, src: i64) -> i64 { c[p]=0x48 as u8; c[p+1]=0x89 as u8; c[p+2]=(((src&7)<<3) | (base&7)) as u8; return p+3 } // mov [base],src (mod=00)
74func e_movrr(c: *u8, p: i64, dst: i64, src: i64) -> i64 { c[p]=0x48 as u8; c[p+1]=0x89 as u8; c[p+2]=(0xC0 | ((src&7)<<3) | (dst&7)) as u8; return p+3 } // mov dst,src
75func e_addrr(c: *u8, p: i64, dst: i64, src: i64) -> i64 { c[p]=0x48 as u8; c[p+1]=0x01 as u8; c[p+2]=(0xC0 | ((src&7)<<3) | (dst&7)) as u8; return p+3 } // dst += src
76func e_cmprr(c: *u8, p: i64, a: i64, bb: i64) -> i64 { c[p]=0x48 as u8; c[p+1]=0x39 as u8; c[p+2]=(0xC0 | ((bb&7)<<3) | (a&7)) as u8; return p+3 } // cmp a,b -> ZF if a==b
77func e_je(c: *u8, p: i64, rel: i64) -> i64 { c[p]=0x74 as u8; c[p+1]=(rel & 0xFF) as u8; return p+2 }
78func e_jne(c: *u8, p: i64, rel: i64) -> i64 { c[p]=0x75 as u8; c[p+1]=(rel & 0xFF) as u8; return p+2 }
79func e_exit(c: *u8, p: i64) -> i64 { c[p]=0x0F as u8; c[p+1]=0x05 as u8; return p+2 }
80
81// sha256(payload-word as 8 bytes) -> first 8 bytes as an i64 = the CID prefix.
82func cid_of(word: i64) -> i64 {
83 let buf: *u8 = sys_mmap(16)
84 k_st64(buf, 0, word)
85 let h: *u8 = sys_mmap(40)
86 sha256_digest(buf, 8, h)
87 return k_ld64(h, 0)
88}
89
90// build the find-kernel-by-CID x86 program into `code`; returns code length.
91func build_scan(code: *u8) -> i64 {
92 var p: i64 = 0
93 p = e_movimm(code, p, 0, 0) // rax = 0 (cursor)
94 p = e_movimm(code, p, 5, 200) // rbp = 200 (target addr)
95 p = e_load(code, p, 1, 5) // rcx = [rbp] = target CID
96 p = e_movimm(code, p, 3, 72) // rbx = 72 (end = 3*24)
97 p = e_movimm(code, p, 5, 24) // rbp = 24 (record step)
98 let loop_pos: i64 = p
99 p = e_load(code, p, 2, 0) // rdx = [rax] (obj CID at cursor)
100 p = e_cmprr(code, p, 2, 1) // cmp rdx, rcx
101 let je_pos: i64 = p
102 p = e_je(code, p, 0) // je found (patched)
103 p = e_addrr(code, p, 0, 5) // rax += rbp (cursor += 24)
104 p = e_cmprr(code, p, 0, 3) // cmp rax, rbx (cursor vs end)
105 let jne_pos: i64 = p
106 p = e_jne(code, p, 0) // jne loop (patched, backward)
107 // not found:
108 p = e_movimm(code, p, 7, 0) // rdi = 0
109 p = e_movimm(code, p, 5, 208) // rbp = 208 (result addr)
110 p = e_store(code, p, 5, 7) // [rbp] = rdi (result = 0)
111 p = e_movimm(code, p, 0, 60) // rax = 60 (exit)
112 p = e_exit(code, p)
113 let found_pos: i64 = p
114 p = e_movrr(code, p, 2, 0) // rdx = rax (cursor)
115 p = e_movimm(code, p, 6, 16) // rsi = 16 (payload offset)
116 p = e_addrr(code, p, 2, 6) // rdx += rsi (payload addr)
117 p = e_load(code, p, 7, 2) // rdi = [rdx] (payload)
118 p = e_movimm(code, p, 5, 208) // rbp = 208
119 p = e_store(code, p, 5, 7) // [rbp] = rdi (result = payload)
120 p = e_movimm(code, p, 7, 0) // rdi = 0 (clean exit code)
121 p = e_movimm(code, p, 0, 60) // rax = 60
122 p = e_exit(code, p)
123 let clen: i64 = p
124 code[je_pos+1] = ((found_pos - (je_pos+2)) & 0xFF) as u8 // patch je -> found (fwd)
125 code[jne_pos+1] = ((loop_pos - (jne_pos+2)) & 0xFF) as u8 // patch jne -> loop (back)
126 return clen
127}
128
129// run the scan with a given target CID; returns the emu rc; *out gets the result word (loaded payload or 0).
130func run_scan(code: *u8, clen: i64, mem: *u8, target: i64, out: *i64) -> i64 {
131 k_st64(mem, 200, target)
132 k_st64(mem, 208, 0)
133 let rc: i64 = emu_x86_run_k(code, clen, mem)
134 out[0] = k_ld64(mem, 208)
135 return rc
136}
137
138func main() -> i64 {
139 ui_puts("ladder C9: NishiFS-aware bootloader CORE -- find the kernel object BY CID, EXECUTED as real x86\n" as *u8)
140
141 // 3 objects (payload words); the kernel is rec1. CID = sha256(payload) 8-byte prefix.
142 let p0: i64 = 0x1111111111111111
143 let p1: i64 = 0x4B45524E454C0001 // "kernel" payload
144 let p2: i64 = 0x3333333333333333
145 let c0: i64 = cid_of(p0)
146 let c1: i64 = cid_of(p1) // the kernel CID
147 let c2: i64 = cid_of(p2)
148 let cbogus: i64 = cid_of(0x9999999999999999)
149
150 // object region: 3 records of 24 bytes [CID8][len8][payload8]
151 let mem: *u8 = sys_mmap(K_MAGIC_4096)
152 k_st64(mem, 0, c0); k_st64(mem, 8, 8); k_st64(mem, 16, p0)
153 k_st64(mem, 24, c1); k_st64(mem, 32, 8); k_st64(mem, 40, p1)
154 k_st64(mem, 48, c2); k_st64(mem, 56, 8); k_st64(mem, 64, p2)
155
156 let code: *u8 = sys_mmap(512)
157 let clen: i64 = build_scan(code)
158
159 let outp: *i64 = sys_mmap(8) as *i64
160 let rcK: i64 = run_scan(code, clen, mem, c1, outp); let resK: i64 = outp[0]
161 let rc0: i64 = run_scan(code, clen, mem, c0, outp); let res0: i64 = outp[0]
162 let rc2: i64 = run_scan(code, clen, mem, c2, outp); let res2: i64 = outp[0]
163 let rcB: i64 = run_scan(code, clen, mem, cbogus, outp); let resB: i64 = outp[0]
164
165 ui_puts(" built x86 scan: " as *u8); ui_num(clen); ui_puts(" bytes; ran on the proven kernel-subset emu (rc kernel=" as *u8); ui_num(rcK); ui_puts(")\n" as *u8)
166
167 var pass: i64=0
168 var ttl: i64=0
169 ttl=ttl+1; ui_puts(" T1 executed-x86 scan finds the kernel BY CID + loads its payload: " as *u8); if rcK==0 { if resK==p1 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL (rc="); ui_num(rcK); ui_puts(")\n" as *u8) }
170 ttl=ttl+1; ui_puts(" T2 finds the right object at ANY position (rec0->p0, rec2->p2): " as *u8); if res0==p0 { if res2==p2 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL\n" as *u8) }
171 ttl=ttl+1; ui_puts(" T3 liar-kill: bogus CID -> NO load (result==0, match is real-executed): " as *u8); if resB==0 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL (resB="); ui_num(resB); ui_puts(")\n" as *u8) }
172 ttl=ttl+1; ui_puts(" T4 the emu executed real x86 to a clean exit (rc==0 on all runs): " as *u8); if rcK==0 { if rc0==0 { if rc2==0 { if rcB==0 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL\n" as *u8) }
173 ttl=ttl+1; ui_puts(" T5 loaded the object's DATA, not echoed the key (payload != CID): " as *u8); if resK != c1 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) }
174 ttl=ttl+1; ui_puts(" T6 distinct content -> distinct CID (c0,c1,c2 all differ): " as *u8); if c0!=c1 { if c1!=c2 { if c0!=c2 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL\n" as *u8) }
175
176 ui_puts("NISHIFS-BOOTASM-GATE passed " as *u8); ui_num(pass); ui_puts("/" as *u8); ui_num(ttl)
177 if pass==ttl { ui_puts(" verdict=GREEN (the bootloader's find-kernel-BY-CID core runs as REAL EXECUTED x86; full 32-byte CID + 16-bit real-mode + partition parse in-asm = refinements; R10 hardware = next)\n" as *u8); sys_exit(0); return 0 }
178 ui_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1
179}