Documentation
On this page

Concepts

Device tree (ADT)

The Apple-format device tree the loader builds for XNU, and what is in it.

XNU boots from an Apple Device Tree (ADT), not a Linux one. mkadt.py writes a minimal ADT: only what the early boot path reads, with every MMIO address taken from the phone’s own tree. The result goes into the payload. The iPhone X user space reads the platform’s identity from it, so most of the root’s properties are identity, not hardware.

Running it

mkadt.py OUT.adt [--spaced [--ufs] [--haptics|--audio] [--torch] [--camera] [--resize]] [--canvas=WxH] [--dump]. In the build, device.conf’s adt line gives the flags; the spaced line is --spaced --ufs --audio --torch (and --resize when resize 1).

The /product node is copied from the iPhone X’s own device tree, which the script reads from a file you extract from your copy of the IPSW (D22AP_ADT): it is Apple’s and kept out of every repository. Without it the script warns and writes no /product.

The tree

NodeWhat it holds
/compatible D22AP, iPhone10,3, mapple,platform, qcom,sm7150, AppleARM; model iPhone10,3; target-type D22, target-sub-type D22AP; with --spaced the serial-number placeholder, model-number and regulatory-model-number RMX3151
/chosendram-base, dram-size, random-seed, embedded-panic-log-size, boot-manifest-hash, crypto-hash-method, display-scale (3), the synthetic unique-chip-id and chip-id (0x8015), the security status values, the two MAC addresses, mapple-resize with --resize
/chosen/memory-mapempty; mkpayload.py --ramdisk adds RAMDisk
/chosen/asmblp-sip0 0x6f, lp-sip1 1: the local boot policy
/defaultsno-effaceable-storage
/cpuscpu0…cpu7, reg = core << 8 (the MPIDR), one homogeneous cluster, timebase-frequency from the SoC
/arm-ioranges from 0x01000000; gic (with virtual-timer-intid), wdt, disp0, then the phone’s devices
/mapple-fbconLK’s framebuffer: reg, width, height, stride
/mapple-ufsthe UFS host LK leaves running, absolute reg
/buttonsbutton-names, home-button-type 2 (no Home button), opposed-power-vol-buttons
/pramthe panic log: the last MiB of the range, outside dram-size
/productfrom the iPhone X’s tree; product-name becomes the phone’s; haptics with --audio or --haptics, camera flash with --torch

The panic log is carved from the top of the range because, without it, check_for_panic_log() leaves gPanicBase at 0 and the kernel hangs after the “kdp_core zlib memory” line.

The devices under /arm-io on spaced

Each has its own IOKit or BSD driver; the property names and values are the ones the driver reads.

NodeHardwareNotes
keypadMediaTek keypad, 0x10010000, SPI 73 edgekeymap <1, volume down>: volume down is bit 1 of KP_MEM1; power and volume up are the PMIC’s
eintexternal interrupts, 0x1000b000, SPI 186an interrupt controller under the GIC; children use <EINT flags>
pwrap > pmic > keysPMIC wrapper 0x1000d000; the PMIC (mt6366-pmic, EINT 144) and its keyskeymap <0 power, 1 volume up>
gpio0x10005000output pins only: SPI4’s pins 13, 144, 145 for the touch screen, and 164 with --audio
i2c3with --audio: the speaker amplifier’s busbus-id 3, 400 kHz
i2c5with --torch: the flash LED chip’s busbus-id 5
i2c2, i2c4, ispwith --cameraisp’s camera-rear is what MobileGestalt asks
touchilitek,ili7807s, spi-gpios 13, 14, 144, 145; EINT 12 fallingmax-x 2047, max-y 2047, panel-size 1080 x 2412; the firmware is sent by mtkloader
gpuMali-G57 MC2, 0x13000000, SPI 274 to 276with the power blocks it drives; the driver does nothing without mp_gpu
wlanCONNSYS Wi-Filocal-mac-address, wifi-vendor; launchd starts wifid only when a node named wlan exists

What comes from where

The constants for spaced in mkadt.py: RAM 0xc0000000 to 0x13e000000, framebuffer 0x771b0000 (stride 4320, 2412 rows), GIC 0x0c000000/0x0c040000, timer 13 MHz and INTID 27, UFS 0x11270000 (size 0x4000, 16 KB pages). The setup script writes the same numbers, read from a phone’s own trees, as adt-input.conf; mkadt.py does not read that file yet.

Source: tools/mkadt.py of mapple_build at f7431bb; tools/mkpayload.py for RAMDisk.

Applies to realme 8i (spaced), release 1 · Updated 15 November 2026