; xhello.asm -- open a *new* X connection from an rdebug `jump` payload and ; create/map a window on the live DWT X server. ; ; Calling convention (the one the firmware itself uses; see the WM at ; 07F57044 and the TM at 07E5D2B4): ; ; MOVE A14,-*SP,1 ; reserve the slot the callee restores A14 from ; MOVI argN,A0 / MOVE A0,*A14+,1 ; last argument first, upward via A14 ; ... ; MOVI arg0,A0 / MOVE A0,*A14+,1 ; first argument last ; CALLA target ; ; We point A14 at a private argument buffer instead of the dispatcher frame, and ; we keep the entry SP/A14 in RAM so the payload returns even if a callee ; leaves the stack in an unexpected state. ; ; Xlib entry points (Ghidra address -> bit address): ; 7F384AE XOpenDisplay(name) -> 3F9C2570 ; 7FA8372 XCreateSimpleWindow(...) -> 3FD41B90 ; 7FAC8B6 XMapWindow(display,window) -> 3FD645B0 ; 7FB3ED6 XSync(display,discard) -> 3FD9F6B0 ; 7F68B1A strlen(s) -> 3FB458D0 (convention check) ; ; Markers (32-bit cells, bit addresses): ; 01850100 display pointer ; 01850110 root window ; 01850120 window id ; 01850130 XSync return ; 01850140 stage counter ; 01850150 strlen("0::0") -- must be 4; if not, we stop before touching Xlib .text _start: setf 16, 0, 0 setf 32, 0, 1 mmtm sp, a0,a1,a2,a3,a4,a5,a6,a7 move sp, @01850420h, 1 ; entry SP move a14, @01850400h, 1 ; entry A14 movi 1, a0, L move a0, @01850140h, 1 ; stage = 1 ; ---- convention check: strlen("0::0") == 4 -------------------- move a14, -*sp, 1 movi 01852000h, a14, L movi 3FACE948h, a0, L ; ROM "0::0" move a0, *a14+, 1 ; arg0 calla 3FB458D0h ; strlen move @01850420h, sp, 1 move @01850400h, a14, 1 move a8, @01850160h, 1 ; MARK strlen movi 4, a0, L cmp a0, a8 jrne done movi 2, a0, L move a0, @01850140h, 1 ; ---- display = XOpenDisplay("0::0") --------------------------- move a14, -*sp, 1 movi 01852000h, a14, L movi 3FACE948h, a0, L move a0, *a14+, 1 ; arg0 = name calla 3F9C2570h ; XOpenDisplay move @01850420h, sp, 1 move @01850400h, a14, 1 move a8, @01850100h, 1 ; MARK display move a8, a8 jreq done movi 3, a0, L move a0, @01850140h, 1 ; ---- root = *(*(display+0x480)+0x40) -------------------------- move @01850100h, a6, 1 move *a6(0480h), a9, 1 move *a9(040h), a9, 1 move a9, @01850110h, 1 ; MARK root ; ---- XCreateSimpleWindow(display,root,100,100,400,200,2,0,0) -- move a14, -*sp, 1 movi 01852000h, a14, L movi 0, a0, L move a0, *a14+, 1 ; background = 0 (black) move a0, *a14+, 1 ; border = 0 movi 2, a0, L move a0, *a14+, 1 ; border width movi 200, a0, L move a0, *a14+, 1 ; height movi 400, a0, L move a0, *a14+, 1 ; width movi 100, a0, L move a0, *a14+, 1 ; y move a0, *a14+, 1 ; x move a9, *a14+, 1 ; parent move @01850100h, a6, 1 move a6, *a14+, 1 ; display calla 3FD41B90h ; XCreateSimpleWindow move @01850420h, sp, 1 move @01850400h, a14, 1 move a8, @01850120h, 1 ; MARK window movi 4, a0, L move a0, @01850140h, 1 ; ---- XMapWindow(display, window) ------------------------------ move a14, -*sp, 1 movi 01852000h, a14, L move a8, *a14+, 1 ; window move @01850100h, a6, 1 move a6, *a14+, 1 ; display calla 3FD645B0h ; XMapWindow move @01850420h, sp, 1 move @01850400h, a14, 1 movi 5, a0, L move a0, @01850140h, 1 ; ---- XSync(display, 0) ---------------------------------------- move a14, -*sp, 1 movi 01852000h, a14, L movi 0, a0, L move a0, *a14+, 1 ; discard = 0 move @01850100h, a6, 1 move a6, *a14+, 1 ; display calla 3FD9F6B0h ; XSync move @01850420h, sp, 1 move @01850400h, a14, 1 move a8, @01850130h, 1 ; MARK sync movi 6, a0, L move a0, @01850140h, 1 done: mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7 movi 0, a8, L rets .end