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}