From 6a4eafb96ea1e9b1dd3ec050a3fabb9a11274910 Mon Sep 17 00:00:00 2001 From: sys64738 Date: Thu, 26 Aug 2021 04:37:38 +0200 Subject: [PATCH] dpctl storage stuff (untested) --- host/dpctl/__init__.py | 32 +++++++++++++++++++ host/dpctl/commands.py | 32 +++++++++++++++++++ host/dpctl/protocol.py | 70 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/host/dpctl/__init__.py b/host/dpctl/__init__.py index 409c6a3..f65eb1b 100644 --- a/host/dpctl/__init__.py +++ b/host/dpctl/__init__.py @@ -52,6 +52,26 @@ def dpctl_do(args: Any) -> int: return 1 return devcmds.sump_overclock_set(conn, oven) + def sto_info(conn, args): + return devcmds.storage_info(conn) + def sto_flush(conn, args): + return devcmds.storage_flush(conn) + def sto_get(conn, args): + return devcmds.storage_get(mode) + + def storage(conn, args): + scmds = { + 'info', sto_info, + 'flush', sto_flush, + 'get', sto_get + } + + ssubfn = stocmds.get(args.storage, None) + if ssubfn is None: + print("Unknown 'storage' subcommand '%s'" % args.storage) + return 1 + + return ssubfn(conn, args) #print(repr(args)) cmds = { @@ -64,6 +84,8 @@ def dpctl_do(args: Any) -> int: 'tempsensor': tempsensor, 'jtag-scan': jtag_scan, 'sump-overclock': sump_ovclk, + + 'storage': storage, } if args.subcmd is None: @@ -142,6 +164,16 @@ def main() -> int: bootloader = subcmds.add_parser("bootloader", help="Set the device in bootloader mode") + # persistent storage commands + storage = subcmds.add_parser("storage", help="Persistent storage commands") + storagecmd = parser.add_subparsers(required=False, metavar="storage", + dest="storage", help="Persistent storage subcommand") + storagehdr = storagecmd.add_parser("info", help="Get persistent storage info") + storageflush = storagecmd.add_parser("flush", help="Flush persistent storage data to storage medium") + storageget = storagecmd.add_parser("get", help="Get data of a particular mode") + storageget.add_arguments('mode', default=None, nargs='?', + help="Mode to get data of. Defaults to the current mode, 'all' means all modes.") + # mode 1 commands usbhwfctl = subcmds.add_parser("uart-cts-rts", help="Get, enable/disable"+\ " UART hardware flow control") diff --git a/host/dpctl/commands.py b/host/dpctl/commands.py index 580c8d3..fd89d1f 100644 --- a/host/dpctl/commands.py +++ b/host/dpctl/commands.py @@ -85,6 +85,38 @@ def set_mode(dev: DPDevice, mode: int) -> int: # --- +def storage_info(dev: DPDevice) -> int: + try: + res = dev.storage_info() + print(repr(res)) # TODO + return 0 + except Exception as e: + print("Could not get storage info: %s" % str(e)) + return 1 + + +def storage_flush(dev: DPDevice) -> int: + try: + dev.storage_flush() + return 0 + except Exception as e: + print("Could not flush persistent storage: %s" % str(e)) + return 1 + + +def storage_get(dev: DPDevice, mode: int) -> int: + try: + res = dev.storage_get(mode) + print(repr(res)) # TODO + return 0 + except Exception as e: + print("Could not get storage data of mode %d: %s" % (mode, str(e))) + return 1 + + +# --- + + def uart_hw_flowctl_get(dev: DPDevice) -> int: try: res = dev.m1_usb_hw_flowctl_get() diff --git a/host/dpctl/protocol.py b/host/dpctl/protocol.py index e73921e..8419b0c 100644 --- a/host/dpctl/protocol.py +++ b/host/dpctl/protocol.py @@ -18,6 +18,51 @@ STAT_BADARG = 0x04 STAT_ILLSTATE = 0x05 +class StorageInfoMode(NamedTuple): + version: int + datasize: int + offset: int + mode: int + data_djb2: int + + def from_bytes(b: bytes) -> StorageInfoMode: + assert len(b) == 12 + v, ds, oam, d = struct.unpack('> 28) & 15, d) + + def list_from_bytes(b: bytes) -> List[StorageInfoMode]: + nelem = len(b) // 12 + assert nelem * 12 == len(b) + + r = [None]*nelem + for i in range(nelem): r[i] = StorageInfoMode.from_bytes(b[(i*12):((i+1)*12)]) + return [re for re in r if re.version != 0xffff and re.datasize != 0xffff] + + +class StorageInfo(NamedTuple): + magic: bytes + version: int + curmode: int + nmodes: int + reserved: bytes + table_djb2: int + mode_data: List[StorageInfoMode] + + def from_bytes(b: bytes) -> StorageInfo: + assert len(b) == 256 + + mag = b[:16] + ver, cm, nm = struct.unpack(' StorageInfo: + cmd = bytearray(b'\x0c') + self.write(b'\x0c') + stat, pl = self.read_resp() + check_statpl(stat, pl, "get storage info", 256, 256) + + return StorageInfo.from_bytes(pl) + + def storage_flush(self): + self.write(b'\x0e') + stat, pl = self.read_resp() + check_statpl(stat, pl, "flush storage", 0, 0) + + def storage_get(self, mode: int) -> bytes: + cmd = bytearray(b'\x0d\x00') + cmd[1] = mode + self.write(cmd) + stat, pl = self.read_resp() + check_statpl(stat, pl, "get storage data", -1, -1) + + return pl # TODO: parse + + # mode 1 commands def m1_usb_hw_flowctl_get(self) -> bool: