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}