2021-02-05 09:30:43 +00:00
|
|
|
#!/usr/bin/env python3
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-05-04 13:45:18 +00:00
|
|
|
import argparse, pathlib, time
|
2021-03-04 13:40:48 +00:00
|
|
|
|
2021-04-14 12:13:19 +00:00
|
|
|
parser = argparse.ArgumentParser(description='Mach-O loader for m1n1')
|
2021-05-12 12:16:33 +00:00
|
|
|
parser.add_argument('-x', '--xnu', action="store_true", help="Load XNU")
|
2021-05-07 17:39:32 +00:00
|
|
|
parser.add_argument('-c', '--call', action="store_true", help="Use call mode")
|
2021-03-04 13:40:48 +00:00
|
|
|
parser.add_argument('payload', type=pathlib.Path)
|
2021-05-07 17:39:32 +00:00
|
|
|
parser.add_argument('boot_args', default=[], nargs="*")
|
2021-03-04 13:40:48 +00:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
2021-01-29 06:19:34 +00:00
|
|
|
from setup import *
|
2021-05-01 06:15:43 +00:00
|
|
|
from tgtypes import BootArgs
|
|
|
|
from macho import MachO
|
2021-04-14 12:13:19 +00:00
|
|
|
import asm
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-05-01 06:15:43 +00:00
|
|
|
macho = MachO(args.payload.read_bytes())
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-05-01 06:15:43 +00:00
|
|
|
image = macho.prepare_image()
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-04-14 12:13:19 +00:00
|
|
|
new_base = u.base
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-05-01 06:15:43 +00:00
|
|
|
entry = macho.entry
|
|
|
|
entry -= macho.vmin
|
2021-02-06 07:34:35 +00:00
|
|
|
entry += new_base
|
2021-01-30 12:55:51 +00:00
|
|
|
|
2021-05-12 12:16:33 +00:00
|
|
|
if args.xnu:
|
2021-05-01 06:15:43 +00:00
|
|
|
sepfw_start, sepfw_length = u.adt["chosen"]["memory-map"].SEPFW
|
2021-04-14 12:13:19 +00:00
|
|
|
else:
|
|
|
|
sepfw_start, sepfw_length = 0, 0
|
|
|
|
|
|
|
|
image_size = align(len(image))
|
|
|
|
sepfw_off = image_size
|
|
|
|
image_size += align(sepfw_length)
|
|
|
|
bootargs_off = image_size
|
2021-05-07 17:39:32 +00:00
|
|
|
bootargs_size = 0x4000
|
|
|
|
image_size += bootargs_size
|
2021-04-14 12:13:19 +00:00
|
|
|
|
|
|
|
print(f"Total region size: 0x{image_size:x} bytes")
|
|
|
|
image_addr = u.malloc(image_size)
|
|
|
|
|
|
|
|
print(f"Loading kernel image (0x{len(image):x} bytes)...")
|
|
|
|
u.compressed_writemem(image_addr, image, True)
|
|
|
|
p.dc_cvau(image_addr, len(image))
|
|
|
|
|
2021-05-12 12:16:33 +00:00
|
|
|
if args.xnu:
|
2021-04-14 12:13:19 +00:00
|
|
|
print(f"Copying SEPFW (0x{sepfw_length:x} bytes)...")
|
|
|
|
p.memcpy8(image_addr + sepfw_off, sepfw_start, sepfw_length)
|
2021-05-05 18:33:35 +00:00
|
|
|
print(f"Adjusting addresses in ADT...")
|
|
|
|
u.adt["chosen"]["memory-map"].SEPFW = (new_base + sepfw_off, sepfw_length)
|
2021-05-07 17:39:32 +00:00
|
|
|
u.adt["chosen"]["memory-map"].BootArgs = (image_addr + bootargs_off, bootargs_size)
|
2021-05-12 12:16:33 +00:00
|
|
|
|
|
|
|
print("Setting secondary CPU RVBARs...")
|
|
|
|
|
|
|
|
rvbar = entry & ~0xfff
|
|
|
|
for cpu in u.adt["cpus"][1:]:
|
2021-05-13 13:44:50 +00:00
|
|
|
addr, size = cpu.cpu_impl_reg
|
2021-05-12 12:16:33 +00:00
|
|
|
print(f" {cpu.name}: [0x{addr:x}] = 0x{rvbar:x}")
|
|
|
|
p.write64(addr, rvbar)
|
|
|
|
|
2021-05-05 18:33:35 +00:00
|
|
|
u.push_adt()
|
2021-04-14 12:13:19 +00:00
|
|
|
|
2021-05-07 17:39:32 +00:00
|
|
|
print("Setting up bootargs...")
|
2021-04-14 12:13:19 +00:00
|
|
|
tba = u.ba.copy()
|
2021-05-01 06:15:43 +00:00
|
|
|
|
2021-05-12 12:16:33 +00:00
|
|
|
if args.xnu:
|
2021-05-01 06:15:43 +00:00
|
|
|
tba.top_of_kernel_data = new_base + image_size
|
|
|
|
else:
|
|
|
|
# SEP firmware is in here somewhere, keep top_of_kdata high so we hopefully don't clobber it
|
|
|
|
tba.top_of_kernel_data = max(tba.top_of_kernel_data, new_base + image_size)
|
2021-04-14 12:13:19 +00:00
|
|
|
|
2021-05-07 17:39:32 +00:00
|
|
|
if len(args.boot_args) > 0:
|
|
|
|
boot_args = " ".join(args.boot_args)
|
|
|
|
if "-v" in boot_args.split():
|
|
|
|
tba.video.display = 0
|
|
|
|
else:
|
|
|
|
tba.video.display = 1
|
|
|
|
print(f"Setting boot arguments to {boot_args!r}")
|
|
|
|
tba.cmdline = boot_args
|
|
|
|
|
2021-04-14 12:13:19 +00:00
|
|
|
iface.writemem(image_addr + bootargs_off, BootArgs.build(tba))
|
|
|
|
|
|
|
|
print(f"Copying stub...")
|
|
|
|
|
|
|
|
stub = asm.ARMAsm(f"""
|
|
|
|
1:
|
|
|
|
ldp x4, x5, [x1], #8
|
|
|
|
stp x4, x5, [x2]
|
|
|
|
dc cvau, x2
|
|
|
|
ic ivau, x2
|
|
|
|
add x2, x2, #8
|
|
|
|
sub x3, x3, #8
|
|
|
|
cbnz x3, 1b
|
|
|
|
|
|
|
|
ldr x1, ={entry}
|
|
|
|
br x1
|
|
|
|
""", image_addr + image_size)
|
|
|
|
|
|
|
|
iface.writemem(stub.addr, stub.data)
|
|
|
|
p.dc_cvau(stub.addr, stub.len)
|
|
|
|
p.ic_ivau(stub.addr, stub.len)
|
|
|
|
|
2021-05-01 06:15:43 +00:00
|
|
|
print(f"Entry point: 0x{entry:x}")
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-05-04 13:45:18 +00:00
|
|
|
if args.call:
|
|
|
|
print(f"Shutting down MMU...")
|
|
|
|
try:
|
|
|
|
p.mmu_shutdown()
|
|
|
|
except ProxyCommandError:
|
|
|
|
pass
|
|
|
|
print(f"Jumping to stub at 0x{stub.addr:x}")
|
|
|
|
p.call(stub.addr, new_base + bootargs_off, image_addr, new_base, image_size, reboot=True)
|
|
|
|
else:
|
|
|
|
print(f"Rebooting into stub at 0x{stub.addr:x}")
|
|
|
|
p.reboot(stub.addr, new_base + bootargs_off, image_addr, new_base, image_size)
|
2021-01-14 18:56:45 +00:00
|
|
|
|
2021-05-04 13:45:18 +00:00
|
|
|
time.sleep(1)
|
2021-01-14 18:56:45 +00:00
|
|
|
iface.nop()
|
|
|
|
print("Proxy is alive again")
|