code wiki / _hdl_build / nx_boot_uefi_memmap.nx

nx_boot_uefi_memmap.nx source

↩ module page · 214 lines · 11790 B

1// nx_boot_uefi_memmap.nx -- NOS-R0.2 of the NISHI OS ladder: the OS calls UEFI BootServices. 2// 3// Extends the auto-discovery seed (R0.1): the emitted subsystem-10 EFI_APPLICATION now INVOKES a 4// real UEFI firmware FUNCTION -- BootServices->GetMemoryMap -- using the full MS-x64 ABI 5// (rcx/rdx/r8/r9 + a 5th argument on the stack at [rsp+0x20]). GetMemoryMap is THE call an 6// installer uses to read the machine's RAM layout ("where can I install"). This rung proves the 7// call MECHANISM (reaching BootServices, passing 5 args, the firmware function returning, and 8// continuing) by printing a fixed "RAM-MAP-READ" confirmation after the call. Reading + printing 9// the returned map size (number formatting) is the next rung, NOS-R0.3. 10// 11// Entry ABI (MS x64): RCX=ImageHandle, RDX=SystemTable*. RSI=SystemTable, RDI=ConOut kept across 12// calls. GetMemoryMap(rcx=&MapSize, rdx=MapBuf(NULL), r8=&MapKey, r9=&DescSize, [rsp+0x20]=&DescVer). 13// SystemTable: +0x40 ConOut, +0x60 BootServices. BootServices: +0x38 GetMemoryMap. 14// Scratch arg buffers live in an RWX section (firmware writes the required size into *MapSize). 15// 16// Build (sovereign): ./_offc/nx_sov_build_run.elf nx_boot_uefi_memmap (nx_cc->nxasm, no gcc) 17// Self-gate: byte-reproducible + structural (subsystem=10, entry, the `mov rax,[rsi+0x60]` + 18// `call [rax+0x38]` GetMemoryMap opcodes present) + tamper (subsystem->3 rejects). 19// Exec-proof: nx_emu_uefi models BootServices->GetMemoryMap as a hook -> confirms the call fires 20// and "RAM-MAP-READ" prints (sovereign, no qemu/laptop). 21// Sovereign: syscalls only, no gcc/.sh. license_tier: ORIGINAL 22import "nx_syscalls.nx" 23const PE_MAGIC_4096: i64 = 4096 24 25const PE_FILE_SIZE: i64 = 0x400 26const PE_MACHINE_AMD64: i64 = 0x8664 27const PE_OH_MAGIC_PEPLUS: i64 = 0x020B 28const PE_SUBSYSTEM_EFI_APP: i64 = 10 29const PE_CHAR_EXEC: i64 = 0x0002 30const PE_CHAR_LARGE_ADDR: i64 = 0x0020 31const PE_SECT_CODE_RWX: i64 = 0xE0000020 // CODE|EXECUTE|READ|WRITE (scratch is written by firmware) 32 33const FOFF_PE_SIG: i64 = 0x80 34const FOFF_COFF: i64 = 0x84 35const FOFF_OPT: i64 = 0x98 36const FOFF_SECT_TBL: i64 = 0x188 37const FOFF_TEXT: i64 = 0x200 38const RVA_TEXT: i64 = 0x1000 39const OPT_SUBSYS: i64 = 0x98 + 68 40const OPT_ENTRY: i64 = 0x98 + 16 41const IMG_BASE: i64 = 0x10000000 42const TEXT_VSIZE: i64 = 0x90 43 44func _w8(buf: *u8, off: i64, v: i64) -> i64 { buf[off] = (v & 0xff) as u8; return off + 1 } 45func _w16(buf: *u8, off: i64, v: i64) -> i64 { _w8(buf, off, v); _w8(buf, off + 1, v >> 8); return off + 2 } 46func _w32(buf: *u8, off: i64, v: i64) -> i64 { 47 _w8(buf, off, v); _w8(buf, off + 1, v >> 8); _w8(buf, off + 2, v >> 16); _w8(buf, off + 3, v >> 24) 48 return off + 4 49} 50func _w64(buf: *u8, off: i64, v: i64) -> i64 { _w32(buf, off, v); _w32(buf, off + 4, v >> 32); return off + 8 } 51func _r16(buf: *u8, off: i64) -> i64 { return (buf[off] as i64) | ((buf[off + 1] as i64) << 8) } 52func _r32(buf: *u8, off: i64) -> i64 { 53 return (buf[off] as i64) | ((buf[off + 1] as i64) << 8) | ((buf[off + 2] as i64) << 16) | ((buf[off + 3] as i64) << 24) 54} 55 56func uefi_emit(buf: *u8) -> i64 { 57 _w16(buf, 0, 0x5A4D) 58 _w32(buf, 0x3C, FOFF_PE_SIG) 59 _w32(buf, FOFF_PE_SIG, 0x00004550) 60 61 _w16(buf, FOFF_COFF + 0, PE_MACHINE_AMD64) 62 _w16(buf, FOFF_COFF + 2, 1) 63 _w16(buf, FOFF_COFF + 16, 0xF0) 64 _w16(buf, FOFF_COFF + 18, PE_CHAR_EXEC | PE_CHAR_LARGE_ADDR) 65 66 _w16(buf, FOFF_OPT + 0, PE_OH_MAGIC_PEPLUS) 67 _w8(buf, FOFF_OPT + 2, 1) 68 _w32(buf, FOFF_OPT + 4, 0x200) 69 _w32(buf, FOFF_OPT + 16, RVA_TEXT) 70 _w32(buf, FOFF_OPT + 20, RVA_TEXT) 71 _w64(buf, FOFF_OPT + 24, IMG_BASE) 72 _w32(buf, FOFF_OPT + 32, 0x1000) 73 _w32(buf, FOFF_OPT + 36, 0x200) 74 _w32(buf, FOFF_OPT + 56, 0x2000) 75 _w32(buf, FOFF_OPT + 60, 0x200) 76 _w16(buf, FOFF_OPT + 68, PE_SUBSYSTEM_EFI_APP) 77 _w64(buf, FOFF_OPT + 72, 0x100000) 78 _w64(buf, FOFF_OPT + 80, 0x1000) 79 _w64(buf, FOFF_OPT + 88, 0x100000) 80 _w64(buf, FOFF_OPT + 96, 0x1000) 81 _w32(buf, FOFF_OPT + 108, 16) 82 83 _w8(buf, FOFF_SECT_TBL + 0, 46); _w8(buf, FOFF_SECT_TBL + 1, 116); _w8(buf, FOFF_SECT_TBL + 2, 101) 84 _w8(buf, FOFF_SECT_TBL + 3, 120); _w8(buf, FOFF_SECT_TBL + 4, 116) 85 _w32(buf, FOFF_SECT_TBL + 8, TEXT_VSIZE) 86 _w32(buf, FOFF_SECT_TBL + 12, RVA_TEXT) 87 _w32(buf, FOFF_SECT_TBL + 16, 0x200) 88 _w32(buf, FOFF_SECT_TBL + 20, FOFF_TEXT) 89 _w32(buf, FOFF_SECT_TBL + 36, PE_SECT_CODE_RWX) 90 91 // ----- .text: PIC entry that calls BootServices->GetMemoryMap then prints confirmation ----- 92 // string strOK @ .text+0x4D (RVA 0x104D); scratch: MapSize@0x70 MapKey@0x78 DescSize@0x80 DescVer@0x88 93 var o: i64 = FOFF_TEXT 94 o = _w8(buf, o, 0x56) // push rsi 95 o = _w8(buf, o, 0x57) // push rdi 96 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xD6) // mov rsi,rdx (SystemTable) 97 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8B); o = _w8(buf, o, 0x7E); o = _w8(buf, o, 0x40) // mov rdi,[rsi+0x40] (ConOut) 98 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xEC); o = _w8(buf, o, 0x38) // sub rsp,0x38 99 // 5th arg: lea rax,[rip+DescVer]; mov [rsp+0x20],rax 100 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x05); o = _w32(buf, o, 0x74) // lea rax,[rip+0x74] -> DescVer 101 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0x44); o = _w8(buf, o, 0x24); o = _w8(buf, o, 0x20) // mov [rsp+0x20],rax 102 // rcx=&MapSize, rdx=NULL, r8=&MapKey, r9=&DescSize 103 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x0D); o = _w32(buf, o, 0x50) // lea rcx,[rip+0x50] -> MapSize 104 o = _w8(buf, o, 0x31); o = _w8(buf, o, 0xD2) // xor edx,edx (MapBuf = NULL) 105 o = _w8(buf, o, 0x4C); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x05); o = _w32(buf, o, 0x4F) // lea r8,[rip+0x4F] -> MapKey 106 o = _w8(buf, o, 0x4C); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x0D); o = _w32(buf, o, 0x50) // lea r9,[rip+0x50] -> DescSize 107 // rax = BootServices; call GetMemoryMap 108 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8B); o = _w8(buf, o, 0x46); o = _w8(buf, o, 0x60) // mov rax,[rsi+0x60] (BootServices) 109 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x50); o = _w8(buf, o, 0x38) // call [rax+0x38] (GetMemoryMap) 110 // print "RAM-MAP-READ\r\n" 111 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xF9) // mov rcx,rdi 112 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x15); o = _w32(buf, o, 0x0C) // lea rdx,[rip+0x0C] -> strOK 113 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x08) // call [rdi+0x08] 114 // epilogue 115 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xC4); o = _w8(buf, o, 0x38) // add rsp,0x38 116 o = _w8(buf, o, 0x5F) // pop rdi 117 o = _w8(buf, o, 0x5E) // pop rsi 118 o = _w8(buf, o, 0x31); o = _w8(buf, o, 0xC0) // xor eax,eax 119 o = _w8(buf, o, 0xC3) // ret (ends at .text 0x4D) 120 // strOK @ .text+0x4D : "RAM-MAP-READ\r\n\0" 121 o = _w16(buf, o, 0x52); o = _w16(buf, o, 0x41); o = _w16(buf, o, 0x4D); o = _w16(buf, o, 0x2D) // R A M - 122 o = _w16(buf, o, 0x4D); o = _w16(buf, o, 0x41); o = _w16(buf, o, 0x50); o = _w16(buf, o, 0x2D) // M A P - 123 o = _w16(buf, o, 0x52); o = _w16(buf, o, 0x45); o = _w16(buf, o, 0x41); o = _w16(buf, o, 0x44) // R E A D 124 o = _w16(buf, o, 0x0D); o = _w16(buf, o, 0x0A); o = _w16(buf, o, 0x00) // CR LF NUL 125 // scratch (zero-init) occupies .text 0x70..0x8F -- left as zeros (firmware writes MapSize) 126 127 return PE_FILE_SIZE 128} 129 130func uefi_verify(buf: *u8) -> i64 { 131 if buf[0] != (0x4D as u8) { return 0 } 132 if buf[1] != (0x5A as u8) { return 0 } 133 if _r32(buf, 0x3C) != FOFF_PE_SIG { return 0 } 134 if _r32(buf, FOFF_PE_SIG) != 0x00004550 { return 0 } 135 if _r16(buf, FOFF_COFF) != PE_MACHINE_AMD64 { return 0 } 136 if _r16(buf, FOFF_OPT) != PE_OH_MAGIC_PEPLUS { return 0 } 137 if _r16(buf, OPT_SUBSYS) != PE_SUBSYSTEM_EFI_APP { return 0 } 138 if _r32(buf, OPT_ENTRY) != RVA_TEXT { return 0 } 139 if buf[FOFF_TEXT] != (0x56 as u8) { return 0 } // entry[0] = push rsi 140 // BootServices load `mov rax,[rsi+0x60]` = 48 8B 46 60 at .text+0x30 141 if buf[FOFF_TEXT + 0x30] != (0x48 as u8) { return 0 } 142 if buf[FOFF_TEXT + 0x31] != (0x8B as u8) { return 0 } 143 if buf[FOFF_TEXT + 0x32] != (0x46 as u8) { return 0 } 144 if buf[FOFF_TEXT + 0x33] != (0x60 as u8) { return 0 } 145 // GetMemoryMap call `call [rax+0x38]` = FF 50 38 at .text+0x34 146 if buf[FOFF_TEXT + 0x34] != (0xFF as u8) { return 0 } 147 if buf[FOFF_TEXT + 0x35] != (0x50 as u8) { return 0 } 148 if buf[FOFF_TEXT + 0x36] != (0x38 as u8) { return 0 } 149 return 1 150} 151 152func 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 } 153func 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 } 154func u_fn(fd: i64, v: i64) -> i64 { 155 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 156 let t: *u8 = sys_mmap(28); var k: i64 = 0 157 if m == 0 { t[0] = 48; k = 1 } 158 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 159 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 160 sys_write(fd, bb, k); return 0 161} 162func u_log(sz: i64, repro: i64, structural: i64, tamper: i64, verdict: *u8) -> i64 { 163 let lfd: i64 = sys_openat_append("knowledge/status/nishi_os.log" as *u8, 0x1a4) 164 if lfd < 0 { return 0 - 1 } 165 u_fp(lfd, "NOSR0_2 name=nx_boot_uefi_memmap.efi subsystem=10 climate=x86_64-uefi calls=BootServices.GetMemoryMap bytes=" as *u8); u_fn(lfd, sz) 166 u_fp(lfd, " repro=" as *u8); u_fn(lfd, repro) 167 u_fp(lfd, " structural=" as *u8); u_fn(lfd, structural) 168 u_fp(lfd, " tamper_caught=" as *u8); u_fn(lfd, tamper) 169 u_fp(lfd, " scope=emit-proven verdict=" as *u8); u_fp(lfd, verdict); u_fp(lfd, "\n" as *u8) 170 sys_close(lfd); return 0 171} 172 173func main(argc: i64, argv: *i64) -> i64 { 174 let buf: *u8 = sys_mmap(PE_MAGIC_4096) 175 let buf2: *u8 = sys_mmap(PE_MAGIC_4096) 176 let sz: i64 = uefi_emit(buf) 177 let sz2: i64 = uefi_emit(buf2) 178 179 var repro: i64 = 1 180 if sz != sz2 { repro = 0 } 181 var i: i64 = 0 182 while i < sz { if buf[i] != buf2[i] { repro = 0 } i = i + 1 } 183 184 let structural: i64 = uefi_verify(buf) 185 186 _w16(buf2, OPT_SUBSYS, 3) 187 var tamper_caught: i64 = 0 188 if uefi_verify(buf2) == 0 { tamper_caught = 1 } 189 190 var green: i64 = 0 191 if repro == 1 { if structural == 1 { if tamper_caught == 1 { green = 1 } } } 192 193 if green == 1 { 194 let ofd: i64 = sys_openat_wr("_offc/nx_boot_uefi_memmap.efi" as *u8, 0x1a4) 195 if ofd < 0 { 196 u_p("NOS-R0.2 RED: cannot write _offc/nx_boot_uefi_memmap.efi\n" as *u8) 197 u_log(sz, repro, structural, tamper_caught, "RED" as *u8) 198 sys_exit(1); return 1 199 } 200 sys_write(ofd, buf, sz) 201 sys_close(ofd) 202 u_p("NOS-R0.2 GREEN: authored _offc/nx_boot_uefi_memmap.efi (calls BootServices->GetMemoryMap) bytes=" as *u8) 203 u_fn(1, sz) 204 u_p(" repro+structural(+GetMemoryMap call opcodes)+tamper all pass\n" as *u8) 205 u_log(sz, repro, structural, tamper_caught, "GREEN" as *u8) 206 sys_exit(0); return 0 207 } 208 209 u_p("NOS-R0.2 RED: repro=" as *u8); u_fn(1, repro) 210 u_p(" structural=" as *u8); u_fn(1, structural) 211 u_p(" tamper_caught=" as *u8); u_fn(1, tamper_caught); u_p("\n" as *u8) 212 u_log(sz, repro, structural, tamper_caught, "RED" as *u8) 213 sys_exit(1); return 1 214}