code wiki / _hdl_build / nx_efi_fat32_image.nx

nx_efi_fat32_image.nx source

↩ module page · 678 lines · 39524 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 return wr_gpt_hdr_ex(img, hdr_off, my_lba, alt_lba, arr_lba, arr_crc, LAST_USABLE) 138} 139// the same header with an explicit LastUsableLBA: the relocate verb (SO0) moves the backup to a real 140// device's end, where LastUsableLBA is a property of the DEVICE, not of the authored image 141func wr_gpt_hdr_ex(img: *u8, hdr_off: i64, my_lba: i64, alt_lba: i64, arr_lba: i64, arr_crc: i64, last_usable: i64) -> i64 { 142 var z: i64 = 0 143 while z < SEC { iw8(img, hdr_off + z, 0); z = z + 1 } 144 let sig: *u8 = "EFI PART" as *u8 145 istr(img, hdr_off + 0, sig, 8) 146 iw32(img, hdr_off + 8, 0x00010000) // revision 1.0 147 iw32(img, hdr_off + 12, GPT_HDR_SZ) 148 iw32(img, hdr_off + 16, 0) // header CRC32 field is ZERO while it is computed 149 iw32(img, hdr_off + 20, 0) // reserved 150 iw64(img, hdr_off + 24, my_lba) 151 iw64(img, hdr_off + 32, alt_lba) 152 iw64(img, hdr_off + 40, FIRST_USABLE) 153 iw64(img, hdr_off + 48, last_usable) 154 var g: i64 = 0 155 while g < 16 { iw8(img, hdr_off + 56 + g, disk_guid_b(g)); g = g + 1 } 156 iw64(img, hdr_off + 72, arr_lba) 157 iw32(img, hdr_off + 80, GPT_ENTRIES) 158 iw32(img, hdr_off + 84, GPT_ENTSZ) 159 iw32(img, hdr_off + 88, arr_crc) 160 let hc: i64 = gpt_crc32(img, hdr_off, GPT_HDR_SZ) // over exactly HeaderSize bytes, CRC field 0 161 iw32(img, hdr_off + 16, hc) 162 return hc 163} 164 165// write FAT entry `clus` = `val` into BOTH FATs (low 28 bits) 166// Both volumes have identical geometry, so every offset is derivable from the volume base. These 167// replace three constants that silently meant "volume 1" -- a constant that encodes WHICH volume is 168// exactly what stops an emitter from ever writing a second one. 169func v_fat1(vb: i64) -> i64 { return vb + RESV * SEC } 170func v_fat2(vb: i64) -> i64 { return vb + (RESV + FATSZ) * SEC } 171func v_data(vb: i64) -> i64 { return vb + (RESV + NFAT * FATSZ) * SEC } 172func v_clus(vb: i64, clus: i64) -> i64 { return v_data(vb) + (clus - 2) * SEC } 173func fat_set_at(img: *u8, vb: i64, clus: i64, val: i64) -> i64 { 174 iw32(img, v_fat1(vb) + clus * 4, val & 0x0FFFFFFF) 175 iw32(img, v_fat2(vb) + clus * 4, val & 0x0FFFFFFF) 176 return 0 177} 178func fat_set(img: *u8, clus: i64, val: i64) -> i64 { return fat_set_at(img, VOL_BASE, clus, val) } 179 180// 32-byte directory entry: name = exactly 11 bytes (space-padded 8.3) 181func wdir(img: *u8, off: i64, name: *u8, attr: i64, clus: i64, size: i64) -> i64 { 182 istr(img, off, name, 11) 183 iw8(img, off + 11, attr) 184 iw16(img, off + 20, (clus >> 16) & 0xFFFF) // first cluster hi 185 iw16(img, off + 26, clus & 0xFFFF) // first cluster lo 186 iw32(img, off + 28, size) // file size 187 return 0 188} 189 190func wr_bpb(img: *u8, base: i64) -> i64 { 191 iw8(img, base + 0, 0xEB); iw8(img, base + 1, 0x58); iw8(img, base + 2, 0x90) // jmp 192 istr(img, base + 3, "NISHI " as *u8, 8) // OEM 193 iw16(img, base + 11, SEC) // bytes/sector 194 iw8(img, base + 13, 1) // sectors/cluster 195 iw16(img, base + 14, RESV) // reserved sectors 196 iw8(img, base + 16, NFAT) // num FATs 197 iw16(img, base + 17, 0) // root entries (0 for FAT32) 198 iw16(img, base + 19, 0) // total sectors 16 (0 -> use 32) 199 iw8(img, base + 21, 0xF8) // media 200 iw16(img, base + 22, 0) // FAT size 16 (0 -> use 32) 201 iw16(img, base + 24, 32) // sectors/track 202 iw16(img, base + 26, 64) // heads 203 iw32(img, base + 28, PART_LBA) // hidden sectors 204 iw32(img, base + 32, VOL_SEC) // total sectors 32 205 iw32(img, base + 36, FATSZ) // FAT size 32 206 iw16(img, base + 40, 0) // ext flags 207 iw16(img, base + 42, 0) // fs version 208 iw32(img, base + 44, CL_ROOT) // root cluster 209 iw16(img, base + 48, 1) // FSInfo sector 210 iw16(img, base + 50, 6) // backup boot sector 211 iw8(img, base + 64, 0x80) // drive number 212 iw8(img, base + 66, 0x29) // ext boot signature 213 iw32(img, base + 67, 0x12345678) // volume id 214 istr(img, base + 71, "NISHI BOOT " as *u8, 11) // volume label 215 istr(img, base + 82, "FAT32 " as *u8, 8) // fs type 216 iw8(img, base + 510, 0x55); iw8(img, base + 511, 0xAA) 217 return 0 218} 219 220func p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 221func 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 } 222func fn(fd: i64, v: i64) -> i64 { 223 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 224 let t: *u8 = sys_mmap(28); var k: i64 = 0 225 if m == 0 { t[0] = 48; k = 1 } 226 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 227 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 228 sys_write(fd, bb, k); return 0 229} 230 231// ===== SO0 (smallos): nk0_gpt_relocate -- make the emitted image USABLE ON A REAL USB STICK ========== 232// The image is authored at a fixed IMG_BYTES with its backup GPT at the image's own last LBA. Written to a 233// larger device, that backup is no longer at the device's end: firmware and OS tools then see a GPT whose 234// AlternateLBA points into the middle of the disk. This verb rewrites the backup header + entry array at the 235// TRUE last LBA of `path` (a block device or an image file), updates the primary's AlternateLBA and 236// LastUsableLBA, and widens the protective MBR. NEVER-BRICK BY CONSTRUCTION (Rule 26): it refuses anything 237// that is not a GPT disk carrying OUR disk GUID, refuses a device smaller than the image, writes the BACKUP 238// first and the PRIMARY last so an interrupted run leaves the primary valid, retires the old mid-disk backup 239// header (signature zeroed) so no reader can find two, never touches a partition entry (same bytes, same 240// CRC), and is idempotent: a second run reports ALREADY-RELOCATED and writes nothing. 241// nx_efi_fat32_image relocate <device-or-image> 242// Exit: 0 GREEN or ALREADY-RELOCATED | 1 RED (a write or the re-read verify failed) | 2 REFUSED (rule named) 243const RL_HEAD_BYTES: i64 = 17408 // LBA 0..33: protective MBR + primary header + the entry array 244const RL_EXIT_RED: i64 = 1 245const RL_EXIT_REFUSED: i64 = 2 246const RL_MBR_MAX: i64 = 0xFFFFFFFF 247const RL_SEEK_SET: i64 = 0 248const RL_SEEK_END: i64 = 2 249 250func ir64(img: *u8, off: i64) -> i64 { return ir32(img, off) | (ir32(img, off + 4) << 32) } 251func rl_streq(a: *u8, b: *u8) -> i64 { 252 var i: i64 = 0 253 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 254 if b[i] != (0 as u8) { return 0 } 255 return 1 256} 257func rl_pread(fd: i64, off: i64, buf: *u8, n: i64) -> i64 { 258 if sys_lseek(fd, off, RL_SEEK_SET) != off { return 0 - 1 } 259 var got: i64 = 0 260 while got < n { let r: i64 = sys_read(fd, (buf + got) as *u8, n - got); if r <= 0 { return got } got = got + r } 261 return got 262} 263func rl_pwrite(fd: i64, off: i64, buf: *u8, n: i64) -> i64 { 264 if sys_lseek(fd, off, RL_SEEK_SET) != off { return 0 - 1 } 265 var put: i64 = 0 266 while put < n { let w: i64 = sys_write(fd, (buf + put) as *u8, n - put); if w <= 0 { return put } put = put + w } 267 return put 268} 269// a 512-byte block is a valid GPT header for my_lba: signature, HeaderSize, CRC over HeaderSize with the field 270// zeroed exactly as a firmware parser does, and MyLBA equal to where it was read from 271func rl_hdr_valid(hdr: *u8, my_lba: i64) -> i64 { 272 let sig: *u8 = "EFI PART" as *u8 273 var i: i64 = 0 274 while i < 8 { if (hdr[i] as i64) != (sig[i] as i64) { return 0 } i = i + 1 } 275 if ir32(hdr, 12) != GPT_HDR_SZ { return 0 } 276 let save: i64 = ir32(hdr, 16) 277 iw32(hdr, 16, 0) 278 let crc: i64 = gpt_crc32(hdr, 0, GPT_HDR_SZ) 279 iw32(hdr, 16, save) 280 if crc != save { return 0 } 281 if ir64(hdr, 24) != my_lba { return 0 } 282 return 1 283} 284func rl_refuse(rule: *u8, path: *u8, fd: i64) -> i64 { 285 p("NOS-USB RELOCATE REFUSED rule=" as *u8); p(rule); p(" path=" as *u8); p(path); p(" (nothing written)\n" as *u8) 286 if fd >= 0 { sys_close(fd) } 287 return RL_EXIT_REFUSED 288} 289func nk0_gpt_relocate(path: *u8) -> i64 { 290 let fd: i64 = sys_openat_rdwr(path, 0x1a4) 291 if fd < 0 { return rl_refuse("cannot-open" as *u8, path, 0 - 1) } 292 let size: i64 = sys_lseek(fd, 0, RL_SEEK_END) 293 if size < IMG_BYTES { p("NOS-USB RELOCATE device_bytes=" as *u8); fn(1, size); p(" image_bytes=" as *u8); fn(1, IMG_BYTES); p("\n" as *u8); return rl_refuse("device-smaller-than-image" as *u8, path, fd) } 294 if (size % SEC) != 0 { return rl_refuse("not-sector-aligned" as *u8, path, fd) } 295 let new_last: i64 = size / SEC - 1 296 let head: *u8 = sys_mmap(RL_HEAD_BYTES) 297 if rl_pread(fd, 0, head, RL_HEAD_BYTES) != RL_HEAD_BYTES { return rl_refuse("short-read-head" as *u8, path, fd) } 298 if (head[510] as i64) != 0x55 { return rl_refuse("not-gpt-no-mbr-signature" as *u8, path, fd) } 299 if (head[511] as i64) != 0xAA { return rl_refuse("not-gpt-no-mbr-signature" as *u8, path, fd) } 300 if (head[446 + 4] as i64) != 0xEE { return rl_refuse("not-gpt-no-protective-entry" as *u8, path, fd) } 301 if rl_hdr_valid((head + SEC) as *u8, 1) == 0 { return rl_refuse("not-gpt-primary-header-invalid" as *u8, path, fd) } 302 var g: i64 = 0 303 while g < 16 { if (head[SEC + 56 + g] as i64) != disk_guid_b(g) { return rl_refuse("foreign-disk-guid" as *u8, path, fd) } g = g + 1 } 304 if ir64(head, SEC + 72) != 2 { return rl_refuse("unexpected-array-lba" as *u8, path, fd) } 305 if ir32(head, SEC + 80) != GPT_ENTRIES { return rl_refuse("unexpected-array-geometry" as *u8, path, fd) } 306 if ir32(head, SEC + 84) != GPT_ENTSZ { return rl_refuse("unexpected-array-geometry" as *u8, path, fd) } 307 let arr_bytes: i64 = GPT_ENTRIES * GPT_ENTSZ 308 let acrc: i64 = gpt_crc32(head, 2 * SEC, arr_bytes) 309 if ir32(head, SEC + 88) != acrc { return rl_refuse("array-crc-mismatch" as *u8, path, fd) } 310 let old_last: i64 = ir64(head, SEC + 32) 311 if old_last > new_last { return rl_refuse("alternate-beyond-device" as *u8, path, fd) } 312 let new_arr_lba: i64 = new_last - GPT_ARR_SEC 313 let new_last_usable: i64 = new_arr_lba - 1 314 if ir64(head, 2 * SEC + 40) > new_last_usable { return rl_refuse("partition-past-last-usable" as *u8, path, fd) } 315 if ir64(head, 2 * SEC + GPT_ENTSZ + 40) > new_last_usable { return rl_refuse("partition-past-last-usable" as *u8, path, fd) } 316 // idempotence: the backup already sits at the true end and verifies 317 let bh: *u8 = sys_mmap(SEC) 318 if old_last == new_last { if rl_pread(fd, new_last * SEC, bh, SEC) == SEC { if rl_hdr_valid(bh, new_last) == 1 { 319 p("NOS-USB RELOCATE ALREADY-RELOCATED path=" as *u8); p(path); p(" last_lba=" as *u8); fn(1, new_last); p(" (nothing written)\n" as *u8) 320 sys_close(fd) 321 return 0 322 } } } 323 // 1. the backup entry array at the new end: the same bytes, the same CRC 324 if rl_pwrite(fd, new_arr_lba * SEC, (head + 2 * SEC) as *u8, arr_bytes) != arr_bytes { p("NOS-USB RELOCATE RED: write backup array\n" as *u8); sys_close(fd); return RL_EXIT_RED } 325 // 2. the backup header at the new last LBA 326 let bhdr: *u8 = sys_mmap(SEC) 327 wr_gpt_hdr_ex(bhdr, 0, new_last, 1, new_arr_lba, acrc, new_last_usable) 328 if rl_pwrite(fd, new_last * SEC, bhdr, SEC) != SEC { p("NOS-USB RELOCATE RED: write backup header\n" as *u8); sys_close(fd); return RL_EXIT_RED } 329 sys_fsync(fd) 330 // 3. retire the old mid-disk backup header so no reader can find two 331 if old_last != new_last { 332 let oh: *u8 = sys_mmap(SEC) 333 if rl_pread(fd, old_last * SEC, oh, SEC) == SEC { if rl_hdr_valid(oh, old_last) == 1 { 334 var zi: i64 = 0 335 while zi < 8 { oh[zi] = 0 as u8; zi = zi + 1 } 336 rl_pwrite(fd, old_last * SEC, oh, SEC) 337 } } 338 } 339 // 4. the primary header LAST: AlternateLBA and LastUsableLBA move, everything else is identical 340 let phdr: *u8 = sys_mmap(SEC) 341 wr_gpt_hdr_ex(phdr, 0, 1, new_last, 2, acrc, new_last_usable) 342 if rl_pwrite(fd, SEC, phdr, SEC) != SEC { p("NOS-USB RELOCATE RED: write primary header\n" as *u8); sys_close(fd); return RL_EXIT_RED } 343 // 5. the protective MBR now spans the whole device (saturated per spec on huge disks) 344 var pmsz: i64 = new_last 345 if pmsz > RL_MBR_MAX { pmsz = RL_MBR_MAX } 346 iw32(head, 446 + 12, pmsz) 347 if rl_pwrite(fd, 0, head, SEC) != SEC { p("NOS-USB RELOCATE RED: write protective MBR\n" as *u8); sys_close(fd); return RL_EXIT_RED } 348 sys_fsync(fd) 349 // 6. re-read and verify from the DEVICE, never from RAM 350 var vok: i64 = 1 351 let rp: *u8 = sys_mmap(SEC) 352 if rl_pread(fd, SEC, rp, SEC) != SEC { vok = 0 } else { 353 if rl_hdr_valid(rp, 1) == 0 { vok = 0 } 354 if ir64(rp, 32) != new_last { vok = 0 } 355 if ir64(rp, 48) != new_last_usable { vok = 0 } 356 } 357 let rb: *u8 = sys_mmap(SEC) 358 if rl_pread(fd, new_last * SEC, rb, SEC) != SEC { vok = 0 } else { 359 if rl_hdr_valid(rb, new_last) == 0 { vok = 0 } 360 if ir64(rb, 32) != 1 { vok = 0 } 361 if ir64(rb, 72) != new_arr_lba { vok = 0 } 362 } 363 let ra: *u8 = sys_mmap(arr_bytes) 364 if rl_pread(fd, new_arr_lba * SEC, ra, arr_bytes) != arr_bytes { vok = 0 } else { if gpt_crc32(ra, 0, arr_bytes) != acrc { vok = 0 } } 365 let rm: *u8 = sys_mmap(SEC) 366 if rl_pread(fd, 0, rm, SEC) != SEC { vok = 0 } else { if ir32(rm, 446 + 12) != pmsz { vok = 0 } } 367 sys_close(fd) 368 let lf: i64 = sys_openat_append("knowledge/status/nishi_os.log" as *u8, 0x1a4) 369 if lf >= 0 { 370 fp(lf, "NOSUSB-RELOCATE path=" as *u8); fp(lf, path) 371 fp(lf, " device_lba=" as *u8); fn(lf, new_last + 1) 372 fp(lf, " backup_hdr_lba=" as *u8); fn(lf, new_last) 373 fp(lf, " old_backup_lba=" as *u8); fn(lf, old_last) 374 fp(lf, " verified=" as *u8); fn(lf, vok) 375 fp(lf, " verdict=" as *u8) 376 if vok == 1 { fp(lf, "GREEN\n" as *u8) } else { fp(lf, "RED\n" as *u8) } 377 sys_close(lf) 378 } 379 if vok == 1 { 380 p("NOS-USB RELOCATE GREEN: path=" as *u8); p(path) 381 p(" device_lba=" as *u8); fn(1, new_last + 1) 382 p(" backup_hdr_lba=" as *u8); fn(1, new_last) 383 p(" backup_arr_lba=" as *u8); fn(1, new_arr_lba) 384 p(" last_usable=" as *u8); fn(1, new_last_usable) 385 p(" old_backup_lba=" as *u8); fn(1, old_last) 386 p(" verified=1\n" as *u8) 387 return 0 388 } 389 p("NOS-USB RELOCATE RED: re-read verify failed verified=0\n" as *u8) 390 return RL_EXIT_RED 391} 392 393func main(argc: i64, argv: *i64) -> i64 { 394 if argc >= 3 { if rl_streq(argv[1] as *u8, "relocate" as *u8) == 1 { let rrc: i64 = nk0_gpt_relocate(argv[2] as *u8); sys_exit(rrc); return rrc } } 395 var efipath: *u8 = "_offc/nx_boot_uefi.efi" as *u8 // payload .efi (argv[1] overrides) 396 if argc >= 2 { efipath = argv[1] as *u8 } 397 var outpath: *u8 = "_offc/nishi-boot.img" as *u8 // output image (argv[2] overrides) 398 if argc >= 3 { outpath = argv[2] as *u8 } 399 // N1-full: argv[3] optionally places a SECOND file, /KERNEL.NXE, in the volume ROOT so the 400 // boot shim can READ ITS OWN KERNEL off the filesystem instead of being handed an embedded 401 // copy at build time. Root-level (not a subdirectory) keeps the shim's Open() path trivial. 402 var nxepath: *u8 = 0 as *u8 403 if argc >= 4 { nxepath = argv[3] as *u8 } 404 var nxelen: i64 = 0 405 var nxe: *u8 = 0 as *u8 406 if nxepath != (0 as *u8) { 407 let nl: *i64 = sys_mmap(16) as *i64 408 nxe = sys_read_file(nxepath, nl) 409 nxelen = nl[0] 410 if nxelen <= 0 { p("NOS-USB RED: cannot read NXE payload 411" as *u8); sys_exit(2); return 2 } 412 } 413 // read the EFI boot app 414 let lenp: *i64 = sys_mmap(16) as *i64 415 let efi: *u8 = sys_read_file(efipath, lenp) 416 let efilen: i64 = lenp[0] 417 if efilen <= 0 { p("NOS-USB REFUSED: cannot read payload .efi: " as *u8); p(efipath); p("\n" as *u8); sys_exit(2); return 2 } 418 // The arg order is <payload.efi> <out.img>. Swapping them read an IMAGE as the payload and then 419 // wrote the new image straight over the caller's .efi -- destroying an input before the structural 420 // gate could refuse. A payload that is not a PE image is refused HERE, before anything is written. 421 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(" 422" as *u8); sys_exit(2); return 2 } 423 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(" 424" as *u8); sys_exit(2); return 2 } 425 if efilen >= IMG_BYTES { p("NOS-USB REFUSED: payload does not fit the volume it must live in 426" as *u8); sys_exit(2); return 2 } 427 428 let img: *u8 = sys_mmap(IMG_BYTES) // zero-filled 429 430 // ----- PROTECTIVE MBR: ONE 0xEE partition spanning the disk (never a real partition) -------- 431 // Its whole job is to make a legacy tool see a full, unknown-type disk instead of an empty one. 432 iw8(img, 446 + 0, 0x00) // NOT bootable: nothing boots via this entry 433 iw8(img, 446 + 1, 0x00); iw8(img, 446 + 2, 0x02); iw8(img, 446 + 3, 0x00) // CHS start 0/0/2 434 iw8(img, 446 + 4, 0xEE) // type 0xEE = GPT protective 435 iw8(img, 446 + 5, 0xFF); iw8(img, 446 + 6, 0xFF); iw8(img, 446 + 7, 0xFF) // CHS end (saturated) 436 iw32(img, 446 + 8, 1) // starts at LBA 1 (the GPT header) 437 var pmsz: i64 = DISK_SEC - 1 438 if pmsz > 0xFFFFFFFF { pmsz = 0xFFFFFFFF } // saturate, per spec, on huge disks 439 iw32(img, 446 + 12, pmsz) 440 iw8(img, 510, 0x55); iw8(img, 511, 0xAA) 441 442 // ----- GPT partition entry 0: our ESP, filling the usable area exactly -------------------- 443 let arr_off: i64 = 2 * SEC 444 var ge: i64 = 0 445 while ge < 16 { iw8(img, arr_off + ge, esp_guid_b(ge)); ge = ge + 1 } // PartitionTypeGUID 446 ge = 0 447 while ge < 16 { iw8(img, arr_off + 16 + ge, part_guid_b(ge)); ge = ge + 1 } // UniquePartitionGUID 448 iw64(img, arr_off + 32, PART_LBA) // StartingLBA 449 iw64(img, arr_off + 40, PART_LBA + VOL_SEC - 1) // EndingLBA (inclusive) 450 iw64(img, arr_off + 48, 0) // Attributes 451 let pname: *u8 = "EFI System Partition" as *u8 // UTF-16LE, 36 chars max 452 var pn: i64 = 0 453 while pn < 20 { iw16(img, arr_off + 56 + pn * 2, pname[pn] as i64); pn = pn + 1 } 454 // ---- GPT entry 1: the DATA partition, filling the rest of the usable area exactly --------- 455 let e1: i64 = arr_off + GPT_ENTSZ 456 ge = 0 457 while ge < 16 { iw8(img, e1 + ge, data_guid_b(ge)); ge = ge + 1 } 458 ge = 0 459 while ge < 16 { iw8(img, e1 + 16 + ge, part2_guid_b(ge)); ge = ge + 1 } 460 iw64(img, e1 + 32, VOL2_LBA) 461 iw64(img, e1 + 40, VOL2_LBA + VOL_SEC - 1) 462 iw64(img, e1 + 48, 0) 463 let dname: *u8 = "NISHI DATA" as *u8 464 var dn: i64 = 0 465 while dn < 10 { iw16(img, e1 + 56 + dn * 2, dname[dn] as i64); dn = dn + 1 } 466 // Both copies of the array are the SAME bytes, so they get the SAME CRC -- copy, never re-emit. 467 let arr_crc: i64 = gpt_crc32(img, arr_off, GPT_ENTRIES * GPT_ENTSZ) 468 var ac: i64 = 0 469 while ac < (GPT_ENTRIES * GPT_ENTSZ) { img[GPT_BAK_ARR_LBA * SEC + ac] = img[arr_off + ac]; ac = ac + 1 } 470 wr_gpt_hdr(img, 1 * SEC, 1, LAST_LBA, 2, arr_crc) // primary 471 wr_gpt_hdr(img, LAST_LBA * SEC, LAST_LBA, 1, GPT_BAK_ARR_LBA, arr_crc) // backup (swapped) 472 473 // ----- FAT32 BPB (+ backup) ----- 474 wr_bpb(img, VOL_BASE) 475 wr_bpb(img, BKBOOT_OFF) 476 477 // ----- FSInfo ----- 478 iw32(img, FSINFO_OFF + 0, 0x41615252) 479 iw32(img, FSINFO_OFF + 484, 0x61417272) 480 iw32(img, FSINFO_OFF + 488, 0 - 1) // free count unknown (0xFFFFFFFF) 481 iw32(img, FSINFO_OFF + 492, 7) // next free hint 482 iw8(img, FSINFO_OFF + 510, 0x55); iw8(img, FSINFO_OFF + 511, 0xAA) 483 484 // ----- the DATA volume: same emitter, different base. Empty on purpose: this is where the 485 // ----- user drops NISHI.AI (or anything else). A volume label so it is recognisable in a file 486 // ----- manager rather than showing up as an anonymous drive. 487 wr_bpb(img, VOL2_BASE) 488 wr_bpb(img, VOL2_BASE + 6 * SEC) 489 iw32(img, VOL2_BASE + SEC + 0, 0x41615252) 490 iw32(img, VOL2_BASE + SEC + 484, 0x61417272) 491 iw32(img, VOL2_BASE + SEC + 488, 0 - 1) 492 iw32(img, VOL2_BASE + SEC + 492, 3) 493 iw8(img, VOL2_BASE + SEC + 510, 0x55); iw8(img, VOL2_BASE + SEC + 511, 0xAA) 494 fat_set_at(img, VOL2_BASE, 0, 0x0FFFFFF8) 495 fat_set_at(img, VOL2_BASE, 1, 0x0FFFFFFF) 496 fat_set_at(img, VOL2_BASE, 2, 0x0FFFFFFF) // root dir: one cluster, end of chain 497 wdir(img, v_clus(VOL2_BASE, 2), "NISHIDATA " as *u8, 0x08, 0, 0) // volume label 498 499 // ----- FAT entries ----- 500 fat_set(img, 0, 0x0FFFFFF8) // media 501 fat_set(img, 1, 0x0FFFFFFF) 502 fat_set(img, CL_ROOT, 0x0FFFFFFF) // root: single cluster 503 fat_set(img, CL_EFI, 0x0FFFFFFF) // /EFI: single cluster 504 fat_set(img, CL_BOOT, 0x0FFFFFFF) // /EFI/BOOT: single cluster 505 // file: efilen bytes -> ceil(efilen/512) clusters, chained from CL_FILE 506 var nfc: i64 = (efilen + SEC - 1) / SEC 507 if nfc < 1 { nfc = 1 } 508 var c: i64 = 0 509 while c < nfc { 510 if c == nfc - 1 { fat_set(img, CL_FILE + c, 0x0FFFFFFF) } 511 else { fat_set(img, CL_FILE + c, CL_FILE + c + 1) } 512 c = c + 1 513 } 514 515 // KERNEL.NXE occupies the clusters immediately after BOOTX64.EFI 516 let cl_kern: i64 = CL_FILE + nfc 517 var nkc: i64 = 0 518 if nxelen > 0 { 519 nkc = (nxelen + SEC - 1) / SEC 520 if nkc < 1 { nkc = 1 } 521 var kc: i64 = 0 522 while kc < nkc { 523 if kc == nkc - 1 { fat_set(img, cl_kern + kc, 0x0FFFFFFF) } 524 else { fat_set(img, cl_kern + kc, cl_kern + kc + 1) } 525 kc = kc + 1 526 } 527 } 528 529 // ----- directories ----- 530 // root (cluster 2): the "EFI" subdirectory 531 wdir(img, cluster_off(CL_ROOT), "EFI " as *u8, 0x10, CL_EFI, 0) 532 // /EFI (cluster 3): . .. BOOT 533 wdir(img, cluster_off(CL_EFI) + 0, ". " as *u8, 0x10, CL_EFI, 0) 534 wdir(img, cluster_off(CL_EFI) + 32, ".. " as *u8, 0x10, 0, 0) // .. of root child -> 0 535 wdir(img, cluster_off(CL_EFI) + 64, "BOOT " as *u8, 0x10, CL_BOOT, 0) 536 // /EFI/BOOT (cluster 4): . .. BOOTX64.EFI 537 wdir(img, cluster_off(CL_BOOT) + 0, ". " as *u8, 0x10, CL_BOOT, 0) 538 wdir(img, cluster_off(CL_BOOT) + 32, ".. " as *u8, 0x10, CL_EFI, 0) 539 wdir(img, cluster_off(CL_BOOT) + 64, "BOOTX64 EFI" as *u8, 0x20, CL_FILE, efilen) 540 541 // root entry #2: /KERNEL.NXE (8.3 name is "KERNEL NXE") 542 if nxelen > 0 { wdir(img, cluster_off(CL_ROOT) + 32, "KERNEL NXE" as *u8, 0x20, cl_kern, nxelen) } 543 544 // ----- file data (contiguous clusters from CL_FILE) ----- 545 let foff: i64 = cluster_off(CL_FILE) 546 var i: i64 = 0 547 while i < efilen { img[foff + i] = efi[i]; i = i + 1 } 548 549 if nxelen > 0 { 550 let koff: i64 = cluster_off(cl_kern) 551 var ki: i64 = 0 552 while ki < nxelen { img[koff + ki] = nxe[ki]; ki = ki + 1 } 553 } 554 555 // ----- write the image ----- 556 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 557 if ofd < 0 { p("NOS-USB RED: cannot write image\n" as *u8); sys_exit(1); return 1 } 558 var done: i64 = 0 559 while done < IMG_BYTES { 560 let w: i64 = sys_write(ofd, (img + done) as *u8, IMG_BYTES - done) 561 if w <= 0 { done = IMG_BYTES } else { done = done + w } 562 } 563 sys_close(ofd) 564 565 // ----- self-gate: re-read + verify the structures ----- 566 let l2: *i64 = sys_mmap(16) as *i64 567 let rb: *u8 = sys_read_file(outpath, l2) 568 let rlen: i64 = l2[0] 569 var ok: i64 = 1 570 if rlen != IMG_BYTES { ok = 0 } 571 if (rb[510] as i64) != 0x55 { ok = 0 } 572 if (rb[511] as i64) != 0xAA { ok = 0 } // protective-MBR signature 573 if (rb[446 + 4] as i64) != 0xEE { ok = 0 } // type 0xEE = GPT protective, NOT 0x0C 574 if (rb[446 + 0] as i64) != 0x00 { ok = 0 } // and it must NOT be marked bootable 575 // ---- GPT teeth: both headers, both CRCs, and the geometry that stops a partition from 576 // ---- overlapping its own backup (the failure a hand-summed layout produces). 577 var gok: i64 = 1 578 let gsig: *u8 = "EFI PART" as *u8 579 var gi: i64 = 0 580 while gi < 8 { if (rb[SEC + gi] as i64) != (gsig[gi] as i64) { gok = 0 } gi = gi + 1 } 581 while gi < 16 { if (rb[LAST_LBA * SEC + gi - 8] as i64) != (gsig[gi - 8] as i64) { gok = 0 } gi = gi + 1 } 582 if ir32(rb, SEC + 12) != GPT_HDR_SZ { gok = 0 } 583 if ir32(rb, SEC + 80) != GPT_ENTRIES { gok = 0 } 584 if ir32(rb, SEC + 84) != GPT_ENTSZ { gok = 0 } 585 // header CRC: recompute with the CRC field zeroed, exactly as a real firmware parser does 586 let hsave: i64 = ir32(rb, SEC + 16) 587 iw32(rb, SEC + 16, 0) 588 if gpt_crc32(rb, SEC, GPT_HDR_SZ) != hsave { gok = 0 } 589 iw32(rb, SEC + 16, hsave) 590 let bsave: i64 = ir32(rb, LAST_LBA * SEC + 16) 591 iw32(rb, LAST_LBA * SEC + 16, 0) 592 if gpt_crc32(rb, LAST_LBA * SEC, GPT_HDR_SZ) != bsave { gok = 0 } 593 iw32(rb, LAST_LBA * SEC + 16, bsave) 594 // entry-array CRC, both copies, and they must be byte-identical to each other 595 let acrc: i64 = gpt_crc32(rb, 2 * SEC, GPT_ENTRIES * GPT_ENTSZ) 596 if ir32(rb, SEC + 88) != acrc { gok = 0 } 597 if ir32(rb, LAST_LBA * SEC + 88) != acrc { gok = 0 } 598 if gpt_crc32(rb, GPT_BAK_ARR_LBA * SEC, GPT_ENTRIES * GPT_ENTSZ) != acrc { gok = 0 } 599 // the ESP entry itself: type GUID, and a partition that ENDS exactly at the last usable LBA 600 var tg: i64 = 0 601 while tg < 16 { if (rb[2 * SEC + tg] as i64) != esp_guid_b(tg) { gok = 0 } tg = tg + 1 } 602 if ir32(rb, 2 * SEC + 32) != PART_LBA { gok = 0 } 603 if ir32(rb, 2 * SEC + 40) != (PART_LBA + VOL_SEC - 1) { gok = 0 } 604 // entry 1 must be the DATA partition, must start where the ESP ends, and must not run past the 605 // last usable LBA. Two partitions is exactly when an off-by-one starts eating the backup GPT. 606 var dg: i64 = 0 607 while dg < 16 { if (rb[2 * SEC + GPT_ENTSZ + dg] as i64) != data_guid_b(dg) { gok = 0 } dg = dg + 1 } 608 if ir32(rb, 2 * SEC + GPT_ENTSZ + 32) != VOL2_LBA { gok = 0 } 609 if ir32(rb, 2 * SEC + GPT_ENTSZ + 40) != (VOL2_LBA + VOL_SEC - 1) { gok = 0 } 610 if VOL2_LBA != (PART_LBA + VOL_SEC) { gok = 0 } // no gap, no overlap 611 if (VOL2_LBA + VOL_SEC - 1) > LAST_USABLE { gok = 0 } 612 if (rb[VOL2_BASE] as i64) != 0xEB { gok = 0 } // its BPB really landed 613 if (rb[VOL2_BASE + 82] as i64) != 70 { gok = 0 } // 'F' of FAT32 614 if (rb[v_clus(VOL2_BASE, 2)] as i64) != 78 { gok = 0 } // 'N' of the NISHIDATA label 615 if (PART_LBA + VOL_SEC - 1) > LAST_USABLE { gok = 0 } // overlap-its-own-backup guard 616 if ir32(rb, SEC + 48) != LAST_USABLE { gok = 0 } 617 if gok == 0 { ok = 0 } 618 p("NOS-USB gpt: sig+hdrCRC+arrCRC+backup+typeGUID+fit verified=" as *u8) 619 if gok == 1 { p("1\n" as *u8) } else { p("0\n" as *u8) } 620 // N1-full tooth: the root directory must carry KERNEL.NXE with the right size, and the bytes 621 // at its first cluster must equal the payload. Re-read from the WRITTEN image, never from RAM. 622 var kern_ok: i64 = 1 623 if nxelen > 0 { 624 let rdent: i64 = cluster_off(CL_ROOT) + 32 625 let kn: *u8 = "KERNEL NXE" as *u8 626 var kj: i64 = 0 627 while kj < 11 { if (rb[rdent + kj] as i64) != (kn[kj] as i64) { kern_ok = 0 } kj = kj + 1 } 628 if ir32(rb, rdent + 28) != nxelen { kern_ok = 0 } 629 let khi: i64 = (rb[rdent + 20] as i64) | ((rb[rdent + 21] as i64) << 8) 630 let klo: i64 = (rb[rdent + 26] as i64) | ((rb[rdent + 27] as i64) << 8) 631 let kclus: i64 = khi * PART_MAGIC_65536 + klo 632 if kclus != cl_kern { kern_ok = 0 } 633 let kdata: i64 = cluster_off(kclus) 634 var kk: i64 = 0 635 while kk < nxelen { if (rb[kdata + kk] as i64) != (nxe[kk] as i64) { kern_ok = 0; kk = nxelen } kk = kk + 1 } 636 if kern_ok == 0 { ok = 0 } 637 p("NOS-USB kernel-file: name+size+cluster+bytes verified=" as *u8) 638 if kern_ok == 1 { p("1 639" as *u8) } else { p("0 640" as *u8) } 641 } 642 if ir32(rb, 446 + 8) != 1 { ok = 0 } // protective MBR starts at LBA 1 643 if (rb[VOL_BASE] as i64) != 0xEB { ok = 0 } // BPB jump 644 if (rb[VOL_BASE + 82] as i64) != 70 { ok = 0 } // fs_type 'F' 645 if (rb[VOL_BASE + 85] as i64) != 51 { ok = 0 } // fs_type '3' 646 if (rb[cluster_off(CL_ROOT)] as i64) != 69 { ok = 0 } // root dir first entry 'E' (EFI) 647 if (rb[cluster_off(CL_FILE)] as i64) != 77 { ok = 0 } // file cluster: 'M' 648 if (rb[cluster_off(CL_FILE) + 1] as i64) != 90 { ok = 0 } // 'Z' (the .efi landed) 649 650 // TAMPER CONTROL, strengthened for GPT: flipping ONE byte anywhere in the partition entry array 651 // must break its CRC32. That is the property MBR could not offer at all, so the bite proves the 652 // integrity field is live rather than merely present. 653 var tamper: i64 = 0 654 let tsave: i64 = rb[2 * SEC + 33] as i64 655 rb[2 * SEC + 33] = ((tsave + 1) & 0xff) as u8 656 if gpt_crc32(rb, 2 * SEC, GPT_ENTRIES * GPT_ENTSZ) != acrc { tamper = 1 } 657 rb[2 * SEC + 33] = tsave as u8 658 if gpt_crc32(rb, 2 * SEC, GPT_ENTRIES * GPT_ENTSZ) != acrc { tamper = 0 } // and it restores 659 660 let lf: i64 = sys_openat_append("knowledge/status/nishi_os.log" as *u8, 0x1a4) 661 if lf >= 0 { 662 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) 663 fp(lf, " efi_bytes=" as *u8); fn(lf, efilen) 664 fp(lf, " structural=" as *u8); fn(lf, ok) 665 fp(lf, " tamper_caught=" as *u8); fn(lf, tamper) 666 fp(lf, " verdict=" as *u8) 667 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) } 668 sys_close(lf) 669 } 670 671 if ok == 1 { if tamper == 1 { 672 p("NOS-USB GREEN: authored " as *u8); p(outpath); p(" (" as *u8); fn(1, IMG_BYTES) 673 p(" bytes) GPT: ESP with /EFI/BOOT/BOOTX64.EFI + a NISHI DATA partition for NISHI.AI\n" as *u8) 674 sys_exit(0); return 0 675 } } 676 p("NOS-USB RED: structural=" as *u8); fn(1, ok); p(" tamper=" as *u8); fn(1, tamper); p("\n" as *u8) 677 sys_exit(1); return 1 678}