code wiki / _hdl_build / nx_emu_x86_boot_kernel_test.nx
nx_emu_x86_boot_kernel_test.nx source
↩ module page · 101 lines · 6269 B
1// nx_emu_x86_boot_kernel_test.nx -- x86 full-system ladder R8: an x86 KERNEL BOOTS END-TO-END.
2// A UNIFIED emu (R1-R4 decode + R5-2 CR0/mode machinery + R7 UART-over-OUT) runs an authored x86
3// "kernel" that: prints a banner over the 16550 UART (out dx,al @ 0x3F8), sets CR0.PE to ENTER
4// PROTECTED MODE, prints again, and exits. The emu collects the serial output and tracks the mode.
5// This is the x86 twin of the rv64 NishiOS boot (which emitted "NISHI"). KAT: serial ==
6// "NISHIOS:PROTECTED" AND the cpu reached protected mode.
7// HONEST SCOPE: integrates decode+mode+UART; folding the R6 page-walk into the emu's mem access +
8// a real multi-stage kernel + R9 bootloader/USB image + R10 hardware remain. No hardware writes
9// (Rule 26). expect_exit: 0 license_tier: ORIGINAL
10import "nx_emu_x86_k.nx"
11
12func bk_b(c: *u8, o: i64, b: i64) -> i64 { c[o]=(b & 0xff) as u8; return o+1 }
13func bk_i32(c: *u8, o: i64, v: i64) -> i64 { c[o]=(v&0xff) as u8; c[o+1]=((v>>8)&0xff) as u8; c[o+2]=((v>>16)&0xff) as u8; c[o+3]=((v>>24)&0xff) as u8; return o+4 }
14func bk_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
15func bk_num(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
16func bk_beq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
17func bk_mode(cr0: i64, efer: i64) -> i64 { let pe: i64=cr0&1; let pg: i64=(cr0>>31)&1; let lme: i64=(efer>>8)&1; if pe==0 { return 0 } if pg==1 { if lme==1 { return 2 } } return 1 }
18
19// emit "mov rax,char ; out dx,al" for each char of s (assumes rdx=0x3F8 already loaded).
20func bk_emit_str(c: *u8, o: i64, s: *u8) -> i64 {
21 var i: i64=0
22 while s[i] != (0 as u8) {
23 o=bk_b(c,o,0x48); o=bk_b(c,o,0xC7); o=bk_b(c,o,0xC0); o=bk_i32(c,o, s[i] as i64)
24 o=bk_b(c,o,0xEE)
25 i=i+1
26 }
27 return o
28}
29
30// unified boot emu: R1-R4 decode + CR0/EFER + mov-cr0(0F22)/wrmsr(0F30) + OUT(EE)->UART. st[1]=mode.
31func emu_x86_boot(code: *u8, len: i64, mem: *u8, uart: *u8, ulen: *i64, st: *i64) -> i64 {
32 let reg: *i64 = sys_mmap(8 * 16) as *i64
33 var pc: i64 = 0
34 var zf: i64 = 0
35 var cr0: i64 = 0
36 var efer: i64 = 0
37 while pc < len {
38 let b: i64 = code[pc] as i64
39 var h: i64 = 0
40 if b == 0x0F {
41 let b1: i64 = code[pc+1] as i64
42 if b1 == 0x05 {
43 if reg[0] == 60 { st[0]=cr0; st[1]=bk_mode(cr0,efer); return reg[7] & 0xff }
44 pc = pc + 2; h = 1
45 }
46 if h == 0 { if b1 == 0x22 { let m: i64=code[pc+2] as i64; let cri: i64=(m>>3)&7; if cri==0 { cr0=reg[m&7] } pc = pc + 3; h = 1 } }
47 if h == 0 { if b1 == 0x30 { efer = reg[0]; pc = pc + 2; h = 1 } }
48 if h == 0 { return 0 - 1 }
49 }
50 if h == 0 { if b == 0xEE { let port: i64=reg[2] & 0xFFFF; if port==0x3F8 { uart[ulen[0]]=(reg[0] & 0xff) as u8; ulen[0]=ulen[0]+1 } pc=pc+1; h=1 } }
51 if h == 0 { if b == 0xEB { var r: i64=code[pc+1] as i64; if r>127 { r=r-256 } pc = pc + 2 + r; h = 1 } }
52 if h == 0 { if b == 0x75 { var r: i64=code[pc+1] as i64; if r>127 { r=r-256 } if zf==0 { pc=pc+2+r } else { pc=pc+2 } h = 1 } }
53 if h == 0 { if b == 0x48 {
54 let op: i64 = code[pc+1] as i64
55 if op == 0xC7 { reg[(code[pc+2] as i64) & 7] = k_i32(code, pc+3); pc = pc + 7; h = 1 }
56 if op == 0x89 { let m: i64=code[pc+2] as i64; reg[m & 7] = reg[(m>>3) & 7]; pc = pc + 3; h = 1 }
57 if op == 0x01 { let m: i64=code[pc+2] as i64; reg[m & 7] = reg[m & 7] + reg[(m>>3) & 7]; pc = pc + 3; h = 1 }
58 if op == 0x39 { let m: i64=code[pc+2] as i64; let t: i64 = reg[m & 7] - reg[(m>>3) & 7]; if t==0 { zf=1 } else { zf=0 } pc = pc + 3; h = 1 }
59 } }
60 if h == 0 { return 0 - 3 }
61 }
62 return 0 - 4
63}
64
65func main() -> i64 {
66 bk_puts("x86 full-system ladder R8: an x86 KERNEL BOOTS END-TO-END (banner -> protected -> banner)\n" as *u8)
67 let c: *u8 = sys_mmap(1024)
68 var o: i64 = 0
69 // mov rdx, 0x3F8 (UART port)
70 o=bk_b(c,o,0x48); o=bk_b(c,o,0xC7); o=bk_b(c,o,0xC2); o=bk_i32(c,o,0x3F8)
71 // print "NISHIOS:" over the UART
72 o=bk_emit_str(c,o,"NISHIOS:\x00" as *u8)
73 // enter protected mode: mov rax,1 ; mov cr0,rax
74 o=bk_b(c,o,0x48); o=bk_b(c,o,0xC7); o=bk_b(c,o,0xC0); o=bk_i32(c,o,1)
75 o=bk_b(c,o,0x0F); o=bk_b(c,o,0x22); o=bk_b(c,o,0xC0)
76 // print "PROTECTED" over the UART
77 o=bk_emit_str(c,o,"PROTECTED\x00" as *u8)
78 // exit
79 o=bk_b(c,o,0x48); o=bk_b(c,o,0xC7); o=bk_b(c,o,0xC7); o=bk_i32(c,o,0)
80 o=bk_b(c,o,0x48); o=bk_b(c,o,0xC7); o=bk_b(c,o,0xC0); o=bk_i32(c,o,60)
81 o=bk_b(c,o,0x0F); o=bk_b(c,o,0x05)
82
83 let mem: *u8 = sys_mmap(65536)
84 let uart: *u8 = sys_mmap(256)
85 let ulen: *i64 = sys_mmap(8) as *i64
86 ulen[0]=0
87 let st: *i64 = sys_mmap(64) as *i64
88 let rc: i64 = emu_x86_boot(c, o, mem, uart, ulen, st)
89
90 bk_puts(" SOVEREIGN-EMU-X86 serial: " as *u8); sys_write(1, uart, ulen[0]); bk_puts("\n final mode = " as *u8); bk_num(st[1]); bk_puts(" (0=real 1=protected 2=long), exit rc=" as *u8); bk_num(rc); bk_puts("\n" as *u8)
91
92 var pass: i64=0
93 var ttl: i64=0
94 ttl=ttl+1; bk_puts(" T1 clean exit: " as *u8); if rc==0 { pass=pass+1; bk_puts("PASS\n" as *u8) } else { bk_puts("FAIL\n" as *u8) }
95 ttl=ttl+1; bk_puts(" T2 serial == NISHIOS:PROTECTED: " as *u8); if ulen[0]==17 { if bk_beq(uart, "NISHIOS:PROTECTED\x00" as *u8, 17)==1 { pass=pass+1; bk_puts("PASS\n" as *u8) } else { bk_puts("FAIL\n" as *u8) } } else { bk_puts("FAIL\n" as *u8) }
96 ttl=ttl+1; bk_puts(" T3 kernel reached PROTECTED mode mid-boot: " as *u8); if st[1]==1 { pass=pass+1; bk_puts("PASS\n" as *u8) } else { bk_puts("FAIL\n" as *u8) }
97
98 bk_puts("X86-BOOT-KERNEL-GATE passed " as *u8); bk_num(pass); bk_puts("/" as *u8); bk_num(ttl)
99 if pass==ttl { bk_puts(" verdict=GREEN (an x86 kernel BOOTS end-to-end on the sovereign emu; R9 bootloader+USB image next)\n" as *u8); sys_exit(0); return 0 }
100 bk_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1
101}