mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-29 18:00:18 +00:00
3a42f80a73
Signed-off-by: Hector Martin <marcan@marcan.st>
80 lines
2.3 KiB
Python
Executable file
80 lines
2.3 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
import argparse, pathlib
|
|
|
|
parser = argparse.ArgumentParser(description='(Linux) kernel loader for m1n1')
|
|
parser.add_argument('payload', type=pathlib.Path)
|
|
parser.add_argument('-1', '--el1', action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
from setup import *
|
|
from tgtypes import *
|
|
|
|
payload = args.payload.read_bytes()
|
|
|
|
obj = MachO.parse(payload)
|
|
|
|
vmin, vmax = (1 << 64), 0
|
|
|
|
entry = None
|
|
|
|
for cmd in obj.cmds:
|
|
if cmd.cmd == LoadCmdType.SEGMENT_64:
|
|
vmin = min(vmin, cmd.args.vmaddr)
|
|
vmax = max(vmax, cmd.args.vmaddr + cmd.args.vmsize)
|
|
elif cmd.cmd == LoadCmdType.UNIXTHREAD:
|
|
entry = cmd.args[0].data.pc
|
|
|
|
memory_size = vmax - vmin
|
|
|
|
# FIXME: this will currently still waste the whole m1n1 size including payload area (64+MB) on each
|
|
# chainload. The best way to fix this is to support in-place chainloading, which has other
|
|
# advantages.
|
|
|
|
try:
|
|
# Try to use the m1n1 heap to avoid wasting 128MB RAM on every load
|
|
new_base = p.memalign(0x10000, memory_size)
|
|
except:
|
|
# Fall back to proxy heap, which will be at the right place in old versions
|
|
new_base = u.memalign(0x10000, memory_size)
|
|
|
|
for cmd in obj.cmds:
|
|
if cmd.cmd == LoadCmdType.SEGMENT_64:
|
|
if cmd.args.fileoff == 0:
|
|
continue # do not load mach-o headers, not needed for now
|
|
dest = cmd.args.vmaddr - vmin + new_base
|
|
end = min(len(payload), cmd.args.fileoff + cmd.args.filesize)
|
|
size = end - cmd.args.fileoff
|
|
print("Loading %d bytes from 0x%x to 0x%x" % (size, cmd.args.fileoff, dest))
|
|
u.compressed_writemem(dest, payload[cmd.args.fileoff:end], True)
|
|
if cmd.args.vmsize > size:
|
|
clearsize = cmd.args.vmsize - size
|
|
print("Zeroing %d bytes from 0x%x to 0x%x" % (clearsize, dest + size, dest + size + clearsize))
|
|
p.memset8(dest + size, 0, clearsize)
|
|
|
|
p.dc_cvau(new_base, memory_size)
|
|
p.ic_ivau(new_base, memory_size)
|
|
|
|
entry -= vmin
|
|
entry += new_base
|
|
|
|
if args.el1:
|
|
print("Setting up EL1 config")
|
|
|
|
# Enable physical timer for EL1
|
|
u.msr(CNTHCTL_EL2, 3 << 10) # EL1PTEN | EL1PCTEN
|
|
|
|
# Unredirect IRQs/FIQs
|
|
u.msr(HCR_EL2, u.mrs(HCR_EL2) & ~(3 << 3)) # ~(IMO | FMO)
|
|
|
|
print("Jumping to 0x%x" % entry)
|
|
|
|
try:
|
|
p.mmu_shutdown()
|
|
except:
|
|
pass
|
|
|
|
p.reboot(entry, u.ba_addr, el1=args.el1)
|
|
|
|
iface.nop()
|
|
print("Proxy is alive again")
|