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}