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}