code wiki / _hdl_build / nx_nishi_install_os.nx

nx_nishi_install_os.nx source

↩ module page · 244 lines · 13034 B

1// nx_nishi_install_os.nx -- ladder C5 (the INSTALL-OUR-OS capstone): install the OS AS a content-addressed NishiFS. 2// 3// Fuses the whole installer/disk side into ONE flow: FORMAT the OS as a NishiFS disk (C1 partition table + 4// C2/C4 content-addressed FS: superblock + Merkle dir + objects) -> INSTALL it onto a target with the C3 5// never-brick installer (refuse-system-disk + sha256 read-back verify + golden recovery) -> MOUNT the 6// INSTALLED copy and read a file by CID, and prove the WHOLE-OS root CID survived the install bit-for-bit. 7// KAT 6/6: T1 install OK + sha256 byte-perfect; T2 never-brick (refuse /dev/sda); T3 the installed target 8// MOUNTS as NishiFS (partition->superblock->file-by-CID, bytes match); T4 the whole-OS root CID is PRESERVED 9// (installed root == source root = the entire filesystem verified through the install); T5 golden recovery 10// (corrupt install -> RECOVERED + still mounts); T6 integrity survives install (tamper installed object -> 11// MNT_INTEGRITY). composes nx_sha256 + nx_syscalls; reuses the proven C3 installer + C4 format/mount. 12// NEVER-BRICK (Rule 26): refuses the system disk; writes FILES only (knowledge/status/); no /dev. expect_exit: 0 license_tier: ORIGINAL 13import "nx_syscalls.nx" 14import "nx_sha256.nx" 15 16const DISK_SZ: i64 = 4096 17const PBYTE: i64 = 512 18const OBJSTART_REL: i64 = 512 19const PART_TYPE_NISHI: i64 = 0x9E 20const MNT_OK: i64 = 0 21const MNT_BADMAGIC: i64 = 1 22const MNT_ROOT_MISMATCH: i64 = 2 23const MNT_NOTFOUND: i64 = 3 24const MNT_INTEGRITY: i64 = 4 25const INST_OK: i64 = 0 26const INST_RECOVERED: i64 = 2 27const INST_UNSAFE: i64 = 7 28const INST_FATAL: i64 = 5 29 30func 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 } 31func 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 } 32func ui_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 33func cid_eq(a: *u8, b: *u8) -> i64 { var i: i64=0; while i<32 { if a[i]!=b[i] { return 0 } i=i+1 } return 1 } 34func wr_u32_le(d: *u8, off: i64, v: i64) -> i64 { d[off]=(v & 0xFF) as u8; d[off+1]=((v>>8)&0xFF) as u8; d[off+2]=((v>>16)&0xFF) as u8; d[off+3]=((v>>24)&0xFF) as u8; return 0 } 35func rd_u32_le(d: *u8, off: i64) -> i64 { return (d[off] as i64) | ((d[off+1] as i64)<<8) | ((d[off+2] as i64)<<16) | ((d[off+3] as i64)<<24) } 36func sha_slice(d: *u8, off: i64, len: i64, out: *u8) -> i64 { sha256_digest(((d as i64)+off) as *u8, len, out); return 0 } 37func w_file(path: *u8, buf: *u8, n: i64) -> i64 { let fd: i64=sys_openat_wr(path, 0x1a4); if fd<=0 { return 0-1 } sys_write(fd, buf, n); sys_close(fd); return 0 } 38func ui_read(path: *u8, out: *u8, cap: i64) -> i64 { let fd: i64=sys_openat_rd(path); if fd<0 { return 0-1 } var n: i64=0; var go: i64=1; while go==1 { let rr: i64=sys_read(fd, ((out as i64)+n) as *u8, cap-n); if rr<=0 { go=0 } else { n=n+rr } if n>=cap { go=0 } } sys_close(fd); return n } 39 40// ---- C3 never-brick installer primitives ---- 41func fl_safe(target: *u8) -> i64 { 42 if target[0]==(47 as u8) { if target[1]==(100 as u8) { if target[2]==(101 as u8) { if target[3]==(118 as u8) { if target[4]==(47 as u8) { if target[5]==(115 as u8) { if target[6]==(100 as u8) { if target[7]==(97 as u8) { return 0 } } } } } } } } 43 return 1 44} 45func fl_verify(img: *u8, n: i64, target: *u8) -> i64 { 46 let lenp: *i64 = sys_mmap(8) as *i64 47 let rb: *u8 = sys_read_file(target, lenp) 48 if (rb as i64)==0 { return 0-3 } 49 if lenp[0] != n { return 0-1 } 50 let h1: *u8 = sys_mmap(40) 51 let h2: *u8 = sys_mmap(40) 52 sha256_digest(img, n, h1) 53 sha256_digest(rb, lenp[0], h2) 54 if cid_eq(h1, h2)==1 { return 0 } 55 return 0-1 56} 57func nx_install(src: *u8, n: i64, target: *u8, golden: *u8, corrupt: i64) -> i64 { 58 if fl_safe(target)==0 { return INST_UNSAFE } 59 w_file(golden, src, n) 60 if corrupt==1 { 61 let bad: *u8 = sys_mmap(n+16) 62 var i: i64=0; while i<n { bad[i]=src[i]; i=i+1 } 63 bad[600] = (((bad[600] as i64)+1) & 0xFF) as u8 64 w_file(target, bad, n) 65 } else { w_file(target, src, n) } 66 var v: i64 = fl_verify(src, n, target) 67 if v==0 { return INST_OK } 68 let lenp: *i64 = sys_mmap(8) as *i64 69 let g: *u8 = sys_read_file(golden, lenp) 70 if (g as i64)==0 { return INST_FATAL } 71 w_file(target, g, lenp[0]) 72 v = fl_verify(src, n, target) 73 if v==0 { return INST_RECOVERED } 74 return INST_FATAL 75} 76 77// ---- C2/C4 content-addressed NishiFS: format + mount ---- 78func put_obj(d: *u8, cursor: i64, blob: *u8, n: i64, cidout: *u8) -> i64 { 79 sha256_digest(blob, n, cidout) 80 var i: i64=0; while i<32 { d[cursor+i]=cidout[i]; i=i+1 } 81 wr_u32_le(d, cursor+32, n) 82 i=0; while i<n { d[cursor+36+i]=blob[i]; i=i+1 } 83 return cursor + 36 + n 84} 85func find_obj(d: *u8, start: i64, endb: i64, cid: *u8, outlen: *i64) -> i64 { 86 var c: i64 = start 87 while c + 36 <= endb { 88 var same: i64 = 1 89 var i: i64 = 0 90 while i < 32 { if d[c+i]!=cid[i] { same=0; i=32 } else { i=i+1 } } 91 let ln: i64 = rd_u32_le(d, c+32) 92 if same==1 { outlen[0]=ln; return c+36 } 93 c = c + 36 + ln 94 } 95 return 0 - 1 96} 97func dir_find(d: *u8, base: i64, len: i64, name: *u8, cidout: *u8) -> i64 { 98 var c: i64 = base 99 let endd: i64 = base + len 100 while c < endd { 101 var k: i64 = 0 102 var same: i64 = 1 103 while d[c] != (0 as u8) { if name[k] != d[c] { same=0 } c=c+1; k=k+1 } 104 if name[k] != (0 as u8) { same=0 } 105 c = c + 1 106 if same==1 { var i: i64=0; while i<32 { cidout[i]=d[c+i]; i=i+1 } return 1 } 107 c = c + 32 108 } 109 return 0 110} 111func format_disk(d: *u8, nameA: *u8, A: *u8, nA: i64, nameB: *u8, B: *u8, nB: i64) -> i64 { 112 var z: i64=0; while z<DISK_SZ { d[z]=0 as u8; z=z+1 } 113 let p: i64 = 446 114 d[p+0]=0x80 as u8; d[p+2]=0x02 as u8; d[p+4]=PART_TYPE_NISHI as u8; d[p+5]=0xFE as u8; d[p+6]=0xFF as u8; d[p+7]=0xFF as u8 115 wr_u32_le(d, p+8, 1) 116 wr_u32_le(d, p+12, (DISK_SZ/512) - 1) 117 d[510]=0x55 as u8; d[511]=0xAA as u8 118 let cidA: *u8 = sys_mmap(40) 119 let cidB: *u8 = sys_mmap(40) 120 var cur: i64 = PBYTE + OBJSTART_REL 121 cur = put_obj(d, cur, A, nA, cidA) 122 cur = put_obj(d, cur, B, nB, cidB) 123 let dir_abs: i64 = cur 124 var w: i64 = dir_abs 125 var i: i64=0; while nameA[i]!=(0 as u8) { d[w]=nameA[i]; w=w+1; i=i+1 } d[w]=0 as u8; w=w+1 126 i=0; while i<32 { d[w]=cidA[i]; w=w+1; i=i+1 } 127 i=0; while nameB[i]!=(0 as u8) { d[w]=nameB[i]; w=w+1; i=i+1 } d[w]=0 as u8; w=w+1 128 i=0; while i<32 { d[w]=cidB[i]; w=w+1; i=i+1 } 129 let dir_len: i64 = w - dir_abs 130 let root: *u8 = sys_mmap(40) 131 sha_slice(d, dir_abs, dir_len, root) 132 let mg: *u8 = "NISHIFS1\x00" as *u8 133 i=0; while i<8 { d[PBYTE+i]=mg[i]; i=i+1 } 134 i=0; while i<32 { d[PBYTE+8+i]=root[i]; i=i+1 } 135 wr_u32_le(d, PBYTE+40, 2) 136 wr_u32_le(d, PBYTE+44, OBJSTART_REL) 137 wr_u32_le(d, PBYTE+48, dir_abs - PBYTE) 138 wr_u32_le(d, PBYTE+52, dir_len) 139 return 0 140} 141// extract the superblock root CID by parsing the partition table (0 ok, neg on failure) 142func get_root(d: *u8, out: *u8) -> i64 { 143 var lba: i64 = 0-1 144 var e: i64=0 145 while e<4 { let off: i64=446+e*16; if (d[off] as i64)==0x80 { if (d[off+4] as i64)==PART_TYPE_NISHI { lba=rd_u32_le(d,off+8); e=4 } else { e=e+1 } } else { e=e+1 } } 146 if lba<0 { return 0-1 } 147 let pb: i64=lba*512 148 let mg: *u8="NISHIFS1\x00" as *u8 149 var i: i64=0; while i<8 { if d[pb+i]!=mg[i] { return 0-2 } i=i+1 } 150 i=0; while i<32 { out[i]=d[pb+8+i]; i=i+1 } 151 return 0 152} 153func mount_read(d: *u8, name: *u8, out: *u8, cap: i64, lenout: *i64) -> i64 { 154 var lba: i64 = 0 - 1 155 var e: i64 = 0 156 while e < 4 { let off: i64 = 446 + e*16; if (d[off] as i64)==0x80 { if (d[off+4] as i64)==PART_TYPE_NISHI { lba = rd_u32_le(d, off+8); e=4 } else { e=e+1 } } else { e=e+1 } } 157 if lba < 0 { return MNT_NOTFOUND } 158 let pb: i64 = lba * 512 159 let mg: *u8 = "NISHIFS1\x00" as *u8 160 var i: i64=0; while i<8 { if d[pb+i]!=mg[i] { return MNT_BADMAGIC } i=i+1 } 161 let objstart_rel: i64 = rd_u32_le(d, pb+44) 162 let dir_off_rel: i64 = rd_u32_le(d, pb+48) 163 let dir_len: i64 = rd_u32_le(d, pb+52) 164 let dir_abs: i64 = pb + dir_off_rel 165 let root_stored: *u8 = sys_mmap(40) 166 i=0; while i<32 { root_stored[i]=d[pb+8+i]; i=i+1 } 167 let root_calc: *u8 = sys_mmap(40) 168 sha_slice(d, dir_abs, dir_len, root_calc) 169 if cid_eq(root_calc, root_stored)==0 { return MNT_ROOT_MISMATCH } 170 let fcid: *u8 = sys_mmap(40) 171 if dir_find(d, dir_abs, dir_len, name, fcid)==0 { return MNT_NOTFOUND } 172 let lenp: *i64 = sys_mmap(8) as *i64 173 let boff: i64 = find_obj(d, pb + objstart_rel, dir_abs, fcid, lenp) 174 if boff < 0 { return MNT_NOTFOUND } 175 let h: *u8 = sys_mmap(40) 176 sha_slice(d, boff, lenp[0], h) 177 if cid_eq(h, fcid)==0 { return MNT_INTEGRITY } 178 var m: i64 = lenp[0] 179 if m > cap { m = cap } 180 var j: i64=0; while j<m { out[j]=d[boff+j]; j=j+1 } 181 lenout[0]=lenp[0] 182 return MNT_OK 183} 184 185func main() -> i64 { 186 ui_puts("ladder C5: INSTALL the OS as a content-addressed NishiFS (C1 partition + C2/C4 FS + C3 never-brick installer)\n" as *u8) 187 let A: *u8 = "NishiOS readme: sovereign content-addressed filesystem\x00" as *u8 188 let B: *u8 = "kernel payload bytes v1 -- the OS image\x00" as *u8 189 let nA: i64 = ui_slen(A) 190 let nB: i64 = ui_slen(B) 191 192 // FORMAT the OS as a NishiFS disk 193 let src: *u8 = sys_mmap(DISK_SZ+16) 194 format_disk(src, "readme\x00" as *u8, A, nA, "kernel\x00" as *u8, B, nB) 195 let rootSrc: *u8 = sys_mmap(40) 196 get_root(src, rootSrc) 197 198 let target: *u8 = "knowledge/status/nishi_os_fs_target.img\x00" as *u8 199 let golden: *u8 = "knowledge/status/nishi_os_fs_golden.img\x00" as *u8 200 201 let r1: i64 = nx_install(src, DISK_SZ, target, golden, 0) 202 let v1: i64 = fl_verify(src, DISK_SZ, target) 203 let tgt: *u8 = sys_mmap(DISK_SZ+16) 204 let trn: i64 = ui_read(target, tgt, DISK_SZ) 205 206 let outK: *u8 = sys_mmap(512) 207 let lenK: *i64 = sys_mmap(8) as *i64 208 let r3: i64 = mount_read(tgt, "kernel\x00" as *u8, outK, 512, lenK) 209 var mok: i64=0 210 if r3==MNT_OK { if lenK[0]==nB { mok=1; var i: i64=0; while i<nB { if outK[i]!=B[i] { mok=0; i=nB } else { i=i+1 } } } } 211 212 let rootTgt: *u8 = sys_mmap(40) 213 get_root(tgt, rootTgt) 214 215 let r2: i64 = nx_install(src, DISK_SZ, "/dev/sda\x00" as *u8, golden, 0) 216 217 let r5: i64 = nx_install(src, DISK_SZ, target, golden, 1) 218 let tgt2: *u8 = sys_mmap(DISK_SZ+16) 219 let t2n: i64 = ui_read(target, tgt2, DISK_SZ) 220 let outK2: *u8 = sys_mmap(512) 221 let lenK2: *i64 = sys_mmap(8) as *i64 222 let r5m: i64 = mount_read(tgt2, "kernel\x00" as *u8, outK2, 512, lenK2) 223 224 let bad: *u8 = sys_mmap(DISK_SZ+16) 225 var c: i64=0; while c<DISK_SZ { bad[c]=tgt[c]; c=c+1 } 226 let aData: i64 = PBYTE + OBJSTART_REL + 36 + 5 227 bad[aData] = (((bad[aData] as i64)+1) & 0xFF) as u8 228 let outx: *u8 = sys_mmap(512) 229 let lenx: *i64 = sys_mmap(8) as *i64 230 let r6: i64 = mount_read(bad, "readme\x00" as *u8, outx, 512, lenx) 231 232 var pass: i64=0 233 var ttl: i64=0 234 ttl=ttl+1; ui_puts(" T1 install OS-FS to target -> OK + sha256 byte-perfect: " as *u8); if r1==INST_OK { if v1==0 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL\n" as *u8) } 235 ttl=ttl+1; ui_puts(" T2 never-brick: refuse install to /dev/sda: " as *u8); if r2==INST_UNSAFE { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) } 236 ttl=ttl+1; ui_puts(" T3 installed target MOUNTS as NishiFS (read 'kernel' by CID, bytes match): " as *u8); if mok==1 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL (r3="); ui_num(r3); ui_puts(")\n" as *u8) } 237 ttl=ttl+1; ui_puts(" T4 whole-OS root CID PRESERVED through install (installed root == source root): " as *u8); if cid_eq(rootTgt, rootSrc)==1 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) } 238 ttl=ttl+1; ui_puts(" T5 golden recovery: corrupt install -> RECOVERED + still mounts: " as *u8); if r5==INST_RECOVERED { if r5m==MNT_OK { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) } } else { ui_puts("FAIL (r5="); ui_num(r5); ui_puts(")\n" as *u8) } 239 ttl=ttl+1; ui_puts(" T6 integrity survives install (tamper installed object -> MNT_INTEGRITY): " as *u8); if r6==MNT_INTEGRITY { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL (r6="); ui_num(r6); ui_puts(")\n" as *u8) } 240 241 ui_puts("NISHI-INSTALL-OS-GATE passed " as *u8); ui_num(pass); ui_puts("/" as *u8); ui_num(ttl) 242 if pass==ttl { ui_puts(" verdict=GREEN (the OS installs AS a content-addressed NishiFS: never-brick install + mountable + whole-OS root-CID preserved + integrity survives; CoW snapshot + encryption + R10 hardware = next)\n" as *u8); sys_exit(0); return 0 } 243 ui_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1 244}