code wiki / _hdl_build / _gpu_dxg_r1_recon3.nx
_gpu_dxg_r1_recon3.nx source
↩ module page · 131 lines · 7149 B
1// _gpu_dxg_r1_recon3.nx -- R1 recon pass 3. Pass 2 proved QueryAdapterInfo(nr=0x09) returns
2// -EINVAL for EVERY type/size AND for a bogus handle -- i.e. the ENUM handle (0x40000000) is NOT a
3// queryable adapter handle in WSL dxgkrnl. The fix (per WSL2 dxgkrnl): get a real per-process
4// adapter handle via LX_DXOPENADAPTERFROMLUID, then QueryAdapterInfo on THAT handle.
5//
6// struct d3dkmt_openadapterfromluid { winluid adapter_luid(8); d3dkmthandle adapter_handle(4 OUT); }
7// = 12 bytes -> code = _IOWR(0x47, nr, 12) = (3<<30)|(12<<16)|(0x47<<8)|nr = 0xC00C4700|nr.
8// We sweep nr to find the accepted one (ret==0), read the OUT handle, then QueryAdapterInfo type=8.
9// Also try LX_DXCLOSEADAPTER cleanup is omitted (recon).
10// AUTHOR=ORGAN / NO-WAVE / raw syscalls only. license_tier: ORIGINAL
11import "nx_syscalls.nx"
12
13const DXG_LX_DXENUMADAPTERS2: i64 = 0xC0104714
14const QAI_CODE: i64 = 0xC0184709 // QueryAdapterInfo, 24-byte struct, pinned live
15
16func p(s: *u8) -> i64 { var nn: i64=0; while s[nn]!=(0 as u8){nn=nn+1} sys_write(1,s,nn); return 0 }
17func n(v: i64) -> i64 { let bb: *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;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{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 }
18func x(v: i64) -> i64 { p("0x" as *u8); let bb:*u8=sys_mmap(20); var k:i64=0; var m:i64=v; if m==0{bb[0]=48;k=1}; while m>0{ let d:i64=m&15; if d<10{bb[k]=(48+d) as u8}else{bb[k]=(87+d) as u8}; m=(m>>4); k=k+1 } var i:i64=0; let o:*u8=sys_mmap(20); while i<k{o[i]=bb[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
19
20func print_utf16(base: *u8, off: i64) -> i64 {
21 let out: *u8 = sys_mmap(600); var i: i64 = 0; var cnt: i64 = 0
22 while i < 260 {
23 let lo: i64 = base[off + i*2] as i64; let hi: i64 = base[off + i*2 + 1] as i64
24 let cu: i64 = lo | (hi << 8)
25 if cu == 0 { i = 260 }
26 else { if cu >= 0x20 { if cu <= 0x7e { out[cnt] = cu as u8 } else { out[cnt] = 63 as u8 } } else { out[cnt] = 63 as u8 } cnt = cnt + 1; i = i + 1 }
27 }
28 sys_write(1, out, cnt); return cnt
29}
30
31func query(fd: i64, handle: i64, qtype: i64, priv: *u8, psize: i64) -> i64 {
32 var z: i64 = 0; while z < 2048 { priv[z] = 0 as u8; z = z + 1 }
33 let req: *u8 = sys_mmap(64); var y: i64 = 0; while y < 64 { req[y] = 0 as u8; y = y + 1 }
34 let h: *i64 = (req as i64 + 0) as *i64
35 h[0] = (handle & 0xffffffff) | ((qtype & 0xffffffff) << 32)
36 let pd: *i64 = (req as i64 + 8) as *i64; pd[0] = priv as i64
37 let pds: *i64 = (req as i64 + 16) as *i64; pds[0] = psize & 0xffffffff
38 return sys_ioctl(fd, QAI_CODE, req as i64)
39}
40
41// Open adapter from a LUID with explicit struct byte-size (so we can also try 12 and 16). Writes the
42// OUT handle to out_h[0] and the ioctl ret to out_ret[0]. Returns ioctl ret.
43func open_from_luid(fd: i64, nr: i64, structsz: i64, la: i64, lb: i64, out_h: *i64, out_ret: *i64) -> i64 {
44 let code: i64 = (3<<30) | (structsz<<16) | (0x47<<8) | nr
45 let req: *u8 = sys_mmap(64); var y: i64 = 0; while y < 64 { req[y] = 0 as u8; y = y + 1 }
46 let lp: *i64 = (req as i64 + 0) as *i64
47 lp[0] = (la & 0xffffffff) | ((lb & 0xffffffff) << 32) // winluid @0
48 let ret: i64 = sys_ioctl(fd, code, req as i64)
49 out_ret[0] = ret
50 // OUT handle at offset 8 (after 8-byte luid)
51 let hp: *i64 = (req as i64 + 8) as *i64
52 let oh: i64 = hp[0] & 0xffffffff
53 out_h[0] = oh
54 return ret
55}
56
57func main() -> i64 {
58 p("=== R1 RECON pass3: OpenAdapterFromLuid -> QueryAdapterInfo on the OPENED handle ===\n" as *u8)
59 let fd: i64 = sys_openat_rd("/dev/dxg" as *u8)
60 if fd < 0 { p("open fail\n" as *u8); sys_exit(1); return 1 }
61
62 let ainfo: *u8 = sys_mmap(4096); var z: i64 = 0; while z < 4096 { ainfo[z] = 0 as u8; z = z + 1 }
63 let ereq: *u8 = sys_mmap(64); var y: i64 = 0; while y < 64 { ereq[y] = 0 as u8; y = y + 1 }
64 ereq[0] = 8 as u8; let r8: *i64 = (ereq as i64 + 8) as *i64; r8[0] = ainfo as i64
65 let eret: i64 = sys_ioctl(fd, DXG_LX_DXENUMADAPTERS2, ereq as i64)
66 let nc: i64 = (ereq[0] as i64)|((ereq[1] as i64)<<8)|((ereq[2] as i64)<<16)|((ereq[3] as i64)<<24)
67 if eret != 0 { p("enum fail\n" as *u8); sys_exit(1); return 1 }
68 p("enum ok num_adapters=" as *u8); n(nc); p("\n" as *u8)
69
70 let priv: *u8 = sys_mmap(8192)
71 let oh_box: *i64 = sys_mmap(16)
72 let oret_box: *i64 = sys_mmap(16)
73
74 // For each adapter: find the OpenAdapterFromLuid nr (try struct sizes 12 and 16, sweep nr 1..0x14)
75 var ai: i64 = 0
76 while ai < nc {
77 let base: i64 = ai * 20
78 let la: i64 = (ainfo[base+4] as i64)|((ainfo[base+5] as i64)<<8)|((ainfo[base+6] as i64)<<16)|((ainfo[base+7] as i64)<<24)
79 let lb: i64 = (ainfo[base+8] as i64)|((ainfo[base+9] as i64)<<8)|((ainfo[base+10] as i64)<<16)|((ainfo[base+11] as i64)<<24)
80 p("\n--- adapter[" as *u8); n(ai); p("] luid.a=" as *u8); x(la); p(" luid.b=" as *u8); x(lb); p(" ---\n" as *u8)
81
82 var found_nr: i64 = -1
83 var found_sz: i64 = -1
84 var opened: i64 = 0
85 // struct size 12 then 16
86 let szs: *i64 = sys_mmap(32); szs[0]=12; szs[1]=16
87 var ssi: i64 = 0
88 while ssi < 2 {
89 var nr: i64 = 1
90 while nr <= 0x14 {
91 let ret: i64 = open_from_luid(fd, nr, szs[ssi], la, lb, oh_box, oret_box)
92 if ret == 0 {
93 let oh: i64 = oh_box[0]
94 // a real open returns a non-zero per-process handle. nr=0x14 is enum (collision) -> oh likely 0
95 if oh != 0 {
96 p(" open ACCEPTED nr=" as *u8); x(nr); p(" structsz=" as *u8); n(szs[ssi]); p(" OUT_handle=" as *u8); x(oh); p("\n" as *u8)
97 if found_nr < 0 { found_nr = nr; found_sz = szs[ssi]; opened = oh }
98 }
99 }
100 nr = nr + 1
101 }
102 ssi = ssi + 1
103 }
104
105 if found_nr >= 0 {
106 // Query the OPENED handle: type=8 ADAPTERREGISTRYINFO, size 1568
107 let qret: i64 = query(fd, opened, 8, priv, 1568)
108 p(" QueryAdapterInfo(opened handle=" as *u8); x(opened); p(", type=8) ret=" as *u8); n(qret)
109 if qret == 0 { p(" string=\"" as *u8); print_utf16(priv, 0); p("\"" as *u8) }
110 p("\n" as *u8)
111 // if EINVAL still, sweep types on the OPENED handle
112 if qret == -22 {
113 p(" (still EINVAL -> type sweep on opened handle):\n" as *u8)
114 var t: i64 = 0
115 while t <= 20 {
116 let qr2: i64 = query(fd, opened, t, priv, 1568)
117 if qr2 != -22 { p(" type=" as *u8); n(t); p(" ret=" as *u8); n(qr2)
118 if qr2 == 0 { p(" string=\"" as *u8); print_utf16(priv, 0); p("\"" as *u8) } p("\n" as *u8) }
119 t = t + 1
120 }
121 }
122 } else {
123 p(" OpenAdapterFromLuid: no nr/size accepted with non-zero handle.\n" as *u8)
124 }
125 ai = ai + 1
126 }
127
128 sys_close(fd)
129 p("\n=== R1 RECON pass3 DONE ===\n" as *u8)
130 return 0
131}