code wiki / _hdl_build / nx_boot_uefi_probe.nx

nx_boot_uefi_probe.nx source

↩ module page · 232 lines · 13131 B

1// nx_boot_uefi_probe.nx -- NOS-R0.1 of the NISHI OS ladder: the UEFI auto-discovery seed. 2// 3// Extends NOS-R0 (nx_boot_uefi): the emitted subsystem-10 EFI_APPLICATION now READS THE 4// MACHINE BACK TO US. Its position-independent entry walks the UEFI SystemTable and prints, 5// via ConOut->OutputString: (1) the "NISHI" banner, then (2) the firmware's OWN vendor 6// string (SystemTable->FirmwareVendor @ +0x18) -- real, unfakeable hardware identity read off 7// the unknown laptop. That readback is the seed of "auto-discover the machine, then install": 8// the OS interrogating firmware instead of being told the specs. GetMemoryMap (the RAM-layout 9// read an installer needs) is the next rung, NOS-R0.2. 10// 11// Same sovereign PE32+ wrapper as nx_boot_uefi (subsystem 10, no imports, PIC entry); only the 12// .text logic grows. Entry ABI (MS x64): RCX=ImageHandle, RDX=SystemTable*. Nonvolatile regs 13// (RSI=SystemTable, RDI=ConOut) survive the firmware calls; pushed/popped per ABI. 14// SystemTable: +0x18 FirmwareVendor(CHAR16*), +0x40 ConOut(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*) 15// ConOut: +0x08 OutputString(This, CHAR16*) 16// 17// Build (sovereign): ./_offc/nx_sov_build_run.elf nx_boot_uefi_probe (nx_cc->nxasm, no gcc) 18// Self-gate (no mocks): byte-reproducible + structural (machine=0x8664, subsystem=10, PE/MZ, 19// entry=0x1000, entry[0]=push rsi, and the ConOut-read opcodes `48 8B 7E 40` present = 20// proves the discovery read is wired) + tamper liar-kill (subsystem->3 must reject). 21// Scope (honest): EMIT-proven. BOOT/READ-proven (real firmware prints its vendor) = on the 22// laptop USB, after NOS-R0 boots clean. VERDICT log -> knowledge/status/nishi_os.log. 23// Sovereign: syscalls only, no gcc/.sh. license_tier: ORIGINAL 24import "nx_syscalls.nx" 25const PE_MAGIC_4096: i64 = 4096 26 27// ===== PE/COFF + UEFI constants (mirror nx_boot_uefi) =========================== 28const PE_FILE_SIZE: i64 = 0x400 29const PE_MACHINE_AMD64: i64 = 0x8664 30const PE_OH_MAGIC_PEPLUS: i64 = 0x020B 31const PE_SUBSYSTEM_EFI_APP: i64 = 10 32const PE_CHAR_EXEC: i64 = 0x0002 33const PE_CHAR_LARGE_ADDR: i64 = 0x0020 34const PE_SECT_CODE_X_R: i64 = 0x60000020 35 36const FOFF_PE_SIG: i64 = 0x80 37const FOFF_COFF: i64 = 0x84 38const FOFF_OPT: i64 = 0x98 39const FOFF_SECT_TBL: i64 = 0x188 40const FOFF_TEXT: i64 = 0x200 41const RVA_TEXT: i64 = 0x1000 42const OPT_SUBSYS: i64 = 0x98 + 68 43const OPT_ENTRY: i64 = 0x98 + 16 44const IMG_BASE: i64 = 0x10000000 45const TEXT_VSIZE: i64 = 0x67 // 71 bytes code (ends 0x46) + 3 UTF-16 strings (0x47..0x66) 46 47// ===== little-endian byte writers / readers ===================================== 48func _w8(buf: *u8, off: i64, v: i64) -> i64 { buf[off] = (v & 0xff) as u8; return off + 1 } 49func _w16(buf: *u8, off: i64, v: i64) -> i64 { _w8(buf, off, v); _w8(buf, off + 1, v >> 8); return off + 2 } 50func _w32(buf: *u8, off: i64, v: i64) -> i64 { 51 _w8(buf, off, v); _w8(buf, off + 1, v >> 8); _w8(buf, off + 2, v >> 16); _w8(buf, off + 3, v >> 24) 52 return off + 4 53} 54func _w64(buf: *u8, off: i64, v: i64) -> i64 { _w32(buf, off, v); _w32(buf, off + 4, v >> 32); return off + 8 } 55func _r16(buf: *u8, off: i64) -> i64 { return (buf[off] as i64) | ((buf[off + 1] as i64) << 8) } 56func _r32(buf: *u8, off: i64) -> i64 { 57 return (buf[off] as i64) | ((buf[off + 1] as i64) << 8) | ((buf[off + 2] as i64) << 16) | ((buf[off + 3] as i64) << 24) 58} 59 60// ===== the EFI image author ===================================================== 61func uefi_emit(buf: *u8) -> i64 { 62 // ----- DOS header + PE sig ----- 63 _w16(buf, 0, 0x5A4D) // 'MZ' 64 _w32(buf, 0x3C, FOFF_PE_SIG) 65 _w32(buf, FOFF_PE_SIG, 0x00004550) // 'PE\0\0' 66 67 // ----- COFF header ----- 68 _w16(buf, FOFF_COFF + 0, PE_MACHINE_AMD64) 69 _w16(buf, FOFF_COFF + 2, 1) 70 _w16(buf, FOFF_COFF + 16, 0xF0) 71 _w16(buf, FOFF_COFF + 18, PE_CHAR_EXEC | PE_CHAR_LARGE_ADDR) 72 73 // ----- Optional header (PE32+) ----- 74 _w16(buf, FOFF_OPT + 0, PE_OH_MAGIC_PEPLUS) 75 _w8(buf, FOFF_OPT + 2, 1) 76 _w32(buf, FOFF_OPT + 4, 0x200) // SizeOfCode 77 _w32(buf, FOFF_OPT + 16, RVA_TEXT) // AddressOfEntryPoint 78 _w32(buf, FOFF_OPT + 20, RVA_TEXT) // BaseOfCode 79 _w64(buf, FOFF_OPT + 24, IMG_BASE) // ImageBase 80 _w32(buf, FOFF_OPT + 32, 0x1000) // SectionAlignment 81 _w32(buf, FOFF_OPT + 36, 0x200) // FileAlignment 82 _w32(buf, FOFF_OPT + 56, 0x2000) // SizeOfImage 83 _w32(buf, FOFF_OPT + 60, 0x200) // SizeOfHeaders 84 _w16(buf, FOFF_OPT + 68, PE_SUBSYSTEM_EFI_APP) // Subsystem = 10 85 _w64(buf, FOFF_OPT + 72, 0x100000) // SizeOfStackReserve 86 _w64(buf, FOFF_OPT + 80, 0x1000) // SizeOfStackCommit 87 _w64(buf, FOFF_OPT + 88, 0x100000) // SizeOfHeapReserve 88 _w64(buf, FOFF_OPT + 96, 0x1000) // SizeOfHeapCommit 89 _w32(buf, FOFF_OPT + 108, 16) // NumberOfRvaAndSizes 90 91 // ----- section header: .text ----- 92 _w8(buf, FOFF_SECT_TBL + 0, 46) // '.' 93 _w8(buf, FOFF_SECT_TBL + 1, 116) // 't' 94 _w8(buf, FOFF_SECT_TBL + 2, 101) // 'e' 95 _w8(buf, FOFF_SECT_TBL + 3, 120) // 'x' 96 _w8(buf, FOFF_SECT_TBL + 4, 116) // 't' 97 _w32(buf, FOFF_SECT_TBL + 8, TEXT_VSIZE) // VirtualSize 98 _w32(buf, FOFF_SECT_TBL + 12, RVA_TEXT) 99 _w32(buf, FOFF_SECT_TBL + 16, 0x200) // SizeOfRawData 100 _w32(buf, FOFF_SECT_TBL + 20, FOFF_TEXT) // PointerToRawData 101 _w32(buf, FOFF_SECT_TBL + 36, PE_SECT_CODE_X_R) 102 103 // ----- .text: PIC UEFI entry that reads + prints the firmware vendor ----- 104 var o: i64 = FOFF_TEXT 105 // prologue 106 o = _w8(buf, o, 0x56) // push rsi 107 o = _w8(buf, o, 0x57) // push rdi 108 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xD6) // mov rsi,rdx (RSI = SystemTable) 109 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8B); o = _w8(buf, o, 0x7E); o = _w8(buf, o, 0x40) // mov rdi,[rsi+0x40] (RDI = ConOut) 110 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xEC); o = _w8(buf, o, 0x28) // sub rsp,0x28 111 // P1: OutputString(ConOut, &banner) 112 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xF9) // mov rcx,rdi 113 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x15); o = _w32(buf, o, 0x30) // lea rdx,[rip+0x30] -> strA @0x47 114 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x08) // call [rdi+8] 115 // P2: OutputString(ConOut, &label "FW: ") 116 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xF9) // mov rcx,rdi 117 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x15); o = _w32(buf, o, 0x33) // lea rdx,[rip+0x33] -> strB @0x57 118 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x08) // call [rdi+8] 119 // P3: OutputString(ConOut, SystemTable->FirmwareVendor) <-- the auto-discovery read 120 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xF9) // mov rcx,rdi 121 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8B); o = _w8(buf, o, 0x56); o = _w8(buf, o, 0x18) // mov rdx,[rsi+0x18] (FirmwareVendor) 122 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x08) // call [rdi+8] 123 // P4: OutputString(ConOut, &newline) 124 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xF9) // mov rcx,rdi 125 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x15); o = _w32(buf, o, 0x26) // lea rdx,[rip+0x26] -> strC @0x61 126 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x08) // call [rdi+8] 127 // epilogue 128 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xC4); o = _w8(buf, o, 0x28) // add rsp,0x28 129 o = _w8(buf, o, 0x5F) // pop rdi 130 o = _w8(buf, o, 0x5E) // pop rsi 131 o = _w8(buf, o, 0x31); o = _w8(buf, o, 0xC0) // xor eax,eax (EFI_SUCCESS) 132 o = _w8(buf, o, 0xC3) // ret 133 // strA @ .text+0x47 : "NISHI\r\n\0" (immediately after ret at 0x46) 134 o = _w16(buf, o, 0x4E); o = _w16(buf, o, 0x49); o = _w16(buf, o, 0x53) 135 o = _w16(buf, o, 0x48); o = _w16(buf, o, 0x49) 136 o = _w16(buf, o, 0x0D); o = _w16(buf, o, 0x0A); o = _w16(buf, o, 0x00) 137 // strB @ .text+0x57 : "FW: \0" 138 o = _w16(buf, o, 0x46); o = _w16(buf, o, 0x57); o = _w16(buf, o, 0x3A); o = _w16(buf, o, 0x20); o = _w16(buf, o, 0x00) 139 // strC @ .text+0x61 : "\r\n\0" 140 o = _w16(buf, o, 0x0D); o = _w16(buf, o, 0x0A); o = _w16(buf, o, 0x00) 141 142 return PE_FILE_SIZE 143} 144 145// ===== structural self-gate ===================================================== 146func uefi_verify(buf: *u8) -> i64 { 147 if buf[0] != (0x4D as u8) { return 0 } 148 if buf[1] != (0x5A as u8) { return 0 } 149 if _r32(buf, 0x3C) != FOFF_PE_SIG { return 0 } 150 if _r32(buf, FOFF_PE_SIG) != 0x00004550 { return 0 } 151 if _r16(buf, FOFF_COFF) != PE_MACHINE_AMD64 { return 0 } 152 if _r16(buf, FOFF_OPT) != PE_OH_MAGIC_PEPLUS { return 0 } 153 if _r16(buf, OPT_SUBSYS) != PE_SUBSYSTEM_EFI_APP { return 0 } 154 if _r32(buf, OPT_ENTRY) != RVA_TEXT { return 0 } 155 if buf[FOFF_TEXT] != (0x56 as u8) { return 0 } // entry[0] = push rsi 156 // the ConOut read `mov rdi,[rsi+0x40]` at .text+0x05 = 48 8B 7E 40 (discovery wiring proof) 157 if buf[FOFF_TEXT + 5] != (0x48 as u8) { return 0 } 158 if buf[FOFF_TEXT + 6] != (0x8B as u8) { return 0 } 159 if buf[FOFF_TEXT + 7] != (0x7E as u8) { return 0 } 160 if buf[FOFF_TEXT + 8] != (0x40 as u8) { return 0 } 161 // the FirmwareVendor read `mov rdx,[rsi+0x18]` = 48 8B 56 18 (the auto-discovery read itself) 162 if buf[FOFF_TEXT + 0x2A] != (0x48 as u8) { return 0 } 163 if buf[FOFF_TEXT + 0x2B] != (0x8B as u8) { return 0 } 164 if buf[FOFF_TEXT + 0x2C] != (0x56 as u8) { return 0 } 165 if buf[FOFF_TEXT + 0x2D] != (0x18 as u8) { return 0 } 166 return 1 167} 168 169// ===== I/O + log helpers ======================================================== 170func u_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 171func u_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 } 172func u_fn(fd: i64, v: i64) -> i64 { 173 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 174 let t: *u8 = sys_mmap(28); var k: i64 = 0 175 if m == 0 { t[0] = 48; k = 1 } 176 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 177 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 178 sys_write(fd, bb, k); return 0 179} 180func u_log(sz: i64, repro: i64, structural: i64, tamper: i64, verdict: *u8) -> i64 { 181 let lfd: i64 = sys_openat_append("knowledge/status/nishi_os.log" as *u8, 0x1a4) 182 if lfd < 0 { return 0 - 1 } 183 u_fp(lfd, "NOSR0_1 name=nx_boot_uefi_probe.efi subsystem=10 climate=x86_64-uefi reads=firmware-vendor bytes=" as *u8); u_fn(lfd, sz) 184 u_fp(lfd, " repro=" as *u8); u_fn(lfd, repro) 185 u_fp(lfd, " structural=" as *u8); u_fn(lfd, structural) 186 u_fp(lfd, " tamper_caught=" as *u8); u_fn(lfd, tamper) 187 u_fp(lfd, " scope=emit-proven(read-proof=on-laptop) verdict=" as *u8); u_fp(lfd, verdict); u_fp(lfd, "\n" as *u8) 188 sys_close(lfd); return 0 189} 190 191func main(argc: i64, argv: *i64) -> i64 { 192 let buf: *u8 = sys_mmap(PE_MAGIC_4096) 193 let buf2: *u8 = sys_mmap(PE_MAGIC_4096) 194 let sz: i64 = uefi_emit(buf) 195 let sz2: i64 = uefi_emit(buf2) 196 197 var repro: i64 = 1 198 if sz != sz2 { repro = 0 } 199 var i: i64 = 0 200 while i < sz { if buf[i] != buf2[i] { repro = 0 } i = i + 1 } 201 202 let structural: i64 = uefi_verify(buf) 203 204 _w16(buf2, OPT_SUBSYS, 3) 205 var tamper_caught: i64 = 0 206 if uefi_verify(buf2) == 0 { tamper_caught = 1 } 207 208 var green: i64 = 0 209 if repro == 1 { if structural == 1 { if tamper_caught == 1 { green = 1 } } } 210 211 if green == 1 { 212 let ofd: i64 = sys_openat_wr("_offc/nx_boot_uefi_probe.efi" as *u8, 0x1a4) 213 if ofd < 0 { 214 u_p("NOS-R0.1 RED: cannot write _offc/nx_boot_uefi_probe.efi\n" as *u8) 215 u_log(sz, repro, structural, tamper_caught, "RED" as *u8) 216 sys_exit(1); return 1 217 } 218 sys_write(ofd, buf, sz) 219 sys_close(ofd) 220 u_p("NOS-R0.1 GREEN: authored _offc/nx_boot_uefi_probe.efi (reads+prints firmware vendor) bytes=" as *u8) 221 u_fn(1, sz) 222 u_p(" repro+structural(+ConOut/vendor-read opcodes)+tamper all pass\n" as *u8) 223 u_log(sz, repro, structural, tamper_caught, "GREEN" as *u8) 224 sys_exit(0); return 0 225 } 226 227 u_p("NOS-R0.1 RED: repro=" as *u8); u_fn(1, repro) 228 u_p(" structural=" as *u8); u_fn(1, structural) 229 u_p(" tamper_caught=" as *u8); u_fn(1, tamper_caught); u_p("\n" as *u8) 230 u_log(sz, repro, structural, tamper_caught, "RED" as *u8) 231 sys_exit(1); return 1 232}