Add raw binary support to HV scripts

Signed-off-by: amarioguy <arminders208@outlook.com>
This commit is contained in:
amarioguy 2022-06-21 20:04:42 -04:00 committed by Hector Martin
parent b8dbb591d7
commit 0cf1f393ed
2 changed files with 89 additions and 81 deletions

View file

@ -1494,6 +1494,89 @@ class HV(Reloadable):
def disable_time_stealing(self):
self.p.hv_set_time_stealing(False)
def load_raw(self, image, entryoffset=0x800):
sepfw_start, sepfw_length = self.u.adt["chosen"]["memory-map"].SEPFW
tc_start, tc_size = self.u.adt["chosen"]["memory-map"].TrustCache
if hasattr(self.u.adt["chosen"]["memory-map"], "preoslog"):
preoslog_start, preoslog_size = self.u.adt["chosen"]["memory-map"].preoslog
else:
preoslog_size = 0
image_size = align(len(image))
sepfw_off = image_size
image_size += align(sepfw_length)
preoslog_off = image_size
image_size += preoslog_size
self.bootargs_off = image_size
bootargs_size = 0x4000
image_size += bootargs_size
print(f"Total region size: 0x{image_size:x} bytes")
self.phys_base = phys_base = guest_base = self.u.heap_top
self.ram_base = self.phys_base & ~0xffffffff
self.ram_size = self.u.ba.mem_size_actual
guest_base += 16 << 20 # ensure guest starts within a 16MB aligned region of mapped RAM
self.adt_base = guest_base
guest_base += align(self.u.ba.devtree_size)
tc_base = guest_base
guest_base += align(tc_size)
self.guest_base = guest_base
mem_top = self.u.ba.phys_base + self.u.ba.mem_size
mem_size = mem_top - phys_base
print(f"Physical memory: 0x{phys_base:x} .. 0x{mem_top:x}")
print(f"Guest region start: 0x{guest_base:x}")
self.entry = guest_base + entryoffset
print(f"Mapping guest physical memory...")
self.add_tracer(irange(self.ram_base, self.u.ba.phys_base - self.ram_base), "RAM-LOW", TraceMode.OFF)
self.add_tracer(irange(phys_base, self.u.ba.mem_size_actual - phys_base + self.ram_base), "RAM-HIGH", TraceMode.OFF)
self.unmap_carveouts()
print(f"Loading kernel image (0x{len(image):x} bytes)...")
self.u.compressed_writemem(guest_base, image, True)
self.p.dc_cvau(guest_base, len(image))
self.p.ic_ivau(guest_base, len(image))
print(f"Copying SEPFW (0x{sepfw_length:x} bytes)...")
self.p.memcpy8(guest_base + sepfw_off, sepfw_start, sepfw_length)
print(f"Copying TrustCache (0x{tc_size:x} bytes)...")
self.p.memcpy8(tc_base, tc_start, tc_size)
if hasattr(self.u.adt["chosen"]["memory-map"], "preoslog"):
print(f"Copying preoslog (0x{preoslog_size:x} bytes)...")
self.p.memcpy8(guest_base + preoslog_off, preoslog_start, preoslog_size)
print(f"Adjusting addresses in ADT...")
self.adt["chosen"]["memory-map"].SEPFW = (guest_base + sepfw_off, sepfw_length)
self.adt["chosen"]["memory-map"].TrustCache = (tc_base, tc_size)
self.adt["chosen"]["memory-map"].DeviceTree = (self.adt_base, align(self.u.ba.devtree_size))
self.adt["chosen"]["memory-map"].BootArgs = (guest_base + self.bootargs_off, bootargs_size)
if hasattr(self.u.adt["chosen"]["memory-map"], "preoslog"):
self.adt["chosen"]["memory-map"].preoslog = (guest_base + preoslog_off, preoslog_size)
print(f"Setting up bootargs at 0x{guest_base + self.bootargs_off:x}...")
self.tba.mem_size = mem_size
self.tba.phys_base = phys_base
self.tba.virt_base = 0xfffffe0010000000 + (phys_base & (32 * 1024 * 1024 - 1))
self.tba.devtree = self.adt_base - phys_base + self.tba.virt_base
self.tba.top_of_kernel_data = guest_base + image_size
self.iface.writemem(guest_base + self.bootargs_off, BootArgs.build(self.tba))
print("Setting secondary CPU RVBARs...")
rvbar = self.entry & ~0xfff
for cpu in self.adt["cpus"][1:]:
addr, size = cpu.cpu_impl_reg
print(f" {cpu.name}: [0x{addr:x}] = 0x{rvbar:x}")
self.p.write64(addr, rvbar)
def load_macho(self, data, symfile=None):
if isinstance(data, str):
data = open(data, "rb")
@ -1539,87 +1622,8 @@ class HV(Reloadable):
#image = macho.prepare_image(load_hook)
image = macho.prepare_image()
sepfw_start, sepfw_length = self.u.adt["chosen"]["memory-map"].SEPFW
tc_start, tc_size = self.u.adt["chosen"]["memory-map"].TrustCache
if hasattr(self.u.adt["chosen"]["memory-map"], "preoslog"):
preoslog_start, preoslog_size = self.u.adt["chosen"]["memory-map"].preoslog
else:
preoslog_size = 0
self.load_raw(image, entryoffset=(macho.entry - macho.vmin))
image_size = align(len(image))
sepfw_off = image_size
image_size += align(sepfw_length)
preoslog_off = image_size
image_size += preoslog_size
self.bootargs_off = image_size
bootargs_size = 0x4000
image_size += bootargs_size
print(f"Total region size: 0x{image_size:x} bytes")
self.phys_base = phys_base = guest_base = self.u.heap_top
self.ram_base = self.phys_base & ~0xffffffff
self.ram_size = self.u.ba.mem_size_actual
guest_base += 16 << 20 # ensure guest starts within a 16MB aligned region of mapped RAM
self.adt_base = guest_base
guest_base += align(self.u.ba.devtree_size)
tc_base = guest_base
guest_base += align(tc_size)
self.guest_base = guest_base
mem_top = self.u.ba.phys_base + self.u.ba.mem_size
mem_size = mem_top - phys_base
print(f"Physical memory: 0x{phys_base:x} .. 0x{mem_top:x}")
print(f"Guest region start: 0x{guest_base:x}")
self.entry = macho.entry - macho.vmin + guest_base
print(f"Mapping guest physical memory...")
self.add_tracer(irange(self.ram_base, self.u.ba.phys_base - self.ram_base), "RAM-LOW", TraceMode.OFF)
self.add_tracer(irange(phys_base, self.u.ba.mem_size_actual - phys_base + self.ram_base), "RAM-HIGH", TraceMode.OFF)
self.unmap_carveouts()
print(f"Loading kernel image (0x{len(image):x} bytes)...")
self.u.compressed_writemem(guest_base, image, True)
self.p.dc_cvau(guest_base, len(image))
self.p.ic_ivau(guest_base, len(image))
print(f"Copying SEPFW (0x{sepfw_length:x} bytes)...")
self.p.memcpy8(guest_base + sepfw_off, sepfw_start, sepfw_length)
print(f"Copying TrustCache (0x{tc_size:x} bytes)...")
self.p.memcpy8(tc_base, tc_start, tc_size)
if hasattr(self.u.adt["chosen"]["memory-map"], "preoslog"):
print(f"Copying preoslog (0x{preoslog_size:x} bytes)...")
self.p.memcpy8(guest_base + preoslog_off, preoslog_start, preoslog_size)
print(f"Adjusting addresses in ADT...")
self.adt["chosen"]["memory-map"].SEPFW = (guest_base + sepfw_off, sepfw_length)
self.adt["chosen"]["memory-map"].TrustCache = (tc_base, tc_size)
self.adt["chosen"]["memory-map"].DeviceTree = (self.adt_base, align(self.u.ba.devtree_size))
self.adt["chosen"]["memory-map"].BootArgs = (guest_base + self.bootargs_off, bootargs_size)
if hasattr(self.u.adt["chosen"]["memory-map"], "preoslog"):
self.adt["chosen"]["memory-map"].preoslog = (guest_base + preoslog_off, preoslog_size)
print(f"Setting up bootargs at 0x{guest_base + self.bootargs_off:x}...")
self.tba.mem_size = mem_size
self.tba.phys_base = phys_base
self.tba.virt_base = 0xfffffe0010000000 + (phys_base & (32 * 1024 * 1024 - 1))
self.tba.devtree = self.adt_base - phys_base + self.tba.virt_base
self.tba.top_of_kernel_data = guest_base + image_size
self.sym_offset = macho.vmin - guest_base + self.tba.phys_base - self.tba.virt_base
self.iface.writemem(guest_base + self.bootargs_off, BootArgs.build(self.tba))
print("Setting secondary CPU RVBARs...")
rvbar = self.entry & ~0xfff
for cpu in self.adt["cpus"][1:]:
addr, size = cpu.cpu_impl_reg
print(f" {cpu.name}: [0x{addr:x}] = 0x{rvbar:x}")
self.p.write64(addr, rvbar)
def update_pac_mask(self):
tcr = TCR(self.u.mrs(TCR_EL12))

View file

@ -14,6 +14,7 @@ parser.add_argument('-e', '--hook-exceptions', action="store_true")
parser.add_argument('-d', '--debug-xnu', action="store_true")
parser.add_argument('-l', '--logfile', type=pathlib.Path)
parser.add_argument('-C', '--cpus', default=None)
parser.add_argument('-r', '--raw', action="store_true")
parser.add_argument('payload', type=pathlib.Path)
parser.add_argument('boot_args', default=[], nargs="*")
args = parser.parse_args()
@ -61,7 +62,10 @@ if len(args.boot_args) > 0:
symfile = None
if args.symbols:
symfile = args.symbols.open("rb")
hv.load_macho(args.payload.open("rb"), symfile=symfile)
if args.raw:
hv.load_raw(args.payload.read_bytes())
else:
hv.load_macho(args.payload.open("rb"), symfile=symfile)
PMU(u).reset_panic_counter()