class SMCEpTracer(EP): BASE_MESSAGE = SMCMessage def __init__(self, tracer, epid): super().__init__(tracer, epid) self.state.sram_addr = None self.state.verbose = 1 self.state.rb = {} Initialize = msg_log(SMC_INITIALIZE, DIR.TX, SMCInitialize) Notification = msg_log(SMC_NOTIFICATION, DIR.RX) @msg(SMC_WRITE_KEY, DIR.TX, SMCWriteKey) def WriteKey(self, msg): key = msg.KEY.to_bytes(4, byteorder="big").decode("ascii") self.state.rb[msg.ID] = msg.TYPE, key, msg.SIZE data = self.hv.iface.readmem(self.state.sram_addr, msg.SIZE) self.log(f"[{msg.ID:x}] >W: <{key}> = {data.hex()} ({msg.SIZE})") return True @msg(SMC_READ_KEY, DIR.TX, SMCReadKey) def ReadKey(self, msg): key = msg.KEY.to_bytes(4, byteorder="big").decode("ascii") self.state.rb[msg.ID] = msg.TYPE, key, msg.SIZE self.log(f"[{msg.ID:x}] >R: <{key}> = ... ({msg.SIZE})") return True @msg(SMC_RW_KEY, DIR.TX, SMCReadWriteKey) def ReadKeyPayload(self, msg): key = msg.KEY.to_bytes(4, byteorder="big").decode("ascii") self.state.rb[msg.ID] = msg.TYPE, key, msg.RSIZE data = self.hv.iface.readmem(self.state.sram_addr, msg.WSIZE) self.log( f"[{msg.ID:x}] >RP: <{key}> = {data.hex()} ({msg.WSIZE, msg.RSIZE})" ) return True @msg(SMC_GET_KEY_INFO, DIR.TX, SMCGetKeyInfo) def GetInfo(self, msg): key = msg.KEY.to_bytes(4, byteorder="big").decode("ascii") self.state.rb[msg.ID] = msg.TYPE, key, None self.log(f"[{msg.ID:x}] >Get Info: <{key}>") return True @msg(None, DIR.RX, Register64) def RXMsg(self, msg): if self.state.sram_addr is None: self.log(f"SRAM address: {msg.value:#x}") self.state.sram_addr = msg.value return True msg = SMCResult(msg.value) if msg.RESULT != 0: self.log(f"[{msg.ID:x}] <Err: 0x{msg.RESULT:02x}") return True if msg.ID in self.state.rb: msgtype, key, size = self.state.rb.pop(msg.ID) if msgtype in (SMC_READ_KEY, SMC_RW_KEY): if size <= 4: data = hex(msg.VALUE) else: data = self.hv.iface.readmem(self.state.sram_addr, msg.SIZE).hex() self.log(f"[{msg.ID:x}] <R: <{key}> = {data}") return True elif msgtype == SMC_GET_KEY_INFO: data = self.hv.iface.readmem(self.state.sram_addr, 6) size, type, flags = struct.unpack("B4sB", data) self.log( f"[{msg.ID:x}] <Info: <{key}>: size={size} type={type.decode('ascii')} flags={flags:#x}" ) return True self.log(f"[{msg.ID:x}] <OK {msg!r}") return True
class AFKEp(EP): BASE_MESSAGE = AFKEPMessage def __init__(self, tracer, epid): super().__init__(tracer, epid) self.txbuf = None self.rxbuf = None self.state.txbuf = EPState() self.state.rxbuf = EPState() self.state.shmem_iova = None self.state.txbuf_info = None self.state.rxbuf_info = None self.state.verbose = 1 def start(self): #self.add_mon() self.create_bufs() def create_bufs(self): if not self.state.shmem_iova: return if not self.txbuf and self.state.txbuf_info: off, size = self.state.txbuf_info self.txbuf = AFKRingBufSniffer(self, self.state.txbuf, self.state.shmem_iova + off, size) if not self.rxbuf and self.state.rxbuf_info: off, size = self.state.rxbuf_info self.rxbuf = AFKRingBufSniffer(self, self.state.rxbuf, self.state.shmem_iova + off, size) def add_mon(self): if self.state.shmem_iova: iomon.add(self.state.shmem_iova, 32768, name=f"{self.name}.shmem@{self.state.shmem_iova:08x}", offset=0) Init = msg_log(0x80, DIR.TX) Init_Ack = msg_log(0xa0, DIR.RX) GetBuf = msg_log(0x89, DIR.RX) Shutdown = msg_log(0xc0, DIR.TX) Shutdown_Ack = msg_log(0xc1, DIR.RX) @msg(0xa1, DIR.TX, AFKEP_GetBuf_Ack) def GetBuf_Ack(self, msg): self.state.shmem_iova = msg.DVA self.txbuf = None self.rxbuf = None self.state.txbuf = EPState() self.state.rxbuf = EPState() self.state.txbuf_info = None self.state.rxbuf_info = None #self.add_mon() @msg(0xa2, DIR.TX, AFKEP_Send) def Send(self, msg): for data in self.txbuf.read(): if self.state.verbose >= 3: self.log(f">TX rptr={self.txbuf.state.rptr:#x}") chexdump(data) self.handle_ipc(data, dir=">") return True Hello = msg_log(0xa3, DIR.TX) @msg(0x85, DIR.RX, AFKEPMessage) def Recv(self, msg): for data in self.rxbuf.read(): if self.state.verbose >= 3: self.log(f"<RX rptr={self.rxbuf.state.rptr:#x}") chexdump(data) self.handle_ipc(data, dir="<") return True def handle_ipc(self, data, dir=None): pass @msg(0x8a, DIR.RX, AFKEP_InitRB) def InitTX(self, msg): off = msg.OFFSET * AFKRingBuf.BLOCK_SIZE size = msg.SIZE * AFKRingBuf.BLOCK_SIZE self.state.txbuf_info = (off, size) self.create_bufs() @msg(0x8b, DIR.RX, AFKEP_InitRB) def InitRX(self, msg): off = msg.OFFSET * AFKRingBuf.BLOCK_SIZE size = msg.SIZE * AFKRingBuf.BLOCK_SIZE self.state.rxbuf_info = (off, size) self.create_bufs()
class DCPEp(EP): BASE_MESSAGE = DCPMessage def __init__(self, tracer, epid): super().__init__(tracer, epid) self.state.shmem_iova = None self.state.show_globals = True self.state.show_acks = True self.state.max_len = 1024 * 1024 self.state.verbosity = 3 self.state.op_verb = {} self.state.ch = {} self.state.dumpfile = None self.ch_cb = DCPCallChannel(self, "CB", 0x60000, 0x8000) self.ch_cmd = DCPCallChannel(self, "CMD", 0, 0x8000) self.ch_async = DCPCallChannel(self, "ASYNC", 0x40000, 0x20000) self.ch_oobcb = DCPCallChannel(self, "OOBCB", 0x68000, 0x8000) self.ch_oobcmd = DCPCallChannel(self, "OOBCMD", 0x8000, 0x8000) self.cmd_ch = { CallContext.CB: self.ch_cmd, CallContext.CMD: self.ch_cmd, CallContext.ASYNC: None, # unknown CallContext.OOBCB: self.ch_oobcmd, CallContext.OOBCMD: self.ch_oobcmd, } self.cb_ch = { CallContext.CB: self.ch_cb, CallContext.CMD: None, CallContext.ASYNC: self.ch_async, CallContext.OOBCB: self.ch_oobcb, CallContext.OOBCMD: None, } def start(self): self.add_mon() def add_mon(self): if self.state.shmem_iova and self.state.show_globals: addr = self.state.shmem_iova + 0x80000 iomon.add(addr, 128, name=f"{self.name}.shmem@{addr:08x}", offset=addr) #addr = self.state.shmem_iova #iomon.add(addr, 0x80080, #name=f"{self.name}.shmem@{addr:08x}", offset=addr) InitComplete = msg_log(1, DIR.RX) @msg(0, DIR.TX, DCPEp_SetShmem) def SetShmem(self, msg): self.log(f"Shared memory DVA: {msg.DVA:#x}") self.state.shmem_iova = msg.DVA & 0xffffffff self.add_mon() @msg(2, DIR.TX, DCPEp_Msg) def Tx(self, msg): if msg.ACK: self.cb_ch[msg.CTX].ack(msg, ">") else: self.cmd_ch[msg.CTX].call(msg, ">") if self.state.show_globals: iomon.poll() return True @msg(2, DIR.RX, DCPEp_Msg) def Rx(self, msg): self.log(msg) if msg.ACK: self.cmd_ch[msg.CTX].ack(msg, "<") else: self.cb_ch[msg.CTX].call(msg, "<") if self.state.show_globals: iomon.poll() return True def get_verbosity(self, tag): return self.state.op_verb.get(tag, self.state.verbosity) def set_verb_known(self, verb): for i in KNOWN_MSGS: if verb is None: self.state.op_verb.pop(i, None) else: self.state.op_verb[i] = verb
class IOEp(EP): BASE_MESSAGE = IOEp_Generic def __init__(self, tracer, epid): super().__init__(tracer, epid) self.state.txbuf = EPState() self.state.rxbuf = EPState() self.state.shmem_iova = None self.state.verbose = 1 def start(self): #self.add_mon() self.create_bufs() def create_bufs(self): if not self.state.shmem_iova: return self.txbuf = IORingBuf(self, self.state.txbuf, self.state.shmem_iova) self.rxbuf = IORingBuf(self, self.state.rxbuf, self.state.shmem_iova + 0x4000) def add_mon(self): if self.state.shmem_iova: iomon.add(self.state.shmem_iova, 32768, name=f"{self.name}.shmem@{self.state.shmem_iova:08x}", offset=0) Init = msg_log(0x80, DIR.TX) Init_Ack = msg_log(0xa0, DIR.RX) GetBuf = msg_log(0x89, DIR.RX) Shutdown = msg_log(0xc0, DIR.TX) Shutdown_Ack = msg_log(0xc1, DIR.RX) @msg(0xa1, DIR.TX, IOEp_SetBuf_Ack) def GetBuf_Ack(self, msg): self.state.shmem_iova = msg.IOVA #self.add_mon() @msg(0xa2, DIR.TX, IOEp_Send) def Send(self, msg): for data in self.txbuf.read(wptr=msg.WPTR): if self.state.verbose >= 1: self.log(f">TX rptr={self.txbuf.state.rptr:#x}") chexdump(data) return True Hello = msg_log(0xa3, DIR.TX) @msg(0x85, DIR.RX, IOEpMessage) def Recv(self, msg): for data in self.rxbuf.read(): if self.state.verbose >= 1: self.log(f"<RX rptr={self.rxbuf.state.rptr:#x}") chexdump(data) return True @msg(0x8b, DIR.RX) def BufInitialized(self, msg): self.create_bufs() self.txbuf.init() self.rxbuf.init()