summaryrefslogtreecommitdiff
path: root/tools/proxyclient/m1n1/fw/smc.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/proxyclient/m1n1/fw/smc.py')
-rw-r--r--tools/proxyclient/m1n1/fw/smc.py202
1 files changed, 202 insertions, 0 deletions
diff --git a/tools/proxyclient/m1n1/fw/smc.py b/tools/proxyclient/m1n1/fw/smc.py
new file mode 100644
index 0000000..204501c
--- /dev/null
+++ b/tools/proxyclient/m1n1/fw/smc.py
@@ -0,0 +1,202 @@
+# SPDX-License-Identifier: MIT
+import struct
+
+from ..utils import *
+
+from .asc import StandardASC
+from .asc.base import *
+
+SMC_READ_KEY = 0x10
+SMC_WRITE_KEY = 0x11
+SMC_GET_KEY_BY_INDEX = 0x12
+SMC_GET_KEY_INFO = 0x13
+SMC_INITIALIZE = 0x17
+SMC_NOTIFICATION = 0x18
+SMC_RW_KEY = 0x20
+
+class SMCMessage(Register64):
+ TYPE = 7, 0
+ UNK = 11, 8, Constant(0)
+ ID = 15, 12
+
+class SMCInitialize(SMCMessage):
+ TYPE = 7, 0, Constant(SMC_INITIALIZE)
+
+class SMCGetKeyInfo(SMCMessage):
+ TYPE = 7, 0, Constant(SMC_GET_KEY_INFO)
+ KEY = 63, 32
+
+class SMCGetKeyByIndex(SMCMessage):
+ TYPE = 7, 0, Constant(SMC_GET_KEY_BY_INDEX)
+ INDEX = 63, 32
+
+class SMCWriteKey(SMCMessage):
+ TYPE = 7, 0, Constant(SMC_WRITE_KEY)
+ SIZE = 23, 16
+ KEY = 63, 32
+
+class SMCReadKey(SMCMessage):
+ TYPE = 7, 0, Constant(SMC_READ_KEY)
+ SIZE = 23, 16
+ KEY = 63, 32
+
+class SMCReadWriteKey(SMCMessage):
+ TYPE = 7, 0, Constant(SMC_RW_KEY)
+ RSIZE = 23, 16
+ WSIZE = 31, 24
+ KEY = 63, 32
+
+class SMCResult(Register64):
+ RESULT = 7, 0
+ ID = 15, 12
+ SIZE = 31, 16
+ VALUE = 63, 32
+
+class SMCError(Exception):
+ pass
+
+class SMCEndpoint(ASCBaseEndpoint):
+ BASE_MESSAGE = SMCMessage
+ SHORT = "smcep"
+ TYPE_MAP = {
+ "ui64": ("<Q", None),
+ "ui32": ("<I", None),
+ "ui16": ("<H", None),
+ "ui8 ": ("<B", None),
+ "si64": ("<q", None),
+ "si32": ("<i", None),
+ "si16": ("<h", None),
+ "si8 ": ("<b", None),
+ "flag": ("<B", None),
+ "flt ": ("<f", None),
+ "hex_": (None, hexdump),
+ "ch8*": (None, lambda c: c.split(b"\x00")[0]),
+ "ioft": ("<Q", None),
+ }
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.shmem = None
+ self.msgid = 0
+ self.outstanding = set()
+ self.ret = {}
+
+ def start(self):
+ self.send(SMCInitialize(ID = 0))
+ self.msgid += 1 # important!
+ while self.shmem is None:
+ self.asc.work()
+
+ def new_msgid(self):
+ mid = (self.msgid & 0xF)
+ self.msgid += 1
+ assert(mid not in self.outstanding)
+ self.outstanding.add(mid)
+ return mid
+
+ def cmd(self, cmd):
+ cmd.ID = self.new_msgid()
+ self.send(cmd)
+ while cmd.ID in self.outstanding:
+ self.asc.work()
+ ret = self.ret[cmd.ID]
+ if ret.RESULT != 0:
+ raise SMCError(f"SMC error {ret}", ret)
+ return ret
+
+ def write(self, key, data):
+ key = int.from_bytes(key.encode("ascii"), byteorder="big")
+ self.asc.iface.writemem(self.shmem, data)
+ self.cmd(SMCWriteKey(KEY = key, SIZE = len(data)))
+
+ def read(self, key, size):
+ key = int.from_bytes(key.encode("ascii"), byteorder="big")
+ ret = self.cmd(SMCReadKey(KEY = key, SIZE = size))
+ if size <= 4:
+ return struct.pack("<I", ret.VALUE)[:size]
+ else:
+ return self.asc.iface.readmem(self.shmem, ret.SIZE)
+
+ def rw(self, key, data, outsize):
+ key = int.from_bytes(key.encode("ascii"), byteorder="big")
+ self.asc.iface.writemem(self.shmem, data)
+ ret = self.cmd(SMCReadWriteKey(KEY=key, RSIZE=outsize, WSIZE=len(data)))
+ if outsize <= 4:
+ return struct.pack("<I", ret.VALUE)[:outsize]
+ else:
+ return self.asc.iface.readmem(self.shmem, ret.SIZE)
+
+ def get_key_by_index(self, index):
+ ret = self.cmd(SMCGetKeyByIndex(INDEX = index))
+ key = ret.VALUE.to_bytes(4, byteorder="little").decode("ascii")
+ return key
+
+ def get_key_info(self, key):
+ key = int.from_bytes(key.encode("ascii"), byteorder="big")
+ ret = self.cmd(SMCGetKeyInfo(KEY = key))
+ info = self.asc.iface.readmem(self.shmem, 6)
+ length, type, flags = struct.unpack("B4sB", info)
+ return length, type.decode("ascii"), flags
+
+ def read64(self, key):
+ return struct.unpack("<Q", self.read(key, 8))[0]
+
+ def read32(self, key):
+ return struct.unpack("<I", self.read(key, 4))[0]
+
+ def read16(self, key):
+ return struct.unpack("<H", self.read(key, 2))[0]
+
+ def read8(self, key):
+ return struct.unpack("<B", self.read(key, 1))[0]
+
+ def read32b(self, key):
+ return struct.unpack(">I", self.read(key, 4))[0]
+
+ def write64(self, key, data):
+ self.write(key, struct.pack("<Q", data))
+
+ def write32(self, key, data):
+ self.write(key, struct.pack("<I", data))
+
+ def write16(self, key, data):
+ self.write(key, struct.pack("<H", data))
+
+ def write8(self, key, data):
+ self.write(key, struct.pack("<B", data))
+
+ def rw32(self, key, data):
+ return struct.unpack("<I", self.rw(key, struct.pack("<I", data), 4))[0]
+
+ def read_type(self, key, size, typecode):
+ fmt, func = self.TYPE_MAP.get(typecode, (None, None))
+
+ val = self.read(key, size)
+
+ if fmt:
+ val = struct.unpack(fmt, val)[0]
+ if func:
+ val = func(val)
+ return val
+
+ def handle_msg(self, msg0, msg1):
+ if self.shmem is None:
+ self.log("Starting up")
+ self.shmem = msg0
+ else:
+ msg = SMCResult(msg0)
+ ret = msg.RESULT
+ mid = msg.ID
+ if ret == SMC_NOTIFICATION:
+ self.log(f"Notification: {msg.VALUE:#x}")
+ return True
+ #print(f"msg {mid} return value {ret}")
+ self.outstanding.discard(mid)
+ self.ret[mid] = msg
+
+ return True
+
+class SMCClient(StandardASC):
+ ENDPOINTS = {
+ 0x20: SMCEndpoint,
+ }