aboutsummaryrefslogtreecommitdiffstats
path: root/psp_emu/harness/probe_sysdrv_105d_zero_length.py
blob: 5cdc40d0a076d31250eadd1240c61c5967c341f8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/env python3
"""Signed .54 0x105D zero-length range: capture modeled fixed TMR writes only.
No card, fabric, or external client's descriptor is modified.
"""
from pathlib import Path
import sys
from unicorn import UC_HOOK_CODE
from unicorn.arm_const import UC_ARM_REG_R0,UC_ARM_REG_R1,UC_ARM_REG_R2,UC_ARM_REG_R6,UC_ARM_REG_LR,UC_ARM_REG_PC
sys.path.insert(0,str(Path(__file__).resolve().parents[1]))
from pspemu import sysdrv_env
SIGNED=Path(__file__).resolve().parents[2]/'psp_out/elf/sys_drv_0.49.0.54_18bd9d26.elf'

def run(start,length):
    sd=sysdrv_env.make()
    assert Path(sd.image_path).read_bytes()==SIGNED.read_bytes()
    r,f,_=sysdrv_env.run_init(sd)
    assert r==0 and not f and sysdrv_env.init_flag(sd)==1
    # Bypass only the model's external-timebase-dependent mutex helper;
    # the signed validation, descriptor allocator and TMR writes still run.
    def mutex_success(uc,ea,size,data):
        uc.reg_write(UC_ARM_REG_R0,0)
        uc.reg_write(UC_ARM_REG_PC,uc.reg_read(UC_ARM_REG_LR))
    sd.uc.hook_add(UC_HOOK_CODE,mutex_success,begin=0xE16210,end=0xE16211)
    hits=[];entered=[];types=[]
    sd.uc.hook_add(UC_HOOK_CODE,lambda uc,pc,size,data:types.append((uc.reg_read(UC_ARM_REG_R6),uc.reg_read(UC_ARM_REG_R1),sd.rd32(uc.reg_read(UC_ARM_REG_R6)+16))),begin=0xE14550,end=0xE14551)
    for ea in (0xE1447C,0xE144D2,0xE144F2,0xE144FA,0xE14500,0xE14508,0xE145E2,0xE17EF4,0xE218FC):
        sd.uc.hook_add(UC_HOOK_CODE,lambda uc,pc,size,data:entered.append(pc),begin=ea,end=ea+1)
    def on_write(comp,n):
        hits.append(tuple(comp.uc.reg_read(reg) for reg in (UC_ARM_REG_R0,UC_ARM_REG_R1,UC_ARM_REG_R2)))
        return 0
    sd.svc.register(0x7C,on_write)
    req=sd.alloc(0x100)
    sd.write(req,bytes(0x100))
    # msg[18] is the subtype for 0x105D. The config pointer at the
    # same index is needed only for init (0x1000), not this request.
    for i,v in ((0,0x105D),(1,2),(14,start),(15,0),(16,length),(17,0),(18,49)):
        sd.wr32(req+i*4,v)
    rv=sd.run_function(0xE087E4,(req,2,0,0),count=2_000_000,timeout=2_000_000)
    return rv,hits,sd.rd32(req+19*4),entered,types

def main():
    for start,length,want in ((0,0,(0,0xffffffff,0x37,0x30038)),
                              (0,0x10000,(0,0,0x37,0x30038)),
                              (0x10000,0,(1,0,0x37,0x30038))):
        rv,hits,slot,entered,types=run(start,length)
        assert rv==0 and types and types[0][1:]==(49,49) and 0xE17EF4 in entered,(rv,entered,types)
        assert hits==[(0x49007a00+4*i,v,4) for i,v in enumerate(want)],hits
        print(f'start={start:#x} length={length:#x} status={rv:#x} slot={slot:#x} model-fabric={[hex(v) for v in want]}')
if __name__=='__main__':main()