code wiki / _hdl_build / nx_efi_fat32_image.nx

nx_efi_fat32_image.nx source

↩ module page · 510 lines · 29442 B

1// nx_efi_fat32_image.nx -- NOS-USB-R0: sovereign bootable USB disk-image emitter. 2// 3// "Nishi ecosystem all the way up": this organ AUTHORS, byte-by-byte, a complete UEFI-bootable 4// disk image -- MBR partition table + a FAT32 EFI System Partition containing 5// /EFI/BOOT/BOOTX64.EFI (our nx_boot_uefi.efi) -- with NO mkfs / xorriso / dd-as-formatter / GRUB. 6// The operator writes the emitted image to a physical USB (the raw byte-copy to the device is the 7// one hardware boundary), then UEFI firmware finds \EFI\BOOT\BOOTX64.EFI and boots NISHI. 8// This is the first concrete piece of the nx_spore design (knowledge: iso/README.md). 9// 10// FAT32 requires >=65525 clusters, so the volume is ~34 MB (1 sector/cluster). Layout: 11// LBA 0 : MBR (1 partition, type 0x0C FAT32-LBA, bootable, start LBA 2048) 12// LBA 2048 : FAT32 volume -> BPB(+FSInfo+backup) | 2 FATs | data (root,/EFI,/EFI/BOOT,file) 13// Build (sovereign): ./_offc/nx_sov_build_run.elf nx_efi_fat32_image (reads _offc/nx_boot_uefi.efi) 14// Self-gate: re-read image -> MBR sig + partition type + BPB "FAT32" + root "EFI" dir + the .efi's 15// "MZ" at the file's cluster; tamper (flip partition type) -> reject. Log -> knowledge/status/nishi_os.log 16// Sovereign: syscalls only, no gcc/.sh. license_tier: ORIGINAL 17import "nx_syscalls.nx" 18const PART_MAGIC_65536: i64 = 65536 19 20const SEC: i64 = 512 21const PART_LBA: i64 = 2048 22const RESV: i64 = 32 23const NFAT: i64 = 2 24const CLUS_CNT: i64 = 65536 // >= 65525 so it is a valid FAT32 25const FATSZ: i64 = 513 // sectors per FAT (513*512/4 = 65664 entries >= CLUS_CNT+2) 26const VOL_SEC: i64 = 66594 // RESV + NFAT*FATSZ + CLUS_CNT (32 + 1026 + 65536) 27// ===== GPT (FS-1, 2026-08-05): MBR is retired =================================================== 28// Operator: "make sure we aren't using some out of date filer format". The FAT32 *filesystem* is 29// NOT a free choice -- UEFI firmware carries a FAT driver and the spec requires the EFI System 30// Partition to be FAT, so every UEFI OS on earth ships a FAT32 ESP. The PARTITION TABLE was the 31// genuinely dated part and it WAS ours: MBR caps at 2 TiB, carries no integrity field, and is a 32// compatibility shim under UEFI. This image is now GPT: a PROTECTIVE MBR (type 0xEE covering the 33// whole disk so no legacy tool thinks the disk is unpartitioned), a primary GPT header at LBA 1, 34// a 128-entry array at LBA 2..33, and a BACKUP header + array at the end of the disk. Every one of 35// those structures carries a CRC32 that this emitter computes and its own gate re-verifies. 36const GPT_ENTRIES: i64 = 128 // spec minimum reserved size is 16 KiB = 128 x 128B 37const GPT_ENTSZ: i64 = 128 38const GPT_ARR_SEC: i64 = 32 // 128*128/512 39const GPT_HDR_SZ: i64 = 92 40// The disk grew by 33 sectors versus the MBR layout: the backup array (32) + the backup header (1) 41// must live BEYOND the last usable LBA. Sizing this by hand is exactly how a partition ends up 42// overlapping its own backup GPT, so the gate below asserts the fit rather than trusting the sum. 43// ===== FS-2b: a SECOND, USER-WRITABLE PARTITION ================================================= 44// Moving to GPT made Windows treat our ESP as a protected EFI System Partition, so the assistant 45// file a user actually swaps could no longer be dropped on it from a file manager. The fix is not to 46// weaken the ESP -- it is to give data a home of its own: a second FAT32 partition carrying the 47// Microsoft BASIC DATA type GUID, which every OS mounts as an ordinary drive. The ESP keeps only the 48// boot chain. The loader already searches EVERY volume for the optional file (LocateHandleBuffer), 49// so this partition is found by capability, not by a hardcoded assumption about where it sits. 50const VOL2_LBA: i64 = 68642 // PART_LBA + VOL_SEC -- immediately after the ESP 51const VOL2_BASE: i64 = 35144704 // VOL2_LBA * 512 52const DISK_SEC: i64 = 135269 // PART_LBA + VOL_SEC*2 + GPT_ARR_SEC + 1 53const IMG_BYTES: i64 = 69257728 // DISK_SEC * 512 54const LAST_LBA: i64 = 135268 // DISK_SEC - 1 55const GPT_BAK_ARR_LBA: i64 = 135236 // LAST_LBA - GPT_ARR_SEC 56const FIRST_USABLE: i64 = 34 // LBA 1 header + LBA 2..33 array 57const LAST_USABLE: i64 = 135235 // LAST_LBA - GPT_ARR_SEC - 1 == VOL2_LBA+VOL_SEC-1 (exact fit) 58 59const VOL_BASE: i64 = 1048576 // PART_LBA*512 60const FSINFO_OFF: i64 = 1049088 // VOL_BASE + 512 61const BKBOOT_OFF: i64 = 1051648 // VOL_BASE + 6*512 62const FAT1_OFF: i64 = 1064960 // VOL_BASE + RESV*512 63const FAT2_OFF: i64 = 1327616 // VOL_BASE + (RESV+FATSZ)*512 64const DATA_BASE: i64 = 1590272 // VOL_BASE + (RESV+NFAT*FATSZ)*512 (data cluster 2 starts here) 65 66// clusters: 2=root dir, 3=/EFI, 4=/EFI/BOOT, 5..=BOOTX64.EFI file 67const CL_ROOT: i64 = 2 68const CL_EFI: i64 = 3 69const CL_BOOT: i64 = 4 70const CL_FILE: i64 = 5 71 72func iw8(img: *u8, off: i64, v: i64) -> i64 { img[off] = (v & 0xff) as u8; return 0 } 73func iw16(img: *u8, off: i64, v: i64) -> i64 { img[off] = (v & 0xff) as u8; img[off+1] = ((v >> 8) & 0xff) as u8; return 0 } 74func iw32(img: *u8, off: i64, v: i64) -> i64 { 75 img[off]=(v&0xff) as u8; img[off+1]=((v>>8)&0xff) as u8; img[off+2]=((v>>16)&0xff) as u8; img[off+3]=((v>>24)&0xff) as u8 76 return 0 77} 78func ir32(img: *u8, off: i64) -> i64 { 79 return (img[off] as i64) | ((img[off+1] as i64) << 8) | ((img[off+2] as i64) << 16) | ((img[off+3] as i64) << 24) 80} 81func istr(img: *u8, off: i64, s: *u8, n: i64) -> i64 { // copy exactly n bytes of s (space-padded literal) 82 var i: i64 = 0 83 while i < n { img[off + i] = s[i]; i = i + 1 } 84 return 0 85} 86func cluster_off(clus: i64) -> i64 { return DATA_BASE + (clus - 2) * SEC } 87 88// CRC32 (IEEE, reflected, poly 0xEDB88320) -- the integrity field GPT has and MBR never did. 89// Same algorithm our gzip organ uses; restated here so the image writer carries no dependency on 90// the compression lane, and so a change there can never silently alter a partition table. 91func gpt_crc32(b: *u8, off: i64, n: i64) -> i64 { 92 var crc: i64 = 0xFFFFFFFF 93 var i: i64 = 0 94 while i < n { 95 crc = crc ^ ((b[off + i] as i64) & 0xff) 96 var bit: i64 = 0 97 while bit < 8 { 98 let lsb: i64 = crc & 1 99 let mask: i64 = 0 - lsb 100 crc = ((crc >> 1) & 0x7FFFFFFFFFFFFFFF) ^ (mask & 0xEDB88320) 101 crc = crc & 0xFFFFFFFF 102 bit = bit + 1 103 } 104 i = i + 1 105 } 106 return (crc ^ 0xFFFFFFFF) & 0xFFFFFFFF 107} 108func iw64(img: *u8, off: i64, v: i64) -> i64 { iw32(img, off, v & 0xFFFFFFFF); iw32(img, off + 4, (v >> 32) & 0xFFFFFFFF); return 0 } 109// EFI System Partition type GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B, in the on-disk mixed-endian 110// byte order the spec mandates (first three fields little-endian, last two big-endian). 111func esp_guid_b(i: i64) -> i64 { 112 if i==0 { return 0x28 } if i==1 { return 0x73 } if i==2 { return 0x2A } if i==3 { return 0xC1 } 113 if i==4 { return 0x1F } if i==5 { return 0xF8 } if i==6 { return 0xD2 } if i==7 { return 0x11 } 114 if i==8 { return 0xBA } if i==9 { return 0x4B } if i==10 { return 0x00 } if i==11 { return 0xA0 } 115 if i==12 { return 0xC9 } if i==13 { return 0x3E } if i==14 { return 0xC9 } return 0x3B 116} 117// Disk and partition unique GUIDs are FIXED, not random. A random GUID would destroy the one 118// property this lane has measured and defended all week: the image rebuilds BYTE-IDENTICALLY. 119// Uniqueness matters when many disks meet one machine; reproducibility matters every single build, 120// so it wins here and the choice is stated rather than defaulted into. 121// Microsoft basic data partition EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, on-disk mixed-endian order. 122// This exact GUID is what makes Windows, Linux and macOS all mount the partition as a normal drive. 123func data_guid_b(i: i64) -> i64 { 124 if i==0 { return 0xA2 } if i==1 { return 0xA0 } if i==2 { return 0xD0 } if i==3 { return 0xEB } 125 if i==4 { return 0xE5 } if i==5 { return 0xB9 } if i==6 { return 0x33 } if i==7 { return 0x44 } 126 if i==8 { return 0x87 } if i==9 { return 0xC0 } if i==10 { return 0x68 } if i==11 { return 0xB6 } 127 if i==12 { return 0xB7 } if i==13 { return 0x26 } if i==14 { return 0x99 } return 0xC7 128} 129func part2_guid_b(i: i64) -> i64 { return (0x61 + i * 13) & 0xff } 130func disk_guid_b(i: i64) -> i64 { return (0x4E + i * 7) & 0xff } 131func part_guid_b(i: i64) -> i64 { return (0x53 + i * 11) & 0xff } 132 133// Write one GPT header at `hdr_off` (byte offset of its LBA). my_lba/alt_lba/arr_lba are the 134// values that DIFFER between the primary and the backup -- everything else is identical, which is 135// why both are emitted by ONE function: a hand-copied backup header is a bug with a delay fuse. 136func wr_gpt_hdr(img: *u8, hdr_off: i64, my_lba: i64, alt_lba: i64, arr_lba: i64, arr_crc: i64) -> i64 { 137 var z: i64 = 0 138 while z < SEC { iw8(img, hdr_off + z, 0); z = z + 1 } 139 let sig: *u8 = "EFI PART" as *u8 140 istr(img, hdr_off + 0, sig, 8) 141 iw32(img, hdr_off + 8, 0x00010000) // revision 1.0 142 iw32(img, hdr_off + 12, GPT_HDR_SZ) 143 iw32(img, hdr_off + 16, 0) // header CRC32 field is ZERO while it is computed 144 iw32(img, hdr_off + 20, 0) // reserved 145 iw64(img, hdr_off + 24, my_lba) 146 iw64(img, hdr_off + 32, alt_lba) 147 iw64(img, hdr_off + 40, FIRST_USABLE) 148 iw64(img, hdr_off + 48, LAST_USABLE) 149 var g: i64 = 0 150 while g < 16 { iw8(img, hdr_off + 56 + g, disk_guid_b(g)); g = g + 1 } 151 iw64(img, hdr_off + 72, arr_lba) 152 iw32(img, hdr_off + 80, GPT_ENTRIES) 153 iw32(img, hdr_off + 84, GPT_ENTSZ) 154 iw32(img, hdr_off + 88, arr_crc) 155 let hc: i64 = gpt_crc32(img, hdr_off, GPT_HDR_SZ) // over exactly HeaderSize bytes, CRC field 0 156 iw32(img, hdr_off + 16, hc) 157 return hc 158} 159 160// write FAT entry `clus` = `val` into BOTH FATs (low 28 bits) 161// Both volumes have identical geometry, so every offset is derivable from the volume base. These 162// replace three constants that silently meant "volume 1" -- a constant that encodes WHICH volume is 163// exactly what stops an emitter from ever writing a second one. 164func v_fat1(vb: i64) -> i64 { return vb + RESV * SEC } 165func v_fat2(vb: i64) -> i64 { return vb + (RESV + FATSZ) * SEC } 166func v_data(vb: i64) -> i64 { return vb + (RESV + NFAT * FATSZ) * SEC } 167func v_clus(vb: i64, clus: i64) -> i64 { return v_data(vb) + (clus - 2) * SEC } 168func fat_set_at(img: *u8, vb: i64, clus: i64, val: i64) -> i64 { 169 iw32(img, v_fat1(vb) + clus * 4, val & 0x0FFFFFFF) 170 iw32(img, v_fat2(vb) + clus * 4, val & 0x0FFFFFFF) 171 return 0 172} 173func fat_set(img: *u8, clus: i64, val: i64) -> i64 { return fat_set_at(img, VOL_BASE, clus, val) } 174 175// 32-byte directory entry: name = exactly 11 bytes (space-padded 8.3) 176func wdir(img: *u8, off: i64, name: *u8, attr: i64, clus: i64, size: i64) -> i64 { 177 istr(img, off, name, 11) 178 iw8(img, off + 11, attr) 179 iw16(img, off + 20, (clus >> 16) & 0xFFFF) // first cluster hi 180 iw16(img, off + 26, clus & 0xFFFF) // first cluster lo 181 iw32(img, off + 28, size) // file size 182 return 0 183} 184 185func wr_bpb(img: *u8, base: i64) -> i64 { 186 iw8(img, base + 0, 0xEB); iw8(img, base + 1, 0x58); iw8(img, base + 2, 0x90) // jmp 187 istr(img, base + 3, "NISHI " as *u8, 8) // OEM 188 iw16(img, base + 11, SEC) // bytes/sector 189 iw8(img, base + 13, 1) // sectors/cluster 190 iw16(img, base + 14, RESV) // reserved sectors 191 iw8(img, base + 16, NFAT) // num FATs 192 iw16(img, base + 17, 0) // root entries (0 for FAT32) 193 iw16(img, base + 19, 0) // total sectors 16 (0 -> use 32) 194 iw8(img, base + 21, 0xF8) // media 195 iw16(img, base + 22, 0) // FAT size 16 (0 -> use 32) 196 iw16(img, base + 24, 32) // sectors/track 197 iw16(img, base + 26, 64) // heads 198 iw32(img, base + 28, PART_LBA) // hidden sectors 199 iw32(img, base + 32, VOL_SEC) // total sectors 32 200 iw32(img, base + 36, FATSZ) // FAT size 32 201 iw16(img, base + 40, 0) // ext flags 202 iw16(img, base + 42, 0) // fs version 203 iw32(img, base + 44, CL_ROOT) // root cluster 204 iw16(img, base + 48, 1) // FSInfo sector 205 iw16(img, base + 50, 6) // backup boot sector 206 iw8(img, base + 64, 0x80) // drive number 207 iw8(img, base + 66, 0x29) // ext boot signature 208 iw32(img, base + 67, 0x12345678) // volume id 209 istr(img, base + 71, "NISHI BOOT " as *u8, 11) // volume label 210 istr(img, base + 82, "FAT32 " as *u8, 8) // fs type 211 iw8(img, base + 510, 0x55); iw8(img, base + 511, 0xAA) 212 return 0 213} 214 215func p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 216func 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 } 217func fn(fd: i64, v: i64) -> i64 { 218 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 219 let t: *u8 = sys_mmap(28); var k: i64 = 0 220 if m == 0 { t[0] = 48; k = 1 } 221 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 222 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 223 sys_write(fd, bb, k); return 0 224} 225 226func main(argc: i64, argv: *i64) -> i64 { 227 var efipath: *u8 = "_offc/nx_boot_uefi.efi" as *u8 // payload .efi (argv[1] overrides) 228 if argc >= 2 { efipath = argv[1] as *u8 } 229 var outpath: *u8 = "_offc/nishi-boot.img" as *u8 // output image (argv[2] overrides) 230 if argc >= 3 { outpath = argv[2] as *u8 } 231 // N1-full: argv[3] optionally places a SECOND file, /KERNEL.NXE, in the volume ROOT so the 232 // boot shim can READ ITS OWN KERNEL off the filesystem instead of being handed an embedded 233 // copy at build time. Root-level (not a subdirectory) keeps the shim's Open() path trivial. 234 var nxepath: *u8 = 0 as *u8 235 if argc >= 4 { nxepath = argv[3] as *u8 } 236 var nxelen: i64 = 0 237 var nxe: *u8 = 0 as *u8 238 if nxepath != (0 as *u8) { 239 let nl: *i64 = sys_mmap(16) as *i64 240 nxe = sys_read_file(nxepath, nl) 241 nxelen = nl[0] 242 if nxelen <= 0 { p("NOS-USB RED: cannot read NXE payload 243" as *u8); sys_exit(2); return 2 } 244 } 245 // read the EFI boot app 246 let lenp: *i64 = sys_mmap(16) as *i64 247 let efi: *u8 = sys_read_file(efipath, lenp) 248 let efilen: i64 = lenp[0] 249 if efilen <= 0 { p("NOS-USB REFUSED: cannot read payload .efi: " as *u8); p(efipath); p("\n" as *u8); sys_exit(2); return 2 } 250 // The arg order is <payload.efi> <out.img>. Swapping them read an IMAGE as the payload and then 251 // wrote the new image straight over the caller's .efi -- destroying an input before the structural 252 // gate could refuse. A payload that is not a PE image is refused HERE, before anything is written. 253 if efi[0] != (0x4D as u8) { p("NOS-USB REFUSED: payload is not PE (no MZ) -- arg order is <payload.efi> <out.img>: " as *u8); p(efipath); p(" 254" as *u8); sys_exit(2); return 2 } 255 if efi[1] != (0x5A as u8) { p("NOS-USB REFUSED: payload is not PE (no MZ) -- arg order is <payload.efi> <out.img>: " as *u8); p(efipath); p(" 256" as *u8); sys_exit(2); return 2 } 257 if efilen >= IMG_BYTES { p("NOS-USB REFUSED: payload does not fit the volume it must live in 258" as *u8); sys_exit(2); return 2 } 259 260 let img: *u8 = sys_mmap(IMG_BYTES) // zero-filled 261 262 // ----- PROTECTIVE MBR: ONE 0xEE partition spanning the disk (never a real partition) -------- 263 // Its whole job is to make a legacy tool see a full, unknown-type disk instead of an empty one. 264 iw8(img, 446 + 0, 0x00) // NOT bootable: nothing boots via this entry 265 iw8(img, 446 + 1, 0x00); iw8(img, 446 + 2, 0x02); iw8(img, 446 + 3, 0x00) // CHS start 0/0/2 266 iw8(img, 446 + 4, 0xEE) // type 0xEE = GPT protective 267 iw8(img, 446 + 5, 0xFF); iw8(img, 446 + 6, 0xFF); iw8(img, 446 + 7, 0xFF) // CHS end (saturated) 268 iw32(img, 446 + 8, 1) // starts at LBA 1 (the GPT header) 269 var pmsz: i64 = DISK_SEC - 1 270 if pmsz > 0xFFFFFFFF { pmsz = 0xFFFFFFFF } // saturate, per spec, on huge disks 271 iw32(img, 446 + 12, pmsz) 272 iw8(img, 510, 0x55); iw8(img, 511, 0xAA) 273 274 // ----- GPT partition entry 0: our ESP, filling the usable area exactly -------------------- 275 let arr_off: i64 = 2 * SEC 276 var ge: i64 = 0 277 while ge < 16 { iw8(img, arr_off + ge, esp_guid_b(ge)); ge = ge + 1 } // PartitionTypeGUID 278 ge = 0 279 while ge < 16 { iw8(img, arr_off + 16 + ge, part_guid_b(ge)); ge = ge + 1 } // UniquePartitionGUID 280 iw64(img, arr_off + 32, PART_LBA) // StartingLBA 281 iw64(img, arr_off + 40, PART_LBA + VOL_SEC - 1) // EndingLBA (inclusive) 282 iw64(img, arr_off + 48, 0) // Attributes 283 let pname: *u8 = "EFI System Partition" as *u8 // UTF-16LE, 36 chars max 284 var pn: i64 = 0 285 while pn < 20 { iw16(img, arr_off + 56 + pn * 2, pname[pn] as i64); pn = pn + 1 } 286 // ---- GPT entry 1: the DATA partition, filling the rest of the usable area exactly --------- 287 let e1: i64 = arr_off + GPT_ENTSZ 288 ge = 0 289 while ge < 16 { iw8(img, e1 + ge, data_guid_b(ge)); ge = ge + 1 } 290 ge = 0 291 while ge < 16 { iw8(img, e1 + 16 + ge, part2_guid_b(ge)); ge = ge + 1 } 292 iw64(img, e1 + 32, VOL2_LBA) 293 iw64(img, e1 + 40, VOL2_LBA + VOL_SEC - 1) 294 iw64(img, e1 + 48, 0) 295 let dname: *u8 = "NISHI DATA" as *u8 296 var dn: i64 = 0 297 while dn < 10 { iw16(img, e1 + 56 + dn * 2, dname[dn] as i64); dn = dn + 1 } 298 // Both copies of the array are the SAME bytes, so they get the SAME CRC -- copy, never re-emit. 299 let arr_crc: i64 = gpt_crc32(img, arr_off, GPT_ENTRIES * GPT_ENTSZ) 300 var ac: i64 = 0 301 while ac < (GPT_ENTRIES * GPT_ENTSZ) { img[GPT_BAK_ARR_LBA * SEC + ac] = img[arr_off + ac]; ac = ac + 1 } 302 wr_gpt_hdr(img, 1 * SEC, 1, LAST_LBA, 2, arr_crc) // primary 303 wr_gpt_hdr(img, LAST_LBA * SEC, LAST_LBA, 1, GPT_BAK_ARR_LBA, arr_crc) // backup (swapped) 304 305 // ----- FAT32 BPB (+ backup) ----- 306 wr_bpb(img, VOL_BASE) 307 wr_bpb(img, BKBOOT_OFF) 308 309 // ----- FSInfo ----- 310 iw32(img, FSINFO_OFF + 0, 0x41615252) 311 iw32(img, FSINFO_OFF + 484, 0x61417272) 312 iw32(img, FSINFO_OFF + 488, 0 - 1) // free count unknown (0xFFFFFFFF) 313 iw32(img, FSINFO_OFF + 492, 7) // next free hint 314 iw8(img, FSINFO_OFF + 510, 0x55); iw8(img, FSINFO_OFF + 511, 0xAA) 315 316 // ----- the DATA volume: same emitter, different base. Empty on purpose: this is where the 317 // ----- user drops NISHI.AI (or anything else). A volume label so it is recognisable in a file 318 // ----- manager rather than showing up as an anonymous drive. 319 wr_bpb(img, VOL2_BASE) 320 wr_bpb(img, VOL2_BASE + 6 * SEC) 321 iw32(img, VOL2_BASE + SEC + 0, 0x41615252) 322 iw32(img, VOL2_BASE + SEC + 484, 0x61417272) 323 iw32(img, VOL2_BASE + SEC + 488, 0 - 1) 324 iw32(img, VOL2_BASE + SEC + 492, 3) 325 iw8(img, VOL2_BASE + SEC + 510, 0x55); iw8(img, VOL2_BASE + SEC + 511, 0xAA) 326 fat_set_at(img, VOL2_BASE, 0, 0x0FFFFFF8) 327 fat_set_at(img, VOL2_BASE, 1, 0x0FFFFFFF) 328 fat_set_at(img, VOL2_BASE, 2, 0x0FFFFFFF) // root dir: one cluster, end of chain 329 wdir(img, v_clus(VOL2_BASE, 2), "NISHIDATA " as *u8, 0x08, 0, 0) // volume label 330 331 // ----- FAT entries ----- 332 fat_set(img, 0, 0x0FFFFFF8) // media 333 fat_set(img, 1, 0x0FFFFFFF) 334 fat_set(img, CL_ROOT, 0x0FFFFFFF) // root: single cluster 335 fat_set(img, CL_EFI, 0x0FFFFFFF) // /EFI: single cluster 336 fat_set(img, CL_BOOT, 0x0FFFFFFF) // /EFI/BOOT: single cluster 337 // file: efilen bytes -> ceil(efilen/512) clusters, chained from CL_FILE 338 var nfc: i64 = (efilen + SEC - 1) / SEC 339 if nfc < 1 { nfc = 1 } 340 var c: i64 = 0 341 while c < nfc { 342 if c == nfc - 1 { fat_set(img, CL_FILE + c, 0x0FFFFFFF) } 343 else { fat_set(img, CL_FILE + c, CL_FILE + c + 1) } 344 c = c + 1 345 } 346 347 // KERNEL.NXE occupies the clusters immediately after BOOTX64.EFI 348 let cl_kern: i64 = CL_FILE + nfc 349 var nkc: i64 = 0 350 if nxelen > 0 { 351 nkc = (nxelen + SEC - 1) / SEC 352 if nkc < 1 { nkc = 1 } 353 var kc: i64 = 0 354 while kc < nkc { 355 if kc == nkc - 1 { fat_set(img, cl_kern + kc, 0x0FFFFFFF) } 356 else { fat_set(img, cl_kern + kc, cl_kern + kc + 1) } 357 kc = kc + 1 358 } 359 } 360 361 // ----- directories ----- 362 // root (cluster 2): the "EFI" subdirectory 363 wdir(img, cluster_off(CL_ROOT), "EFI " as *u8, 0x10, CL_EFI, 0) 364 // /EFI (cluster 3): . .. BOOT 365 wdir(img, cluster_off(CL_EFI) + 0, ". " as *u8, 0x10, CL_EFI, 0) 366 wdir(img, cluster_off(CL_EFI) + 32, ".. " as *u8, 0x10, 0, 0) // .. of root child -> 0 367 wdir(img, cluster_off(CL_EFI) + 64, "BOOT " as *u8, 0x10, CL_BOOT, 0) 368 // /EFI/BOOT (cluster 4): . .. BOOTX64.EFI 369 wdir(img, cluster_off(CL_BOOT) + 0, ". " as *u8, 0x10, CL_BOOT, 0) 370 wdir(img, cluster_off(CL_BOOT) + 32, ".. " as *u8, 0x10, CL_EFI, 0) 371 wdir(img, cluster_off(CL_BOOT) + 64, "BOOTX64 EFI" as *u8, 0x20, CL_FILE, efilen) 372 373 // root entry #2: /KERNEL.NXE (8.3 name is "KERNEL NXE") 374 if nxelen > 0 { wdir(img, cluster_off(CL_ROOT) + 32, "KERNEL NXE" as *u8, 0x20, cl_kern, nxelen) } 375 376 // ----- file data (contiguous clusters from CL_FILE) ----- 377 let foff: i64 = cluster_off(CL_FILE) 378 var i: i64 = 0 379 while i < efilen { img[foff + i] = efi[i]; i = i + 1 } 380 381 if nxelen > 0 { 382 let koff: i64 = cluster_off(cl_kern) 383 var ki: i64 = 0 384 while ki < nxelen { img[koff + ki] = nxe[ki]; ki = ki + 1 } 385 } 386 387 // ----- write the image ----- 388 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 389 if ofd < 0 { p("NOS-USB RED: cannot write image\n" as *u8); sys_exit(1); return 1 } 390 var done: i64 = 0 391 while done < IMG_BYTES { 392 let w: i64 = sys_write(ofd, (img + done) as *u8, IMG_BYTES - done) 393 if w <= 0 { done = IMG_BYTES } else { done = done + w } 394 } 395 sys_close(ofd) 396 397 // ----- self-gate: re-read + verify the structures ----- 398 let l2: *i64 = sys_mmap(16) as *i64 399 let rb: *u8 = sys_read_file(outpath, l2) 400 let rlen: i64 = l2[0] 401 var ok: i64 = 1 402 if rlen != IMG_BYTES { ok = 0 } 403 if (rb[510] as i64) != 0x55 { ok = 0 } 404 if (rb[511] as i64) != 0xAA { ok = 0 } // protective-MBR signature 405 if (rb[446 + 4] as i64) != 0xEE { ok = 0 } // type 0xEE = GPT protective, NOT 0x0C 406 if (rb[446 + 0] as i64) != 0x00 { ok = 0 } // and it must NOT be marked bootable 407 // ---- GPT teeth: both headers, both CRCs, and the geometry that stops a partition from 408 // ---- overlapping its own backup (the failure a hand-summed layout produces). 409 var gok: i64 = 1 410 let gsig: *u8 = "EFI PART" as *u8 411 var gi: i64 = 0 412 while gi < 8 { if (rb[SEC + gi] as i64) != (gsig[gi] as i64) { gok = 0 } gi = gi + 1 } 413 while gi < 16 { if (rb[LAST_LBA * SEC + gi - 8] as i64) != (gsig[gi - 8] as i64) { gok = 0 } gi = gi + 1 } 414 if ir32(rb, SEC + 12) != GPT_HDR_SZ { gok = 0 } 415 if ir32(rb, SEC + 80) != GPT_ENTRIES { gok = 0 } 416 if ir32(rb, SEC + 84) != GPT_ENTSZ { gok = 0 } 417 // header CRC: recompute with the CRC field zeroed, exactly as a real firmware parser does 418 let hsave: i64 = ir32(rb, SEC + 16) 419 iw32(rb, SEC + 16, 0) 420 if gpt_crc32(rb, SEC, GPT_HDR_SZ) != hsave { gok = 0 } 421 iw32(rb, SEC + 16, hsave) 422 let bsave: i64 = ir32(rb, LAST_LBA * SEC + 16) 423 iw32(rb, LAST_LBA * SEC + 16, 0) 424 if gpt_crc32(rb, LAST_LBA * SEC, GPT_HDR_SZ) != bsave { gok = 0 } 425 iw32(rb, LAST_LBA * SEC + 16, bsave) 426 // entry-array CRC, both copies, and they must be byte-identical to each other 427 let acrc: i64 = gpt_crc32(rb, 2 * SEC, GPT_ENTRIES * GPT_ENTSZ) 428 if ir32(rb, SEC + 88) != acrc { gok = 0 } 429 if ir32(rb, LAST_LBA * SEC + 88) != acrc { gok = 0 } 430 if gpt_crc32(rb, GPT_BAK_ARR_LBA * SEC, GPT_ENTRIES * GPT_ENTSZ) != acrc { gok = 0 } 431 // the ESP entry itself: type GUID, and a partition that ENDS exactly at the last usable LBA 432 var tg: i64 = 0 433 while tg < 16 { if (rb[2 * SEC + tg] as i64) != esp_guid_b(tg) { gok = 0 } tg = tg + 1 } 434 if ir32(rb, 2 * SEC + 32) != PART_LBA { gok = 0 } 435 if ir32(rb, 2 * SEC + 40) != (PART_LBA + VOL_SEC - 1) { gok = 0 } 436 // entry 1 must be the DATA partition, must start where the ESP ends, and must not run past the 437 // last usable LBA. Two partitions is exactly when an off-by-one starts eating the backup GPT. 438 var dg: i64 = 0 439 while dg < 16 { if (rb[2 * SEC + GPT_ENTSZ + dg] as i64) != data_guid_b(dg) { gok = 0 } dg = dg + 1 } 440 if ir32(rb, 2 * SEC + GPT_ENTSZ + 32) != VOL2_LBA { gok = 0 } 441 if ir32(rb, 2 * SEC + GPT_ENTSZ + 40) != (VOL2_LBA + VOL_SEC - 1) { gok = 0 } 442 if VOL2_LBA != (PART_LBA + VOL_SEC) { gok = 0 } // no gap, no overlap 443 if (VOL2_LBA + VOL_SEC - 1) > LAST_USABLE { gok = 0 } 444 if (rb[VOL2_BASE] as i64) != 0xEB { gok = 0 } // its BPB really landed 445 if (rb[VOL2_BASE + 82] as i64) != 70 { gok = 0 } // 'F' of FAT32 446 if (rb[v_clus(VOL2_BASE, 2)] as i64) != 78 { gok = 0 } // 'N' of the NISHIDATA label 447 if (PART_LBA + VOL_SEC - 1) > LAST_USABLE { gok = 0 } // overlap-its-own-backup guard 448 if ir32(rb, SEC + 48) != LAST_USABLE { gok = 0 } 449 if gok == 0 { ok = 0 } 450 p("NOS-USB gpt: sig+hdrCRC+arrCRC+backup+typeGUID+fit verified=" as *u8) 451 if gok == 1 { p("1\n" as *u8) } else { p("0\n" as *u8) } 452 // N1-full tooth: the root directory must carry KERNEL.NXE with the right size, and the bytes 453 // at its first cluster must equal the payload. Re-read from the WRITTEN image, never from RAM. 454 var kern_ok: i64 = 1 455 if nxelen > 0 { 456 let rdent: i64 = cluster_off(CL_ROOT) + 32 457 let kn: *u8 = "KERNEL NXE" as *u8 458 var kj: i64 = 0 459 while kj < 11 { if (rb[rdent + kj] as i64) != (kn[kj] as i64) { kern_ok = 0 } kj = kj + 1 } 460 if ir32(rb, rdent + 28) != nxelen { kern_ok = 0 } 461 let khi: i64 = (rb[rdent + 20] as i64) | ((rb[rdent + 21] as i64) << 8) 462 let klo: i64 = (rb[rdent + 26] as i64) | ((rb[rdent + 27] as i64) << 8) 463 let kclus: i64 = khi * PART_MAGIC_65536 + klo 464 if kclus != cl_kern { kern_ok = 0 } 465 let kdata: i64 = cluster_off(kclus) 466 var kk: i64 = 0 467 while kk < nxelen { if (rb[kdata + kk] as i64) != (nxe[kk] as i64) { kern_ok = 0; kk = nxelen } kk = kk + 1 } 468 if kern_ok == 0 { ok = 0 } 469 p("NOS-USB kernel-file: name+size+cluster+bytes verified=" as *u8) 470 if kern_ok == 1 { p("1 471" as *u8) } else { p("0 472" as *u8) } 473 } 474 if ir32(rb, 446 + 8) != 1 { ok = 0 } // protective MBR starts at LBA 1 475 if (rb[VOL_BASE] as i64) != 0xEB { ok = 0 } // BPB jump 476 if (rb[VOL_BASE + 82] as i64) != 70 { ok = 0 } // fs_type 'F' 477 if (rb[VOL_BASE + 85] as i64) != 51 { ok = 0 } // fs_type '3' 478 if (rb[cluster_off(CL_ROOT)] as i64) != 69 { ok = 0 } // root dir first entry 'E' (EFI) 479 if (rb[cluster_off(CL_FILE)] as i64) != 77 { ok = 0 } // file cluster: 'M' 480 if (rb[cluster_off(CL_FILE) + 1] as i64) != 90 { ok = 0 } // 'Z' (the .efi landed) 481 482 // TAMPER CONTROL, strengthened for GPT: flipping ONE byte anywhere in the partition entry array 483 // must break its CRC32. That is the property MBR could not offer at all, so the bite proves the 484 // integrity field is live rather than merely present. 485 var tamper: i64 = 0 486 let tsave: i64 = rb[2 * SEC + 33] as i64 487 rb[2 * SEC + 33] = ((tsave + 1) & 0xff) as u8 488 if gpt_crc32(rb, 2 * SEC, GPT_ENTRIES * GPT_ENTSZ) != acrc { tamper = 1 } 489 rb[2 * SEC + 33] = tsave as u8 490 if gpt_crc32(rb, 2 * SEC, GPT_ENTRIES * GPT_ENTSZ) != acrc { tamper = 0 } // and it restores 491 492 let lf: i64 = sys_openat_append("knowledge/status/nishi_os.log" as *u8, 0x1a4) 493 if lf >= 0 { 494 fp(lf, "NOSUSB name=nishi-boot.img fs=FAT32 gpt=protectiveMBR+1ESP efi=/EFI/BOOT/BOOTX64.EFI img_bytes=" as *u8); fn(lf, IMG_BYTES) 495 fp(lf, " efi_bytes=" as *u8); fn(lf, efilen) 496 fp(lf, " structural=" as *u8); fn(lf, ok) 497 fp(lf, " tamper_caught=" as *u8); fn(lf, tamper) 498 fp(lf, " verdict=" as *u8) 499 if ok == 1 { if tamper == 1 { fp(lf, "GREEN\n" as *u8) } else { fp(lf, "RED\n" as *u8) } } else { fp(lf, "RED\n" as *u8) } 500 sys_close(lf) 501 } 502 503 if ok == 1 { if tamper == 1 { 504 p("NOS-USB GREEN: authored " as *u8); p(outpath); p(" (" as *u8); fn(1, IMG_BYTES) 505 p(" bytes) GPT: ESP with /EFI/BOOT/BOOTX64.EFI + a NISHI DATA partition for NISHI.AI\n" as *u8) 506 sys_exit(0); return 0 507 } } 508 p("NOS-USB RED: structural=" as *u8); fn(1, ok); p(" tamper=" as *u8); fn(1, tamper); p("\n" as *u8) 509 sys_exit(1); return 1 510}