summaryrefslogtreecommitdiff
path: root/tools/proxyclient/m1n1/hw/sep.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/proxyclient/m1n1/hw/sep.py')
-rw-r--r--tools/proxyclient/m1n1/hw/sep.py169
1 files changed, 169 insertions, 0 deletions
diff --git a/tools/proxyclient/m1n1/hw/sep.py b/tools/proxyclient/m1n1/hw/sep.py
new file mode 100644
index 0000000..f206a71
--- /dev/null
+++ b/tools/proxyclient/m1n1/hw/sep.py
@@ -0,0 +1,169 @@
+# 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("<I", len(data)) + data))
+ self.offset += sz
+
+ def finalize(self):
+ bfr = bytearray(b"\x00" * self.offset)
+ for i, (name, offset, sz, data) in enumerate(self.items):
+ bfr[i * 16 : i * 16 + 12] = struct.pack("<4sII", name, sz, offset)
+ bfr[offset : offset + len(data)] = data
+
+ cnt = len(self.items)
+ bfr[cnt * 16 : cnt * 16 + 4] = b"llun" # null
+
+ return bfr
+
+
+class SEP:
+ SHMEM_IOVA = 0xBEEF0000
+ FW_IOVA = 0xDEAD0000
+
+ def __init__(self, proxy, iface, utils):
+ self.i = iface
+ self.p = proxy
+ self.u = utils
+
+ self.sep_base = self.u.adt["/arm-io/sep"].get_reg(0)[0]
+ self.dart_base = self.u.adt["/arm-io/dart-sep"].get_reg(0)[0]
+
+ self.asc = ASCRegs(self.u, self.sep_base)
+
+ self.dart_handle = self.p.dart_init(self.dart_base, 0)
+
+ self.epnum2name = {}
+ self.epname2num = {}
+ self.msgs = defaultdict(deque)
+
+ def map_sepfw(self):
+ sepfw_addr, sepfw_size = self.u.adt["/chosen/memory-map"].SEPFW
+ self.p.dart_map(self.dart_handle, self.FW_IOVA, sepfw_addr, sepfw_size)
+
+ def unmap_sepfw(self):
+ _, sepfw_size = self.u.adt["/chosen/memory-map"].SEPFW
+ self.p.dart_unmap(self.dart_handle, self.FW_IOVA, sepfw_size)
+
+ def create_shmem(self):
+ shmem = SEPShMem()
+
+ # PNIC - panic buffer
+ shmem.add_item(b"CINP", b"\x00", 0x8000)
+
+ # ALPO / SIPS - unknown img4-like blobs from the ADT
+ addr, sz = self.u.adt["/chosen/boot-object-manifests"].lpol
+ shmem.add_item(b"OPLA", self.i.readmem(addr, sz))
+ addr, sz = self.u.adt["/chosen/boot-object-manifests"].ibot
+ shmem.add_item(b"IPIS", self.i.readmem(addr, sz))
+
+ bfr = shmem.finalize()
+ sz = align_up(len(bfr), 0x4000)
+ self.shmem = self.u.heap.memalign(0x4000, 0x30000)
+ self.i.writemem(self.shmem, bfr)
+ self.p.dart_map(self.dart_handle, self.SHMEM_IOVA, self.shmem, 0x30000)
+
+ def boot(self):
+ self.create_shmem()
+ self.map_sepfw()
+
+ self.send_msg(SEPMessage(EP=0xFF, TYPE=BootRomMsg.GET_STATUS))
+ self.expect_msg(0xFF, BootRomStatus.STATUS_OK)
+
+ self.send_msg(SEPMessage(EP=0xFF, TYPE=BootRomMsg.BOOT_TZ0))
+ self.expect_msg(0xFF, BootRomStatus.STATUS_BOOT_TZ0_DONE)
+ self.expect_msg(0xFF, BootRomStatus.STATUS_BOOT_UNK_DONE)
+
+ self.send_msg(SEPMessage(EP=0xFF, TYPE=BootRomMsg.GET_STATUS))
+ self.expect_msg(0xFF, BootRomStatus.STATUS_OK)
+
+ self.send_msg(
+ SEPMessage(EP=0xFF, TYPE=BootRomMsg.BOOT_IMG4, DATA=self.FW_IOVA >> 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