mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-25 08:00:17 +00:00
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:
parent
3a8068a73d
commit
65501cdd70
3 changed files with 112 additions and 94 deletions
|
@ -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"]
|
||||
|
|
112
proxyclient/m1n1/fw/aop/base.py
Normal file
112
proxyclient/m1n1/fw/aop/base.py
Normal 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)
|
|
@ -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)
|
Loading…
Reference in a new issue