mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-26 16:30:17 +00:00
4555cc5148
Signed-off-by: Hector Martin <marcan@marcan.st>
140 lines
3.6 KiB
Python
Executable file
140 lines
3.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: MIT
|
|
import sys, pathlib
|
|
sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))
|
|
|
|
import struct
|
|
from construct import *
|
|
|
|
from m1n1.setup import *
|
|
from m1n1.shell import run_shell
|
|
from m1n1.hw.dart import DART, DARTRegs
|
|
from m1n1.fw.asc import StandardASC, ASCDummyEndpoint
|
|
|
|
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):
|
|
assert self.index == other.index
|
|
|
|
for key in self.keys():
|
|
if self[key] != other[key]:
|
|
print(f"Differs: {key:4s} = {self[key]} / {other[key]}")
|
|
|
|
def to_bytes(self):
|
|
return bytes(self.blob)
|
|
|
|
|
|
class AOPClient(StandardASC):
|
|
ENDPOINTS = {
|
|
0x20: ASCDummyEndpoint,
|
|
0x21: ASCDummyEndpoint,
|
|
0x22: ASCDummyEndpoint,
|
|
0x23: ASCDummyEndpoint,
|
|
0x24: ASCDummyEndpoint,
|
|
0x25: ASCDummyEndpoint,
|
|
0x26: ASCDummyEndpoint,
|
|
0x27: ASCDummyEndpoint,
|
|
0x28: ASCDummyEndpoint
|
|
}
|
|
|
|
def __init__(self, u, adtpath, dart=None):
|
|
node = u.adt[adtpath]
|
|
self.base = node.get_reg(0)[0]
|
|
self.fw_base, self.fw_len = node.get_reg(2)
|
|
|
|
super().__init__(u, self.base, dart)
|
|
|
|
def _bootargs_span(self):
|
|
base = self.fw_base + self.p.read32(self.fw_base + 0x224)
|
|
length = self.p.read32(self.fw_base + 0x228)
|
|
|
|
return (base, length)
|
|
|
|
def read_bootargs(self):
|
|
blob = self.iface.readmem(*self._bootargs_span())
|
|
return ASCArgumentSection(blob)
|
|
|
|
def write_bootargs(self, args):
|
|
base, _ = self._bootargs_span()
|
|
self.iface.writemem(base, args.to_bytes())
|
|
|
|
def update_bootargs(self, keyvals):
|
|
args = self.read_bootargs()
|
|
args.update(keyvals)
|
|
self.write_bootargs(args)
|
|
|
|
p.dapf_init_all()
|
|
|
|
dart = DART.from_adt(u, "/arm-io/dart-aop")
|
|
dart.initialize()
|
|
|
|
dart.regs.TCR[0].set( BYPASS_DAPF=0, BYPASS_DART=0, TRANSLATE_ENABLE=1)
|
|
dart.regs.TCR[15].set(BYPASS_DAPF=0, BYPASS_DART=1, TRANSLATE_ENABLE=0)
|
|
|
|
aop = AOPClient(u, "/arm-io/aop", dart)
|
|
|
|
aop.update_bootargs({
|
|
'p0CE': 0x20000,
|
|
# 'laCn': 0x0,
|
|
# 'tPOA': 0x1,
|
|
})
|
|
|
|
aop.verbose = 4
|
|
|
|
try:
|
|
aop.boot()
|
|
except KeyboardInterrupt:
|
|
pass
|
|
|
|
run_shell(locals())
|