Apple Silicon macOS on non-Apple AArch64 hardware.
HackintARM boots the retail Apple Silicon kernel collection on machines Apple
never blessed: no QEMU vmapple machine model, no proprietary Apple hypervisor,
and eventually no emulator at all.
Today the macOS 27 "Golden Gate" VMApple kernel collection boots through
Gatehouse to launchd and a partial userland under QEMU virt. The frontier is
graphics: the machine has no display device, so the window server and the
services that depend on it cannot stay alive.
| Stage | State |
|---|---|
| UEFI application, serial console | done |
| Kernel collection load, slide, kext init | done |
| Apple Image4 / platform expert / GICv3 | done |
| IOKit matching, BSD init, MACF/AMFI | done |
| Storage transport and APFS root mount | done |
launchd, mount phases, multi-user daemons |
done |
| Graphical userland | blocked on a display device |
| Bare-metal AArch64 | after the QEMU virt target is complete |
The newest boot (build/boot81.log) reaches "Early boot complete. Continuing
system boot" and starts loginwindow, WindowServer, opendirectoryd,
mDNSResponder, storagekitd, distnoted, PerfPowerService and the rest of
the launchd job set. There is no kernel panic. WindowServer, loginwindow
and timed crash-loop ("Too many corpses being created") because there is no
GPU/display for them to bind to, and ReportCrashService cannot start either,
so the crashes leave no .ips reports.
The kernel-collection workarounds needed to get this far are in
gatehouse/src/patch.c. Each one is documented,
byte-verified against the staged copy, and applied only at load time; the
pristine image in kernel/ is never modified.
- UART/serial output
- Kernel collection slides and all prelinked kexts load
- Past
AppleImage4platform initialisation - Full IOKit matching phase and BSD init
- Root transport starts, APFS root volume mounts
-
launchdruns, mount phases complete, userland daemons start - A display/GPU device the guest can bind
- A usable desktop
- Trestle on the boot path instead of QEMU's machine
- Real hardware
HackintARM is an umbrella project. All three parts are bridge-themed.
| Sub-project | Role | Code |
|---|---|---|
| Gatehouse | The freestanding UEFI bootloader. Loads the kernel collection, builds the Apple Device Tree (ADT), supplies NVRAM, the trust cache and boot arguments, and jumps to XNU. Portable: the only board-specific input is the ADT description. | gatehouse/ |
| Trestle | The platform layer. Provides the AVP devices and services macOS expects — device tree, NVRAM, RTC, panic log, PCIe, and (soon) the graphics devices — on machines that do not implement Apple's paravirtual interfaces. | trestle/ |
| Lantern | The paravirtual GPU. Speaks VMApple's graphics protocol to the guest and translates it to a real GPU: Vulkan first, bare-metal GPU backends later. | docs/lantern.md |
Trestle is designed to be machine-portable: device models never hard-code an
address; the machine description says where each device lives. That is what
lets the same models serve QEMU virt now and bare metal later.
VMApple exposes graphics as two paravirtual devices (paravirtualizedgraphics,gpu
and paravirtualizedgraphics,iosurface) backed on real Apple hardware by
ParavirtualizedGraphics.framework. HackintARM cannot link that framework, so
Lantern replaces the host side. It reuses
steelbrain/reims-vgpu as the PVG
protocol core — a clean-room, framework-free implementation with a C API and a
swappable Platform backend — and adds only the device front-end, guest-memory
mapping and display sink. See docs/lantern.md for the
architecture decision and bring-up plan.
UEFI firmware
│ BOOTAA64.EFI
▼
Gatehouse ── loads MH_FILESET, lays it out 1:1, applies kernel patches,
│ builds the ADT, NVRAM, trust cache, boot arguments
▼
XNU (EL1) ── IOKit matching, BSD init, root media, APFS
│
▼
launchd ── mount phases, daemons, loginwindow/WindowServer
│
▼
Lantern ── paravirtual GPU + IOSurface devices → Vulkan → real display
The near-term target is under QEMU virt, with Gatehouse providing the ADT
itself. QEMU's generated device tree is not used for the guest's platform
description; the QEMU device placement and the ADT must agree, and both are
derived from the same machine description.
macOS 27 is Apple Silicon only, so there is no "legacy" kernel path left. The VMApple collection is used because it makes far fewer assumptions about the SoC than a bare-metal M-series collection: it expects a virtual platform with paravirtual devices, which is exactly the platform Trestle is built to supply. The collection on disk is the signed retail image and is never modified; compatibility work happens in Gatehouse at load time, not in Apple's binaries.
The current target is QEMU virt on an x86-64 host, using TCG (software CPU)
so that no Apple hardware is required to develop:
# Kernel collection at kernel/kernelcache.release.vma2.kc
./qemu/run.shUseful knobs (see the header of qemu/run.sh):
| Variable | Meaning |
|---|---|
KERNEL= |
kernel collection to boot |
ROOTIMG=, ROOTFMT= |
root disk and its format (raw or qcow2) |
ISCIMG=, ISCFMT= |
auxiliary storage (iSC/xART container) |
TRUSTCACHE= |
static trust cache |
RAMDISK=, RAMDISKTC= |
restore ramdisk and its trust cache |
BOOTARGS= |
extra kernel arguments (inert unless set) |
INIT=, INITARG= |
PID 1 override for bring-up |
MEM=, CPU= |
guest RAM and CPU model |
The launcher builds Gatehouse, regenerates the ADT, stages an EFI System
Partition in build/esp, and starts QEMU with AAVMF, GICv3 and a GDB stub on
:1234 (opt-in with GDB=1).
When /mnt/windows2/combined2.qcow2 exists, the launcher uses it as the
read-write root disk by default. It is an overlay over combined2.img, which
keeps guest writes out of the base disk. ROOTIMG, ROOTFMT and ROOTIMG_RO
can select another image or access mode.
The QEMU virt machine is a development vehicle, not the destination. Once
Lantern and the remaining devices work there, only the machine description and
the GPU backend should change for bare metal.
The decrypted APFS volume is the input to disk assembly. The guest boots from
the resulting GPT disk, which carries the iSC partition and the APFS System,
Data and Preboot volumes; qemu/run.sh prefers its writable qcow2 overlay
when present. Nothing in the boot path retains AEA or an IPSW.
| Tool | Purpose |
|---|---|
tools/ipsw_extract.py |
pull members out of an IPSW with HTTP Range requests |
tools/im4p_extract.py |
unwrap IMG4/IM4P payloads |
tools/aea_decrypt.py |
decrypt the AEA root image to a raw APFS container |
tools/mkisc |
build the iSC/xART auxiliary-storage container |
tools/mkcombined |
assemble System/Data/Preboot APFS volumes and a combined GPT disk |
mkcombined can build the single GPT disk macOS 27 expects (iSC partition 1,
main APFS container partition 2), inject the extracted dyld shared cache, and
populate the Data volume from the installer's /System/Library/Templates/Data.
The template matters: daemons such as logd assume its directory skeleton
exists, and their sandbox profiles do not allow creating the missing parents.
The restore image we use, its build identity and its member map are recorded in
docs/ipsw.md. The detailed boot narrative — every wall hit on
the way to launchd, and the evidence for each fix — is in
docs/bringup.md.
For the eventual bare-metal target:
- AArch64 with ARMv8.2/8.3 extensions and pointer authentication (PAuth). SoCs without PAuth are not compatible for now.
- Support for 16 KiB pages (or a CPU/MMU configuration that can run a 16 KiB-page kernel).
- UEFI firmware, for Gatehouse.
For development on the QEMU virt target, any x86-64 or AArch64 host with QEMU
and EDK2 AAVMF works; no Apple hardware is needed.
gatehouse/ UEFI bootloader (C + a little asm)
dt/build_adt.py builds the ADT blob handed to XNU
src/patch.c kernel-collection workarounds
trestle/ platform layer / hypervisor (in progress)
src/ device models, ADT builder, machine descriptions
docs/ design and bring-up documentation
tools/ host-side helpers (IPSW, AEA, Mach-O, ADT, disk images)
qemu/ run.sh and GDB helpers for the QEMU virt target
kernel/ extracted Apple images (not in git)
New code for the GPU front-end will live under lantern/ (device front-end,
QEMU integration, Trestle device model, platform backends).
docs/lantern.md— Lantern architecture, PVG device contract, and bring-up phasesdocs/bringup.md— the detailed boot narrativedocs/ipsw.md— the restore image and its contentstrestle/docs/design.md— Trestle's device-model architectureLICENSING.md— the mixed-licence policy
Everything HackintARM authors is GPL-2.0-or-later. Acidanthera kexts are
GPL-3.0-or-later and combine with the core under GPLv3 terms. Linux
GPL-2.0-only code is kept isolated. The full policy is in
LICENSING.md; the GPLv2 text is in LICENSE.
Lantern vendors reims-vgpu, which is dual-licensed
GPL-2.0-or-later OR LGPL-3.0-or-later; the GPL option is compatible with this
tree.
- Lantern device probe — publish the GPU and IOSurface nodes; bring the
MMIO register file, interrupts and guest-memory map up under QEMU
virt. - PVG protocol — FIFOs, resources, textures and command streams over
Vulkan via reims-vgpu's
Platformbackend. - Scanout — frames reach a real window and QMP
screendump;WindowServerandloginwindowstay alive. - Trestle — move the same device models onto the boot path, replacing QEMU's machine description.
- Bare metal — EFI + Trestle + a native GPU backend, with only the
Platformand machine description differing.
There is no reliable ETA. The boot-to-userland stage is done; the desktop and bare metal are large, device-specific projects.