code wiki / _hdl_build / nx_efi_fat32_image.nx
nx_efi_fat32_image.nx
buildroot/runtime/_hdl_build/nx_efi_fat32_image.nx
about
nx_efi_fat32_image.nx -- NOS-USB-R0: sovereign bootable USB disk-image emitter.
"Nishi ecosystem all the way up": this organ AUTHORS, byte-by-byte, a complete UEFI-bootable
disk image -- MBR partition table + a FAT32 EFI System Partition containing
/EFI/BOOT/BOOTX64.EFI (our nx_boot_uefi.efi) -- with NO mkfs / xorriso / dd-as-formatter / GRUB.
The operator writes the emitted image to a physical USB (the raw byte-copy to the device is the
one hardware boundary), then UEFI firmware finds \EFI\BOOT\BOOTX64.EFI and boots NISHI.
This is the first concrete piece of the nx_spore design (knowledge: iso/README.md).
FAT32 requires >=65525 clusters, so the volume is ~34 MB (1 sector/cluster). Layout:
LBA 0 : MBR (1 partition, type 0x0C FAT32-LBA, bootable, start LBA 2048)
LBA 2048 : FAT32 volume -> BPB(+FSInfo+backup) | 2 FATs | data (root,/EFI,/EFI/BOOT,file)
Build (sovereign): ./_offc/nx_sov_build_run.elf nx_efi_fat32_image (reads _offc/nx_boot_uefi.efi)
Self-gate: re-read image -> MBR sig + partition type + BPB "FAT32" + root "EFI" dir + the .efi's
"MZ" at the file's cluster; tamper (flip partition type) -> reject. Log -> knowledge/status/nishi_os.log
Sovereign: syscalls only, no gcc/.sh. license_tier: ORIGINAL
dependencies 1 imports · 0 importers
imports: nx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 18 | const PART_MAGIC_65536: i64 = 65536 |
| 20 | const SEC: i64 = 512 |
| 21 | const PART_LBA: i64 = 2048 |
| 22 | const RESV: i64 = 32 |
| 23 | const NFAT: i64 = 2 |
| 24 | const CLUS_CNT: i64 = 65536 // >= 65525 so it is a valid FAT32 |
| 25 | const FATSZ: i64 = 513 // sectors per FAT (513*512/4 = 65664 entries >= CLUS_CNT+2) |
| 26 | const VOL_SEC: i64 = 66594 // RESV + NFAT*FATSZ + CLUS_CNT (32 + 1026 + 65536) |
| 36 | const GPT_ENTRIES: i64 = 128 // spec minimum reserved size is 16 KiB = 128 x 128B |
| 37 | const GPT_ENTSZ: i64 = 128 |
| 38 | const GPT_ARR_SEC: i64 = 32 // 128*128/512 |
| 39 | const GPT_HDR_SZ: i64 = 92 |
| 50 | const VOL2_LBA: i64 = 68642 // PART_LBA + VOL_SEC -- immediately after the ESP |
| 51 | const VOL2_BASE: i64 = 35144704 // VOL2_LBA * 512 |
| 52 | const DISK_SEC: i64 = 135269 // PART_LBA + VOL_SEC*2 + GPT_ARR_SEC + 1 |
| 53 | const IMG_BYTES: i64 = 69257728 // DISK_SEC * 512 |
| 54 | const LAST_LBA: i64 = 135268 // DISK_SEC - 1 |
| 55 | const GPT_BAK_ARR_LBA: i64 = 135236 // LAST_LBA - GPT_ARR_SEC |
| 56 | const FIRST_USABLE: i64 = 34 // LBA 1 header + LBA 2..33 array |
| 57 | const LAST_USABLE: i64 = 135235 // LAST_LBA - GPT_ARR_SEC - 1 == VOL2_LBA+VOL_SEC-1 (exact fit) |
| 59 | const VOL_BASE: i64 = 1048576 // PART_LBA*512 |
| 60 | const FSINFO_OFF: i64 = 1049088 // VOL_BASE + 512 |
| 61 | const BKBOOT_OFF: i64 = 1051648 // VOL_BASE + 6*512 |
| 62 | const FAT1_OFF: i64 = 1064960 // VOL_BASE + RESV*512 |
| 63 | const FAT2_OFF: i64 = 1327616 // VOL_BASE + (RESV+FATSZ)*512 |
| 64 | const DATA_BASE: i64 = 1590272 // VOL_BASE + (RESV+NFAT*FATSZ)*512 (data cluster 2 starts here) |
| 67 | const CL_ROOT: i64 = 2 |
| 68 | const CL_EFI: i64 = 3 |
| 69 | const CL_BOOT: i64 = 4 |
| 70 | const CL_FILE: i64 = 5 |
functions
| 72 | func iw8(img: *u8, off: i64, v: i64) -> i64 { img[off] = (v & 0xff) as u8; return 0 } |
| 73 | func iw16(img: *u8, off: i64, v: i64) -> i64 { img[off] = (v & 0xff) as u8; img[off+1] = ((v >> 8) & 0xff) as u8; return 0 } |
| 74 | func iw32(img: *u8, off: i64, v: i64) -> i64 |
| 78 | func ir32(img: *u8, off: i64) -> i64 called by 1: main |
| 81 | func istr(img: *u8, off: i64, s: *u8, n: i64) -> i64 { // copy exactly n bytes of s (space-padded literal) |
| 86 | func cluster_off(clus: i64) -> i64 { return DATA_BASE + (clus - 2) * SEC } called by 1: main |
| 91 | func gpt_crc32(b: *u8, off: i64, n: i64) -> i64 |
| 108 | func iw64(img: *u8, off: i64, v: i64) -> i64 { iw32(img, off, v & 0xFFFFFFFF); iw32(img, off + 4, (v >> 32) & 0xFFFFFFFF); return 0 } |
| 111 | func esp_guid_b(i: i64) -> i64 called by 1: main |
| 123 | func data_guid_b(i: i64) -> i64 called by 1: main |
| 129 | func part2_guid_b(i: i64) -> i64 { return (0x61 + i * 13) & 0xff } called by 1: main |
| 130 | func disk_guid_b(i: i64) -> i64 { return (0x4E + i * 7) & 0xff } called by 1: wr_gpt_hdr |
| 131 | func part_guid_b(i: i64) -> i64 { return (0x53 + i * 11) & 0xff } called by 1: main |
| 136 | func wr_gpt_hdr(img: *u8, hdr_off: i64, my_lba: i64, alt_lba: i64, arr_lba: i64, arr_crc: i64) -> i64 |
| 164 | func v_fat1(vb: i64) -> i64 { return vb + RESV * SEC } called by 1: fat_set_at |
| 165 | func v_fat2(vb: i64) -> i64 { return vb + (RESV + FATSZ) * SEC } called by 1: fat_set_at |
| 166 | func v_data(vb: i64) -> i64 { return vb + (RESV + NFAT * FATSZ) * SEC } called by 1: v_clus |
| 167 | func v_clus(vb: i64, clus: i64) -> i64 { return v_data(vb) + (clus - 2) * SEC } |
| 168 | func fat_set_at(img: *u8, vb: i64, clus: i64, val: i64) -> i64 |
| 173 | func fat_set(img: *u8, clus: i64, val: i64) -> i64 { return fat_set_at(img, VOL_BASE, clus, val) } |
| 176 | func wdir(img: *u8, off: i64, name: *u8, attr: i64, clus: i64, size: i64) -> i64 |
| 185 | func wr_bpb(img: *u8, base: i64) -> i64 |
| 215 | func p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 216 | func 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 } |
| 217 | func fn(fd: i64, v: i64) -> i64 |
| 226 | func main(argc: i64, argv: *i64) -> i64 |