From 65501cdd7060b55c3d52375712976dcf7fae2f96 Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Tue, 9 Jan 2024 12:40:12 +0900 Subject: [PATCH] m1n1.fw.aop: Fix 13.5 bootargs ABI break + rename Move from __init__.py to base.py so it can be imported. Signed-off-by: Eileen Yoon --- proxyclient/m1n1/fw/aop/__init__.py | 30 -------- proxyclient/m1n1/fw/aop/base.py | 112 ++++++++++++++++++++++++++++ proxyclient/m1n1/fw/aop/bootargs.py | 64 ---------------- 3 files changed, 112 insertions(+), 94 deletions(-) create mode 100644 proxyclient/m1n1/fw/aop/base.py delete mode 100644 proxyclient/m1n1/fw/aop/bootargs.py diff --git a/proxyclient/m1n1/fw/aop/__init__.py b/proxyclient/m1n1/fw/aop/__init__.py index 68282325..548d2d44 100644 --- a/proxyclient/m1n1/fw/aop/__init__.py +++ b/proxyclient/m1n1/fw/aop/__init__.py @@ -1,31 +1 @@ # SPDX-License-Identifier: MIT -from .bootargs import ASCArgumentSection - -class AOPBase: - def __init__(self, u, adtnode): - self.fw_base, self.fw_len = adtnode.get_reg(2) - if u.adt["arm-io"].compatible[0] == "arm-io,t6000": - # argh - self.fw_base -= 0x2_0000_0000 - - @property - def _bootargs_span(self): - base = self.fw_base + self.u.proxy.read32(self.fw_base + 0x224) - length = self.u.proxy.read32(self.fw_base + 0x228) - - return (base, length) - - def read_bootargs(self): - blob = self.u.proxy.iface.readmem(*self._bootargs_span) - return ASCArgumentSection(blob) - - def write_bootargs(self, args): - base, _ = self._bootargs_span - self.u.proxy.iface.writemem(base, args.to_bytes()) - - def update_bootargs(self, keyvals): - args = self.read_bootargs() - args.update(keyvals) - self.write_bootargs(args) - -__all__ = ["ASCArgumentSection", "AOPBase"] diff --git a/proxyclient/m1n1/fw/aop/base.py b/proxyclient/m1n1/fw/aop/base.py new file mode 100644 index 00000000..0742073e --- /dev/null +++ b/proxyclient/m1n1/fw/aop/base.py @@ -0,0 +1,112 @@ +# SPDX-License-Identifier: MIT +import struct +from construct import * +from copy import deepcopy + +def round_up(x, y): return ((x + (y - 1)) & (-y)) +def round_down(x, y): return (x - (x % y)) + +AOPBootargsItem = Struct( + "key" / PaddedString(4, "utf8"), + "size" / Int32ul, +) + +class AOPBootargs: + def __init__(self, bytes_): + self.blob = bytearray(bytes_) + self.index = self.build_index(self.blob) + + def build_index(self, blob): + off = 0 + fields = [] + while off < len(blob): + item = AOPBootargsItem.parse(blob[off:off+AOPBootargsItem.sizeof()]) + off += AOPBootargsItem.sizeof() + fields.append((item.key, (off, item.size))) + off += item.size + if off > len(blob): + raise ValueError('blob overran during parsing') + return dict(fields) + + def items(self): + for key, span in self.index.items(): + off, length = span + yield key, self.blob[off:off + length] + + def __getitem__(self, key): + off, length = self.index[key] + return bytes(self.blob[off:off + length]) + + def __setitem__(self, key, value): + off, length = self.index[key] + if type(value) is int: + value = int.to_bytes(value, length, byteorder='little') + elif type(value) is str: + value = value.encode('ascii') + if len(value) > length: + raise ValueError(f'field {key:s} overflown') + self.blob[off:off + length] = value + + def update(self, keyvals): + for key, val in keyvals.items(): + self[key] = val + + def keys(self): + return self.index.keys() + + def dump(self, logger): + for key, val in self.items(): + logger(f"{key:4s} = {val}") + + def dump_diff(self, other, logger): + assert self.index == other.index + for key in self.keys(): + if self[key] != other[key]: + logger(f"\t{key:4s} = {self[key]} -> {other[key]}") + + def to_bytes(self): + return bytes(self.blob) + +class AOPBase: + def __init__(self, u): + self.u = u + self.nub_base = u.adt["/arm-io/aop/iop-aop-nub"].region_base + if u.adt["arm-io"].compatible[0] == "arm-io,t6000": + # argh + self.nub_base -= 0x2_0000_0000 + + @property + def _bootargs_span(self): + """ + [cpu1] MMIO: R.4 0x24ac0022c (aop[2], offset 0x22c) = 0xaffd8 // offset + [cpu1] MMIO: R.4 0x24ac00230 (aop[2], offset 0x230) = 0x2ae // size + [cpu1] MMIO: R.4 0x24ac00234 (aop[2], offset 0x234) = 0x82000 // va? low + [cpu1] MMIO: R.4 0x24ac00238 (aop[2], offset 0x238) = 0x0 // va? high + [cpu1] MMIO: R.4 0x24ac0023c (aop[2], offset 0x23c) = 0x4ac82000 // phys low + [cpu1] MMIO: R.4 0x24ac00240 (aop[2], offset 0x240) = 0x2 // phys high + [cpu1] MMIO: W.4 0x24acaffd8 (aop[2], offset 0xaffd8) = 0x53544b47 // start of bootargs + [cpu1] MMIO: W.4 0x24acaffdc (aop[2], offset 0xaffdc) = 0x8 + [cpu1] MMIO: W.4 0x24acaffe0 (aop[2], offset 0xaffe0) = 0x73eed2a3 + ... + [cpu1] MMIO: W.4 0x24acb0280 (aop[2], offset 0xb0280) = 0x10000 + [cpu1] MMIO: W.4 0x24acb0284 (aop[2], offset 0xb0284) = 0x0 // end of bootargs + """ + offset = self.u.proxy.read32(self.nub_base + 0x22c) # 0x224 in 12.3 + size = self.u.proxy.read32(self.nub_base + 0x230) # 0x228 in 12.3 + return (self.nub_base + offset, size) + + def read_bootargs(self): + addr, size = self._bootargs_span + blob = self.u.proxy.iface.readmem(addr, size) + return AOPBootargs(blob) + + def write_bootargs(self, args): + base, _ = self._bootargs_span + self.u.proxy.iface.writemem(base, args.to_bytes()) + + def update_bootargs(self, keyval, logger=print): + args = self.read_bootargs() + old = deepcopy(args) + args.update(keyval) + self.write_bootargs(args) + old.dump_diff(args, logger) diff --git a/proxyclient/m1n1/fw/aop/bootargs.py b/proxyclient/m1n1/fw/aop/bootargs.py deleted file mode 100644 index 100e4f30..00000000 --- a/proxyclient/m1n1/fw/aop/bootargs.py +++ /dev/null @@ -1,64 +0,0 @@ -# SPDX-License-Identifier: MIT - -class ASCArgumentSection: - def __init__(self, bytes_): - self.blob = bytearray(bytes_) - self.index = self.build_index() - - def build_index(self): - off = 0 - fields = [] - while off < len(self.blob): - snip = self.blob[off:] - key = snip[0:4] - length = int.from_bytes(snip[4:8], byteorder='little') - fields.append((key.decode('ascii'), (off + 8, length))) - off += 8 + length - - if off > len(self.blob): - raise ValueError('blob overran during parsing') - - return dict(fields) - - def items(self): - for key, span in self.index.items(): - off, length = span - yield key, self.blob[off:off + length] - - def __getitem__(self, key): - off, length = self.index[key] - return bytes(self.blob[off:off + length]) - - def __setitem__(self, key, value): - off, length = self.index[key] - - if type(value) is int: - value = int.to_bytes(value, length, byteorder='little') - elif type(value) is str: - value = value.encode('ascii') - - if len(value) > length: - raise ValueError(f'field {key:s} overflown') - - self.blob[off:off + length] = value - - def update(self, keyvals): - for key, val in keyvals.items(): - self[key] = val - - def keys(self): - return self.index.keys() - - def dump(self): - for key, val in self.items(): - print(f"{key:4s} = {val}") - - def dump_diff(self, other, logger): - assert self.index == other.index - - for key in self.keys(): - if self[key] != other[key]: - logger(f"\t{key:4s} = {self[key]} -> {other[key]}") - - def to_bytes(self): - return bytes(self.blob)