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}