# SPDX-License-Identifier: MIT import struct from collections import defaultdict, deque from enum import IntEnum from ..trace.asc import ASCRegs from ..utils import * class BootRomMsg(IntEnum): GET_STATUS = 2 BOOT_TZ0 = 5 BOOT_IMG4 = 6 SET_SHMEM = 0x18 class BootRomStatus(IntEnum): STATUS_OK = 0x66 STATUS_BOOT_TZ0_DONE = 0x69 STATUS_BOOT_IMG4_DONE = 0x6A STATUS_BOOT_UNK_DONE = 0xD2 class SEPMessage(Register64): EP = 7, 0 TAG = 15, 8 TYPE = 23, 16 PARAM = 31, 24 DATA = 63, 32 # TODO: make this class actually own the shared memory instead of just # generating a static buffer if we actually need to read/write to # individual items inside the shmem buffer class SEPShMem: def __init__(self): self.items = [] self.offset = 0x4000 def add_item(self, name, data, min_size=0): sz = align_up(len(data) + 4, 0x4000) sz = max(sz, min_size) self.items.append((name, self.offset, sz, struct.pack("> 0xC) ) self.send_msg( SEPMessage(EP=0xFE, TYPE=BootRomMsg.SET_SHMEM, DATA=self.SHMEM_IOVA >> 0xC) ) self.expect_msg(0xFF, BootRomStatus.STATUS_BOOT_IMG4_DONE) self.unmap_sepfw() def expect_msg(self, ep, type): msg = self.recv_msg(ep, block=True) if msg.TYPE != type: raise ValueError( f"Expected type 0x{type:x} but got message with type 0x{msg.TYPE:x}" ) def send_msg(self, msg): self.asc.INBOX0 = msg.value self.asc.INBOX1 = 0 def _recv_single_msg(self): msg = SEPMessage(self.asc.OUTBOX0.val) _ = self.asc.OUTBOX1.val return msg def _try_recv_msgs(self): while not self.asc.OUTBOX_CTRL.reg.EMPTY: msg = self._recv_single_msg() self.msgs[msg.EP].append(msg) self._handle_ep_discovery() def _handle_ep_discovery(self): while len(self.msgs[0xFD]): msg = self.msgs[0xFD].popleft() if msg.TYPE == 0: cs = "".join( [chr((msg.DATA >> (i * 8)) & 0xFF) for i in range(3, -1, -1)] ) self.epnum2name[msg.PARAM] = cs self.epname2num[cs] = msg.PARAM def recv_msg(self, ep, block=False): self._try_recv_msgs() while block and len(self.msgs[ep]) < 1: self._try_recv_msgs() if len(self.msgs[ep]): return self.msgs[ep].popleft() else: return None