2021-02-05 09:30:43 +00:00
|
|
|
#!/usr/bin/env python3
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-03-04 13:40:48 +00:00
|
|
|
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()
|
|
|
|
|
2021-01-29 06:19:34 +00:00
|
|
|
from setup import *
|
2021-02-06 07:34:35 +00:00
|
|
|
from tgtypes import *
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-03-04 13:40:48 +00:00
|
|
|
payload = args.payload.read_bytes()
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-02-06 07:34:35 +00:00
|
|
|
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
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-01-29 06:19:34 +00:00
|
|
|
# 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.
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-02-06 07:34:35 +00:00
|
|
|
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)
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-02-06 07:34:35 +00:00
|
|
|
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))
|
2021-02-14 22:26:50 +00:00
|
|
|
u.compressed_writemem(dest, payload[cmd.args.fileoff:end], True)
|
2021-02-06 07:34:35 +00:00
|
|
|
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)
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-02-06 07:34:35 +00:00
|
|
|
p.dc_cvau(new_base, memory_size)
|
|
|
|
p.ic_ivau(new_base, memory_size)
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-02-06 07:34:35 +00:00
|
|
|
entry -= vmin
|
|
|
|
entry += new_base
|
2021-01-30 12:55:51 +00:00
|
|
|
|
2021-03-28 10:13:18 +00:00
|
|
|
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)
|
|
|
|
|
2021-01-14 18:56:45 +00:00
|
|
|
print("Jumping to 0x%x" % entry)
|
|
|
|
|
2021-01-30 12:55:51 +00:00
|
|
|
try:
|
|
|
|
p.mmu_shutdown()
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2021-03-04 13:40:48 +00:00
|
|
|
p.reboot(entry, u.ba_addr, el1=args.el1)
|
2021-01-14 18:56:45 +00:00
|
|
|
|
|
|
|
iface.nop()
|
|
|
|
print("Proxy is alive again")
|