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 <eyn@gmx.com>
This commit is contained in:
Eileen Yoon 2024-01-09 12:40:12 +09:00 committed by Hector Martin
parent 3a8068a73d
commit 65501cdd70
3 changed files with 112 additions and 94 deletions

View file

@ -1,31 +1 @@
# SPDX-License-Identifier: MIT # 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"]

View file

@ -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)

View file

@ -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)