ios-topaz README

The project's README from github.com/MakrSas/ios-topaz. As one markdown file: README.md.

ios-topaz

Apple's iOS 16 running on a Redmi Note 12 4G.

This is a port of dipa-studio/ios-sweet (Apple's open-source XNU kernel, xnu-8796, on a Redmi Note 10 Pro) to the Xiaomi Redmi Note 12 4G (topaz / tapas, Qualcomm SM6225 "khaje" / Snapdragon 685). On top of it runs the unmodified iOS 16.7.16 (20H392) userland of the iPhone X: launchd, the system daemons, backboardd and SpringBoard.

As of 2026-10-18 the phone boots to the iOS lock screen in about 3 minutes, on the four Cortex-A73 cores. Rendering runs entirely on the CPU; there is no GPU driver. Touch is being brought up (see the roadmap); without it the lock screen cannot be unlocked yet.

Experimental bring-up, not a usable phone OS. Many things are missing or stubbed, and Apple's security model is mostly switched off. It installs into the userdata partition and so erases Android's user data. Nothing is flashed to the boot partitions; the kernel is started from RAM with fastboot boot.

What works

Area State
Boot Stock Xiaomi ABL → fastboot boot of our shim (boot image v4) → XNU. Boot slots and other OSes on the phone are not touched
CPU The four Cortex-A73 ("Gold", MPIDR 0x100–0x103) cores, 16K pages, GICv3, timers. The Silver cores are parked (see below)
Memory The upper DDR bank, 0x1_40000000 + 4 GiB
Storage UFS host driver (UFS 3.0 at 0x4804000); the iOS root is a journaled HFS+ volume in userdata, read/write
iOS userland Real iPhone X 16.7.16 root filesystem and shared cache; launchd and the system daemons run
Display Kernel IOSurface + IOMobileFramebuffer (AppleCLCD); CoreAnimation renders in software into ABL's framebuffer at 0x5c000000 (1080×2400). Presented to iOS as an iPhone X panel
GUI backboardd, SpringBoard, boot Apple logo, lock screen
Device identity iPhone X (iPhone10,3 / D22AP): no Home button, gesture UI

What does not work (yet)

How topaz differs from sweet

These are the walls hit during the port; each one stops the boot silently if missed.

Problem Fix
Xiaomi's topaz ABL ignores boot image v1/v2 and drops the boot v4 ramdisk (it only passes vendor_boot's) The shim is packed as boot v4 and the XNU payload is appended to the shim's kernel Image after _end (shim/build.sh, shim/loader.c)
ABL starts on a Kryo 260 Silver core (Cortex-A53 class, MIDR 0x51AF8014), which has no 16K translation granule (ID_AA64MMFR0.TGran16 = 0) The shim wakes Gold CPU 0x100 with PSCI CPU_ON, the Silver core parks in wfi, and XNU only ever runs on Gold. The ADT lists the four Gold cores (tools/mkadt.py, patch 0082)
The cores are ARMv8.0: no LSE atomics, no RCpc (ldapr), no PAN. Apple clang keeps its apple-m1 CPU default under -arch arm64 even with -march Kernel and libfirehose_kernel are built with -mcpu=cortex-a53, PAN is off, the commpage PFZ casa became an LDAXR/STXR loop (patch 0081, xnu.yml)
The iPhone X userland still contains LSE atomics and ldapr They are emulated atomically in handle_uncategorized (LDAXR/STLXR on the user address, copyio recovery) (patch 0081)
XNU hangs after initCPU on Gold (no SGI / timer interrupt) The shim prepares the GIC for all Gold cores before the jump: GICD groups, redistributor wake, SGIs/PPIs in Group 1 (test_gic() / gold_gicr_prepare() in shim/shim.c)
Different MMIO map GIC 0xf200000/0xf300000, UFS 0x4804000, splash framebuffer 0x5c000000, PS_HOLD 0x440b000, IMEM restart reason 0xc12565c, TLMM tiles WEST 0x500000 / SOUTH 0x900000 / EAST 0xd00000

Why only the Gold cores

XNU for iOS uses 16K pages for the kernel and the userland on every CPU, and the Silver cores cannot translate 16K pages. Using all eight cores needs a 4K-page XNU, which is on the roadmap as an experiment.

How it boots

ABL (stock Xiaomi bootloader, unlocked)
  -> fastboot boot shim-boot.img        (boot image v4, RAM only)
     -> shim on Silver CPU0: prints MMFR0/MIDR, wakes Gold CPU 0x100, parks
        -> shim on Gold: GIC setup, speed probe, finds the payload behind _end
           -> XNU Mach-O + Apple Device Tree (ADT) + boot-args
              -> XNU -> UFS driver -> HFS+ root in userdata
                 -> dyld + shared cache -> launchd -> backboardd + SpringBoard

There is no serial console. The kernel draws its console into ABL's framebuffer; with sweetfb_noconsole=1 it stops after the first iOS frame (panics are still drawn). The kernel also keeps sweet's persistent log ring at the end of userdata and its user stack sampler (SMP name tN pc .. bt ..).

How to do it yourself

You need a Redmi Note 12 4G (topaz/tapas, SM6225) with an unlocked bootloader, a Linux PC with fastboot, and a GitHub account for the kernel build. Everything on userdata is lost. Boot, vendor_boot, firmware and other partitions are never written.

1. Build the kernel

The kernel builds on GitHub's macOS runners (macos-14, Xcode 15) with blacktop/darwin-xnu-build; newer Xcode's iig does not match the xnu-8796 IORPC ABI. Fork the repo and run, on the topaz branch:

gh workflow run xnu.yml -R YOU/ios-topaz --ref topaz
gh run download RUN_ID -R YOU/ios-topaz -n xnu-kernel -D xnu/out

A build takes about 8 minutes. If the artifact upload times out on GitHub's side, rerun the job. Check that the kernel has no LSE left (llvm-objdump -d --mattr=+v8.5a ... | grep -P '\t(cas|ldadd|ldset|ldclr|swp|ldapr)'; the only hit should be the K256 SHA table).

2. Build the iOS root image

Download the iPhone X (iPhone10,3) iOS 16.7.16 (20H392) IPSW from Apple. On Linux, with apfs-fuse (build it from sgan81/apfs-fuse if your distribution has no package), hfsprogs and sudo:

# OS, SystemOS and AppOS disk images (see BuildManifest.plist, D22AP Erase identity)
sudo bash tools/mkiosroot.sh OS.dmg SystemOS.dmg AppOS.dmg ios16-root.img 16G
sudo mount -t hfsplus -o loop,force ios16-root.img /mnt/iosroot
sudo python3 tools/sweet-root-tweaks.py /mnt/iosroot
sudo umount /mnt/iosroot
img2simg ios16-root.img ios16-root.simg

The device tree builder copies /product from the real iPhone X device tree. Take Firmware/all_flash/DeviceTree.d22ap.im4p from the IPSW, decompress its LZFSE payload (ipsw img4 im4p extract) and save it as research/ipsw-x/d22ap.adt.

3. Build the boot image

Needs aarch64-linux-gnu-gcc and AOSP mkbootimg.py (set MKBOOTIMG if it is not at the default path in shim/build.sh).

python3 tools/mkadt.py shim/out/topaz.adt --highmem
python3 tools/mkpayload.py xnu/out/kernel.development.sweet shim/out/topaz.adt shim/out/payload.bin \
    --cmdline 'debug=0xc serial=3 cpus=4 keepsyms=1 -noprogress rd=ufsroot0 unentitled_ios_sim_launch=1 ignition_level=1 wdt_test=no_user_checkin ufsrw=1 rootrw=1 launchd_unsecure_cache=1 wdt=-1 sweetfb_noconsole=1 sweetfb_hz=30'
shim/build.sh ../shim/out/payload.bin      # -> shim/out/shim-boot.img
Boot-arg Effect
rd=ufsroot0 ufsrw=1 rootrw=1 Root on userdata, writable
cpus=4 All four Gold cores; cpus=1 is the safe fallback
sweetfb_noconsole=1 Stop drawing kernel text over the GUI after the first iOS frame. Leave it out to debug (much slower: every console line is drawn and scrolled by the CPU)
sweetfb_hz=30 Panel refresh rate of the CPU frame copy
sweettouch=0 Disable the touch driver
sweethw=1 Also start sweet's SM7150 key and USB drivers (unsafe on topaz, not ported)
launchd_unsecure_cache=1, wdt=-1 wdt_test=no_user_checkin launchd without AMFI; no hardware watchdog

4. Flash the root and boot

fastboot -S 512M flash userdata ios16-root.simg   # ~5 minutes; do not unplug
fastboot boot shim/out/shim-boot.img

The shim screen (red) shows MMFR0, the Gold hand-off and SPEED silver=… gold=… for 8 seconds, then XNU starts. The first boot spends a while on the Apple logo (SpringBoard waits for LaunchServices to build its database); the lock screen follows after about 3 minutes. To get back to fastboot, hold Power + Volume down.

Debugging tips

Roadmap

  1. Touch (FT5452 at I²C 0x38 on QUP0 SE2 0x4a88000, IRQ GPIO80, reset GPIO86, AVDD GPIO36): patch 0083, needs confirmation on the phone.

  2. Buttons: power and volume down on the PM6125 PON block, volume up on PM6125 GPIO5.

  3. Smoother display: higher sweetfb_hz; check whether the Gold cores run at a low clock without cpufreq (the shim's speed probe) and raise it if so.

  4. Narrow the GIC fix to the register that actually matters, then move it into XNU.

  5. Real-time clock from the PMIC RTC or passed in by the shim.

  6. All 8 cores (experiment, later): build XNU with 4K pages (drop __ARM_16K_PG__ from SWEET.h, as XNU's own BCM2837 Raspberry Pi 3 config does on Cortex-A53) and describe two clusters, Gold as P and Silver as E, so the AMP scheduler uses both. Risk: the iOS 16 userland was only ever run on 16K pages (hard-coded 16K in malloc, JIT guard pages, IOSurface, commpage layout), and the 16K assumptions in the shim and sweet's patches have to be checked too. The 16K Gold-only kernel stays as the fallback.

  7. Silver cores as a coprocessor (idea): run bare-metal shim code on them for the panel frame copy instead of XNU.

  8. 6 GB model (requested): the RAM layout is hard-coded for the 4 GB phone (mkadt.py --highmem, 4 GiB at 0x1_40000000). Have the shim read the DDR ranges from the /memory node of the DTB that ABL passes and write them into the ADT and boot args, so one image boots both the 4 GB and the 6 GB versions. Everything else (SoC, panel, touch, battery) is the same hardware. GPU plan (2026-10-19): a kernel Adreno 610 driver (topaz-woa TopazGpuW sequences) with an msm DRM style user client for Mesa freedreno, so QuartzCore's OpenGL ES renderer draws the UI on the GPU; Metal for apps after that.

  9. Wi-Fi (port from MakrSas/topaz-woa TopazWifi, which has scan, WPA2 and working internet on Windows): bring up the modem/WLAN firmware through TrustZone, SMEM/QMI and the WCN3988 WLAN commands exactly as TopazWifi does, in an XNU driver. Expose it to iOS first as a network interface (IONetworkingFamily, network set by config), then emulate the IO80211 interface that wifid talks to, so Settings → Wi-Fi shows the scan list and joins networks.

  10. Speaker (port from topaz-woa TopazAudio (ADSP / AudioReach) + TopazSpeaker, see its docs/P9_audio.md): ADSP firmware through TrustZone, AudioReach graph to the speaker, and an XNU audio driver that CoreAudio can output to.

  11. Also ready in topaz-woa to port: brightness (display adapter), USB host/OTG (TopazOtgDxe + XHCI), RPM requests (TopazRpm: rails, clocks, GPU CX level), SIM/LTE registration (docs/P9_sim.md). The GPU work follows TopazGpuW.

Repository layout

Path What
shim/ Bare-metal boot shim (C + asm), boot image v4, Gold hand-off, GIC setup, payload loader
xnu/patches/ XNU patch series (applied in order by CI): sweet's 0001–0079, topaz's 0080+
.github/workflows/xnu.yml Kernel CI build
tools/mkadt.py Apple Device Tree for topaz (Gold cores, memory map, MMIO) and the iPhone X identity
tools/mkpayload.py Packs kernel + ADT + boot-args into the shim payload
tools/mkiosroot.sh, tools/sweet-root-tweaks.py Build and adjust the HFS+ iOS root
tools/sweet-crash.py, sweet-log.py Symbolicate crash reports, read the persistent log
NOTES.md sweet's engineering log (history of the original port)

Not in git: partition backups, live device trees, Apple firmware and root images, build trees.

topaz kernel patches

# What
0080 CPU topology for SM6225; sweet's SM7150 key/touch/USB drivers gated behind sweethw=1
0081 ARMv8.0: -mcpu=cortex-a53, no PAN, PFZ without CASA, userland LSE/LDAPR emulation
0082 Boot CPU is Gold MPIDR 0x100
0083 Touch: FocalTech FT5452 on QUP0 SE2 (values from topaz-woa TopazTouch)

Key hardware facts (topaz)

Credits

Based on dipa-studio/ios-sweet, which did the hard part: XNU on a Qualcomm phone with the iPhone X userland. Built on Apple's open-source releases (xnu, IOHIDFamily, libpthread, hfs), BearSSL, blacktop/darwin-xnu-build, ipsw, Qualcomm/Xiaomi's published Linux kernel sources, and the topaz hardware work in MakrSas/topaz-woa. iOS itself is Apple's and is not distributed here.

ios-topaz (MakrSas/ios-topaz)

Searching Database…

What is this?ios-topaz is an experimental port of Apple's unmodified iOS 16.7.16 userland and the open-source XNU kernel to run on a Xiaomi Redmi Note 12 4G Android phone (topaz/tapas, Snapdragon 685), booting all the way to the iOS lock screen.
Is this a flashable iOS ROM or a research bring-up project?It is an experimental research bring-up, not a usable phone OS: the kernel boots fresh from RAM every time via fastboot, nothing is permanently flashed, and much of Apple's security and hardware support is stubbed or disabled.
How do I try booting iOS on the phone myself?You build the XNU kernel on GitHub's macOS CI, build an iOS root filesystem from an official iPhone X IPSW on Linux, build a boot-v4 shim image, then boot it over USB; the kernel is started from RAM with fastboot boot and nothing is written to the boot or vendorboot partitions.
What hardware and tools do I need to attempt this?A Xiaomi Redmi Note 12 4G (topaz/tapas, SM6225) with an unlocked bootloader, a Linux PC with fastboot, and a GitHub account to run the macOS-hosted kernel build (Xcode 15 / blacktop/darwin-xnu-build).
What doesn't work yet, like touch or GPU?Touch and buttons are not confirmed working yet, so the lock screen cannot be unlocked; there is also no Wi-Fi, Bluetooth, cellular, audio, camera, sensors, GPS, SEP, or real-time clock, and only 4 of the phone's 8 CPU cores are used.
Does it use the phone's GPU for the UI?No, there is no GPU driver yet; CoreAnimation renders entirely on the CPU into the framebuffer, which is why the frame rate is low.
Why does the first boot take about 3 minutes?On first boot SpringBoard has to wait for LaunchServices to build its database before the lock screen appears, which the README cites as the main reason for the roughly 3-minute boot time.
What project is this based on?It is a port of dipa-studio/ios-sweet, which first got XNU and the iPhone X userland running on a Qualcomm phone (a Redmi Note 10 Pro); ios-topaz adapts that work to the different SoC and ABL of the Redmi Note 12 4G.
Can I actually unlock and use the phone once it boots?Not yet: touch input is still unconfirmed and buttons aren't wired up, so you can reach the lock screen but can't unlock or interact with it.
What's planned next on the roadmap?Upcoming work includes confirming the touch driver, power/volume buttons, a real-time clock, an Adreno 610 GPU driver for hardware-accelerated rendering, and ports of Wi-Fi and speaker audio from the related TopazWifi/TopazAudio projects.
Creator
MakrSas
Size
0.5 MB
Stars
246
Updated
CommitOct 19
Age
2d
Commits · 90 Days