code wiki / _hdl_build / nx_boot_uefi_ramsize.nx
nx_boot_uefi_ramsize.nx source
↩ module page · 200 lines · 13519 B
1// nx_boot_uefi_ramsize.nx -- NOS-R0.3: DISPLAY a discovered hardware value (the RAM map size).
2//
3// Extends R0.2 (the GetMemoryMap call): after calling BootServices->GetMemoryMap, the emitted
4// EFI app now READS the returned MapSize and PRINTS it as hex -- the first rung that shows a real
5// hardware value the OS discovered from the machine. This unlocks an installer UI ("this box has
6// N bytes of RAM, install here"). The hex render is a real LOOP in machine code (8 nibbles MSB
7// first, shr-by-CL + cmp + jcc), which is exactly why the exec-harness grew loop support.
8//
9// Entry ABI (MS x64): RCX=ImageHandle, RDX=SystemTable*. RSI=SystemTable, RDI=ConOut, RBX=hex
10// write pointer (all callee-saved across the firmware call). Prints "RAM:0x" + 8 hex digits + CRLF.
11// GetMemoryMap writes the required map size into *MapSize; we load it and format it.
12// Scratch + hex buffer live in an RWX section (firmware writes MapSize; we write the hex chars).
13//
14// Build (sovereign): ./_offc/nx_sov_build_run.elf nx_boot_uefi_ramsize (nx_cc->nxasm, no gcc)
15// Exec-proof: nx_emu_uefi runs it (GetMemoryMap hook returns 0x1800) -> expect "RAM:0x00001800".
16// Self-gate: byte-reproducible + structural (subsystem=10, entry, GetMemoryMap call opcodes, the
17// shr-by-CL hex-loop opcode present) + tamper (subsystem->3 rejects).
18// Sovereign: syscalls only, no gcc/.sh. license_tier: ORIGINAL
19import "nx_syscalls.nx"
20const PE_MAGIC_4096: i64 = 4096
21
22const PE_FILE_SIZE: i64 = 0x400
23const PE_MACHINE_AMD64: i64 = 0x8664
24const PE_OH_MAGIC_PEPLUS: i64 = 0x020B
25const PE_SUBSYSTEM_EFI_APP: i64 = 10
26const PE_CHAR_EXEC: i64 = 0x0002
27const PE_CHAR_LARGE_ADDR: i64 = 0x0020
28const PE_SECT_CODE_RWX: i64 = 0xE0000020
29
30const FOFF_PE_SIG: i64 = 0x80
31const FOFF_COFF: i64 = 0x84
32const FOFF_OPT: i64 = 0x98
33const FOFF_SECT_TBL: i64 = 0x188
34const FOFF_TEXT: i64 = 0x200
35const RVA_TEXT: i64 = 0x1000
36const OPT_SUBSYS: i64 = 0x98 + 68
37const OPT_ENTRY: i64 = 0x98 + 16
38const IMG_BASE: i64 = 0x10000000
39const TEXT_VSIZE: i64 = 0x100
40
41func _w8(buf: *u8, off: i64, v: i64) -> i64 { buf[off] = (v & 0xff) as u8; return off + 1 }
42func _w16(buf: *u8, off: i64, v: i64) -> i64 { _w8(buf, off, v); _w8(buf, off + 1, v >> 8); return off + 2 }
43func _w32(buf: *u8, off: i64, v: i64) -> i64 {
44 _w8(buf, off, v); _w8(buf, off + 1, v >> 8); _w8(buf, off + 2, v >> 16); _w8(buf, off + 3, v >> 24)
45 return off + 4
46}
47func _w64(buf: *u8, off: i64, v: i64) -> i64 { _w32(buf, off, v); _w32(buf, off + 4, v >> 32); return off + 8 }
48func _r16(buf: *u8, off: i64) -> i64 { return (buf[off] as i64) | ((buf[off + 1] as i64) << 8) }
49func _r32(buf: *u8, off: i64) -> i64 {
50 return (buf[off] as i64) | ((buf[off + 1] as i64) << 8) | ((buf[off + 2] as i64) << 16) | ((buf[off + 3] as i64) << 24)
51}
52
53func uefi_emit(buf: *u8) -> i64 {
54 _w16(buf, 0, 0x5A4D); _w32(buf, 0x3C, FOFF_PE_SIG); _w32(buf, FOFF_PE_SIG, 0x00004550)
55 _w16(buf, FOFF_COFF + 0, PE_MACHINE_AMD64); _w16(buf, FOFF_COFF + 2, 1)
56 _w16(buf, FOFF_COFF + 16, 0xF0); _w16(buf, FOFF_COFF + 18, PE_CHAR_EXEC | PE_CHAR_LARGE_ADDR)
57 _w16(buf, FOFF_OPT + 0, PE_OH_MAGIC_PEPLUS); _w8(buf, FOFF_OPT + 2, 1)
58 _w32(buf, FOFF_OPT + 4, 0x200); _w32(buf, FOFF_OPT + 16, RVA_TEXT); _w32(buf, FOFF_OPT + 20, RVA_TEXT)
59 _w64(buf, FOFF_OPT + 24, IMG_BASE); _w32(buf, FOFF_OPT + 32, 0x1000); _w32(buf, FOFF_OPT + 36, 0x200)
60 _w32(buf, FOFF_OPT + 56, 0x2000); _w32(buf, FOFF_OPT + 60, 0x200)
61 _w16(buf, FOFF_OPT + 68, PE_SUBSYSTEM_EFI_APP)
62 _w64(buf, FOFF_OPT + 72, 0x100000); _w64(buf, FOFF_OPT + 80, 0x1000)
63 _w64(buf, FOFF_OPT + 88, 0x100000); _w64(buf, FOFF_OPT + 96, 0x1000); _w32(buf, FOFF_OPT + 108, 16)
64 _w8(buf, FOFF_SECT_TBL + 0, 46); _w8(buf, FOFF_SECT_TBL + 1, 116); _w8(buf, FOFF_SECT_TBL + 2, 101)
65 _w8(buf, FOFF_SECT_TBL + 3, 120); _w8(buf, FOFF_SECT_TBL + 4, 116)
66 _w32(buf, FOFF_SECT_TBL + 8, TEXT_VSIZE); _w32(buf, FOFF_SECT_TBL + 12, RVA_TEXT)
67 _w32(buf, FOFF_SECT_TBL + 16, 0x200); _w32(buf, FOFF_SECT_TBL + 20, FOFF_TEXT)
68 _w32(buf, FOFF_SECT_TBL + 36, PE_SECT_CODE_RWX)
69
70 // ----- .text: GetMemoryMap, then hex-print *MapSize -----
71 // data: strLabel@0xAC "RAM:0x", strNL@0xBA "\r\n", HexBuf@0xC0(32), MapSize@0xE0 MapKey@0xE8 DescSize@0xF0 DescVer@0xF8
72 var o: i64 = FOFF_TEXT
73 o = _w8(buf, o, 0x56); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x53) // push rsi; push rdi; push rbx
74 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xD6) // mov rsi,rdx
75 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8B); o = _w8(buf, o, 0x7E); o = _w8(buf, o, 0x40)// mov rdi,[rsi+0x40]
76 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xEC); o = _w8(buf, o, 0x40)// sub rsp,0x40
77 // GetMemoryMap(rcx=&MapSize, rdx=0, r8=&MapKey, r9=&DescSize, [rsp+0x20]=&DescVer)
78 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x05); o = _w32(buf, o, 0xE3)// lea rax,[rip+DescVer]
79 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
80 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x0D); o = _w32(buf, o, 0xBF)// lea rcx,[rip+MapSize]
81 o = _w8(buf, o, 0x31); o = _w8(buf, o, 0xD2) // xor edx,edx
82 o = _w8(buf, o, 0x4C); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x05); o = _w32(buf, o, 0xBE)// lea r8,[rip+MapKey]
83 o = _w8(buf, o, 0x4C); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x0D); o = _w32(buf, o, 0xBF)// lea r9,[rip+DescSize]
84 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8B); o = _w8(buf, o, 0x46); o = _w8(buf, o, 0x60)// mov rax,[rsi+0x60]
85 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x50); o = _w8(buf, o, 0x38) // call [rax+0x38]
86 // print "RAM:0x"
87 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xF9) // mov rcx,rdi
88 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x15); o = _w32(buf, o, 0x6A)// lea rdx,[rip+strLabel]
89 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x08) // call [rdi+8]
90 // rax = *MapSize
91 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x05); o = _w32(buf, o, 0x94)// lea rax,[rip+MapSize]
92 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8B); o = _w8(buf, o, 0x40); o = _w8(buf, o, 0x00)// mov rax,[rax+0]
93 // hex setup: rbx=&HexBuf, rcx=28 (shift)
94 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x1D); o = _w32(buf, o, 0x69)// lea rbx,[rip+HexBuf]
95 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0xC7); o = _w8(buf, o, 0xC1); o = _w32(buf, o, 0x1C)// mov rcx,28
96 // loop (RVA 0x105E): emit one hex digit per iteration, shift -= 4 until < 0
97 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xC2) // mov rdx,rax
98 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0xD3); o = _w8(buf, o, 0xEA) // shr rdx,cl
99 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xE2); o = _w8(buf, o, 0x0F)// and rdx,0xF
100 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xC2); o = _w8(buf, o, 0x30)// add rdx,0x30
101 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xFA); o = _w8(buf, o, 0x39)// cmp rdx,0x39
102 o = _w8(buf, o, 0x7E); o = _w8(buf, o, 0x04) // jle +4 (skip the A-F adjust)
103 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xC2); o = _w8(buf, o, 0x07)// add rdx,7
104 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0x53); o = _w8(buf, o, 0x00)// mov [rbx+0],rdx
105 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xC3); o = _w8(buf, o, 0x02)// add rbx,2
106 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xE9); o = _w8(buf, o, 0x04)// sub rcx,4
107 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xF9); o = _w8(buf, o, 0x00)// cmp rcx,0
108 o = _w8(buf, o, 0x7D); o = _w8(buf, o, 0xD6) // jge loop (rel -42)
109 // print HexBuf
110 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xF9) // mov rcx,rdi
111 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x15); o = _w32(buf, o, 0x2E)// lea rdx,[rip+HexBuf]
112 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x08) // call [rdi+8]
113 // print "\r\n"
114 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x89); o = _w8(buf, o, 0xF9) // mov rcx,rdi
115 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x8D); o = _w8(buf, o, 0x15); o = _w32(buf, o, 0x1B)// lea rdx,[rip+strNL]
116 o = _w8(buf, o, 0xFF); o = _w8(buf, o, 0x57); o = _w8(buf, o, 0x08) // call [rdi+8]
117 // epilogue
118 o = _w8(buf, o, 0x48); o = _w8(buf, o, 0x83); o = _w8(buf, o, 0xC4); o = _w8(buf, o, 0x40)// add rsp,0x40
119 o = _w8(buf, o, 0x5B); o = _w8(buf, o, 0x5F); o = _w8(buf, o, 0x5E) // pop rbx; pop rdi; pop rsi
120 o = _w8(buf, o, 0x31); o = _w8(buf, o, 0xC0); o = _w8(buf, o, 0xC3) // xor eax,eax; ret (ends 0xAC)
121 // strLabel @0xAC "RAM:0x\0"
122 o = _w16(buf, o, 0x52); o = _w16(buf, o, 0x41); o = _w16(buf, o, 0x4D); o = _w16(buf, o, 0x3A); o = _w16(buf, o, 0x30); o = _w16(buf, o, 0x78); o = _w16(buf, o, 0x00)
123 // strNL @0xBA "\r\n\0"
124 o = _w16(buf, o, 0x0D); o = _w16(buf, o, 0x0A); o = _w16(buf, o, 0x00)
125 // HexBuf @0xC0 (32B) + scratch @0xE0.. left zero
126 return PE_FILE_SIZE
127}
128
129func uefi_verify(buf: *u8) -> i64 {
130 if buf[0] != (0x4D as u8) { return 0 }
131 if buf[1] != (0x5A as u8) { return 0 }
132 if _r32(buf, 0x3C) != FOFF_PE_SIG { return 0 }
133 if _r32(buf, FOFF_PE_SIG) != 0x00004550 { return 0 }
134 if _r16(buf, FOFF_COFF) != PE_MACHINE_AMD64 { return 0 }
135 if _r16(buf, FOFF_OPT) != PE_OH_MAGIC_PEPLUS { return 0 }
136 if _r16(buf, OPT_SUBSYS) != PE_SUBSYSTEM_EFI_APP { return 0 }
137 if _r32(buf, OPT_ENTRY) != RVA_TEXT { return 0 }
138 if buf[FOFF_TEXT] != (0x56 as u8) { return 0 } // entry[0] = push rsi
139 if buf[FOFF_TEXT + 0x31] != (0x48 as u8) { return 0 } // mov rax,[rsi+0x60] (BootServices)
140 if buf[FOFF_TEXT + 0x33] != (0x46 as u8) { return 0 }
141 if buf[FOFF_TEXT + 0x35] != (0xFF as u8) { return 0 } // call [rax+0x38] (GetMemoryMap)
142 if buf[FOFF_TEXT + 0x37] != (0x38 as u8) { return 0 }
143 if buf[FOFF_TEXT + 0x61] != (0x48 as u8) { return 0 } // shr rdx,cl (the hex loop's variable shift)
144 if buf[FOFF_TEXT + 0x62] != (0xD3 as u8) { return 0 }
145 if buf[FOFF_TEXT + 0x63] != (0xEA as u8) { return 0 }
146 return 1
147}
148
149func 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 }
150func 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 }
151func u_fn(fd: i64, v: i64) -> i64 {
152 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m }
153 let t: *u8 = sys_mmap(28); var k: i64 = 0
154 if m == 0 { t[0] = 48; k = 1 }
155 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
156 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
157 sys_write(fd, bb, k); return 0
158}
159func u_log(sz: i64, repro: i64, structural: i64, tamper: i64, verdict: *u8) -> i64 {
160 let lfd: i64 = sys_openat_append("knowledge/status/nishi_os.log" as *u8, 0x1a4)
161 if lfd < 0 { return 0 - 1 }
162 u_fp(lfd, "NOSR0_3 name=nx_boot_uefi_ramsize.efi subsystem=10 climate=x86_64-uefi displays=ram-map-size-hex bytes=" as *u8); u_fn(lfd, sz)
163 u_fp(lfd, " repro=" as *u8); u_fn(lfd, repro)
164 u_fp(lfd, " structural=" as *u8); u_fn(lfd, structural)
165 u_fp(lfd, " tamper_caught=" as *u8); u_fn(lfd, tamper)
166 u_fp(lfd, " scope=emit-proven verdict=" as *u8); u_fp(lfd, verdict); u_fp(lfd, "\n" as *u8)
167 sys_close(lfd); return 0
168}
169
170func main(argc: i64, argv: *i64) -> i64 {
171 let buf: *u8 = sys_mmap(PE_MAGIC_4096)
172 let buf2: *u8 = sys_mmap(PE_MAGIC_4096)
173 let sz: i64 = uefi_emit(buf)
174 let sz2: i64 = uefi_emit(buf2)
175 var repro: i64 = 1
176 if sz != sz2 { repro = 0 }
177 var i: i64 = 0
178 while i < sz { if buf[i] != buf2[i] { repro = 0 } i = i + 1 }
179 let structural: i64 = uefi_verify(buf)
180 _w16(buf2, OPT_SUBSYS, 3)
181 var tamper_caught: i64 = 0
182 if uefi_verify(buf2) == 0 { tamper_caught = 1 }
183 var green: i64 = 0
184 if repro == 1 { if structural == 1 { if tamper_caught == 1 { green = 1 } } }
185 if green == 1 {
186 let ofd: i64 = sys_openat_wr("_offc/nx_boot_uefi_ramsize.efi" as *u8, 0x1a4)
187 if ofd < 0 {
188 u_p("NOS-R0.3 RED: cannot write _offc/nx_boot_uefi_ramsize.efi\n" as *u8)
189 u_log(sz, repro, structural, tamper_caught, "RED" as *u8); sys_exit(1); return 1
190 }
191 sys_write(ofd, buf, sz); sys_close(ofd)
192 u_p("NOS-R0.3 GREEN: authored _offc/nx_boot_uefi_ramsize.efi (reads+hex-prints RAM map size) bytes=" as *u8)
193 u_fn(1, sz); u_p(" repro+structural(+hex-loop opcode)+tamper all pass\n" as *u8)
194 u_log(sz, repro, structural, tamper_caught, "GREEN" as *u8); sys_exit(0); return 0
195 }
196 u_p("NOS-R0.3 RED: repro=" as *u8); u_fn(1, repro)
197 u_p(" structural=" as *u8); u_fn(1, structural)
198 u_p(" tamper_caught=" as *u8); u_fn(1, tamper_caught); u_p("\n" as *u8)
199 u_log(sz, repro, structural, tamper_caught, "RED" as *u8); sys_exit(1); return 1
200}