ios-sweet README

The project's README from github.com/dipa-studio/ios-sweet. As one markdown file: README.md.

ios-sweet

Apple's iOS 16 running on a Redmi Note 10 Pro.

This project ports Apple's open-source XNU kernel (xnu-8796, the iOS 16 generation) to the Xiaomi Redmi Note 10 Pro (sweet, Qualcomm SM7150 / Snapdragon 732G). On top of it runs the unmodified iOS 16.7.16 (20H392) userland of the iPhone X: launchd, the system daemons, backboardd, SpringBoard and the stock apps.

As of 2026-10-18 the phone boots to the iOS home screen. You can unlock it, open Settings, pull down Control Center and the notification center, and use the touchscreen and the hardware buttons. Rendering runs entirely on the CPU; there is no GPU driver.

Experimental bring-up, not a usable phone OS. Many things are missing or stubbed (see below), and Apple's security model is mostly switched off. It installs into the userdata partition and so erases Android's user data.

What works

Area State
Boot Stock Xiaomi bootloader → fastboot boot of our shim → XNU. Nothing is flashed to the boot partitions
CPU 6 of the 8 cores (the six Cortex-A55s) via PSCI, 16K pages, GICv3 interrupts, timers
Memory About 3.95 GiB of the upper DDR bank
Storage Own UFS host driver; 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) services; CoreAnimation renders in software; frames are copied into the bootloader's framebuffer. Presented to iOS as an iPhone X panel (1125×2436)
GUI backboardd, SpringBoard, lock screen, home screen, Control Center, notification center, Settings
Touch Goodix GT9896 over I²C (GENI), rail enabled through RPMh, delivered as HID digitizer events
Buttons Power, volume up/down (PMIC through SPMI) as HID consumer keys; lock/wake works
Battery IOPMPowerSource service (static 100 %, charging icon; real fuel-gauge readout prepared)
Device identity iPhone X (iPhone10,3 / D22AP): no Home button, gesture UI
Activation Native "Hactivation" path of mobileactivationd, chosen through device-tree security status. No Apple servers involved

What does not work (yet)

How it boots

ABL (stock Xiaomi bootloader, unlocked)
  -> fastboot boot shim-boot.img              (temporary; nothing is flashed to boot)
     -> shim: own MMU setup, reads the live FDT, loads the payload from the ramdisk
        -> XNU Mach-O + generated Apple Device Tree (ADT) + boot-args
           -> XNU -> UFS driver -> HFS+ root in the userdata partition
              -> dyld + shared cache -> launchd -> daemons -> backboardd + SpringBoard

There is no serial port (the debug UART is wired as SPI on this board). The kernel draws its console into the framebuffer that ABL leaves at 0x9c000000, and keeps a persistent 4 MiB log ring at the end of userdata. You read that log from OrangeFox recovery with tools/sweet-log-pull.sh, so you don't have to film the screen.

How to do it yourself

You need a Redmi Note 10 Pro (sweet, global or Indian variant, SM7150) with an unlocked bootloader, a Linux PC, and a GitHub account for the kernel build. This is the exact path used for the screenshots above; other variants or firmware may need changes. Everything on userdata is lost. Bootloaders, recovery, modem and persist partitions are never touched.

0. Back up the phone

Boot OrangeFox (or any recovery with adb root) temporarily and pull at least persist, modemst1, modemst2, fsg, fsc and boot, dtbo, vbmeta. They contain per-device calibration data. Keep them off git; .gitignore already excludes backup/, dtb/ and recovery/.

The shim needs the stock DTB. Unpack your phone's stock boot.img:

python3 tools/unpack_bootv2.py backup/boot.img dtb/boot_unpacked   # -> dtb/boot_unpacked/dtb

1. Build the kernel

The kernel builds on GitHub's macOS runners with blacktop/darwin-xnu-build. The workflow fetches xnu-8796, applies xnu/patches/ in order, and also stages the pinned open-source libpthread, HFS and BearSSL sources it needs. Fork the repo (public repos get free macOS minutes) and run:

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

To check a patch locally before spending a CI run, tools/xnu-cc.py replays the compile commands of a previous CI log for single files.

2. Build the iOS root image

Download the iPhone X (iPhone10,3) iOS 16.7.16 (20H392) IPSW from Apple. Then, on Linux, with apfs-fuse, hfsprogs and sudo:

# OS, SystemOS and AppOS disk images from the IPSW (see BuildManifest.plist for their names)
tools/mkiosroot.sh OS.dmg SystemOS.dmg AppOS.dmg ios16-root.img 16G
sudo fsck.hfsplus -fy ios16-root.img
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

mkiosroot.sh copies the OS volume and both cryptexes into one case-sensitive journaled HFS+ volume. It adds the dyld cache links, the plain system keybag and the log directories the daemons expect. sweet-root-tweaks.py applies the bring-up changes: it skips Setup, seeds the activation state, removes the baseband daemon, disables the watchdogs that kill slow apps and the crash-looping media paths, and so on. The script's header explains each change.

The device tree builder copies /product from the real iPhone X device tree, which MobileGestalt needs. Extract it once, without downloading the whole IPSW:

python3 tools/remotezip.py IPSW_URL DeviceTree.d22ap.im4p research/ipsw-x/dt
ipsw img4 im4p extract research/ipsw-x/dt/Firmware/all_flash/DeviceTree.d22ap.im4p -o research/ipsw-x/d22ap.adt

3. Build the boot image

Needs aarch64-linux-gnu-gcc and mkbootimg.

python3 tools/mkadt.py shim/out/sweet.adt --highmem
python3 tools/mkpayload.py xnu/out/kernel.development.sweet shim/out/sweet.adt shim/out/payload.bin \
    --cmdline 'debug=0xc serial=3 cpus=6 keepsyms=1 -enable_kprintf_spam -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

What the less obvious boot-args do:

Boot-arg Effect
rd=ufsroot0 ufsrw=1 rootrw=1 Root on the userdata partition, writable
cpus=6 Start the six A55 cores; cpus=1 is the safe fallback
launchd_unsecure_cache=1 launchd accepts its job cache without AMFI
wdt=-1 wdt_test=no_user_checkin No hardware watchdog
sweetfb_noconsole=1 Stop drawing kernel text over the GUI. It still goes to the persistent log; panics are drawn
sweetfb_hz=30 Panel refresh rate of the CPU copy
sweettouch=0, sweetkeys=0 Disable the touch or button driver

4. Flash the root and boot

fastboot -S 512M flash userdata ios16-root.simg   # ~7 minutes; do not unplug
# Xiaomi's fastboot often hangs after a large flash: re-enter fastboot with Power + Volume down
fastboot boot shim/out/shim-boot.img

The first boot takes about 4–5 minutes on the Apple logo, then the lock screen appears. Swipe up to unlock. To get back to fastboot, hold Power + Volume down.

5. Read the kernel log

fastboot boot recovery/recovery.img        # OrangeFox, temporary
tools/sweet-log-pull.sh logs/boot.txt      # 4 MiB console ring from the end of userdata
adb reboot bootloader

The log contains crash reports with backtraces (CRASH name ...), IOKit traces of backboardd and SpringBoard, and the drivers' SWEET ... lines. tools/sweet-crash.py symbolicates them against the shared cache.

QEMU

tools/qemu-sweet.py boots the same kernel on QEMU virt with a test RAM-disk root. It is useful for kernel-only changes; see NOTES.md.

Repository layout

Path What
shim/ Bare-metal boot shim (C + asm) packed as an Android boot.img v2
xnu/patches/ The XNU patch series (applied in order by CI), plus staging scripts for libpthread, HFS and BearSSL
.github/workflows/xnu.yml Kernel CI build
tools/mkadt.py Generates the Apple Device Tree from sweet's MMIO layout and the iPhone X identity
tools/mkpayload.py Packs kernel + ADT + boot-args into the shim payload
tools/mkiosroot.sh Builds the HFS+ iOS root from the IPSW images
tools/sweet-root-tweaks.py Bring-up changes to the root (Setup skip, activation, daemons)
tools/sweet-log-pull.sh, sweet-log.py Read the persistent kernel log from recovery
tools/sweet-crash.py Symbolicate console crash reports
tools/xnu-cc.py Local single-file compile check from a CI log
tools/qemu-sweet.py QEMU test boots with framebuffer text decoding
tools/adt.py, remotezip.py, unpack_bootv2.py, sparsediff.py Helpers
NOTES.md Detailed engineering log: every boot, crash and decision, plus hardware facts

Not in git: partition backups, live device trees, recovery images, Apple firmware and root images, and downloaded or generated build trees. They contain device serials and calibration data, or Apple's copyrighted files.

Kernel patches

# What
0001–0009 Toolchain compatibility, SWEET machine config, non-PAC arm64, stubs for Apple-internal pieces
0010–0018 Early framebuffer console, physmap fix, PRNG without corecrypto, device-tree platform expert, timer PPI, boot CPU driver
0019–0020 Apple open-source libpthread kernel provider; BearSSL AES
0021–0027 RAM-disk root, mockfs, SHA-256, minimal AMFI, Apple open-source HFS+, MD5
0028–0034 UFS host driver and root device, read/write root, DMA above 4 GiB
0035–0045 Entitlements, bindfs, AppleKeyStore stub, IOWatchdog, console crash reports
0046 IOSurface (IOCoreSurfaceRoot) and IOMobileFramebuffer (AppleCLCD) services
0047–0055 Diagnostics: persistent log, /dev/null tee, IOKit trace, heap strings and user stack sampler on crash; permissive Sandbox policy; HFS rename-swap; AppleKeyStore selectors
0056–0057 Throttled panel copy; no external identity resolver
0058 HID event services. Apple's IOHIDFamily-1915.140.3 user client and event queue, matching the iOS 16.7 userland
0059 iPhone X identity (hw.product / hw.target from the device tree)
0060 Power and volume keys over SPMI; touch over GENI I²C
0061 Present the display as 1125×2436
0062 RPMh regulator vote for the touch rail; battery power source
0063 GENI FIFO packing fix and the Goodix GT9896 protocol
0064 Grant PRIV_WORK_INTERVAL (UIKit's CoreAnimation work interval)
0065 SMP: secondary A55 cores via PSCI CPU_ON
0066–0067 Fault-region crash info; console mute
0068 IOSurface lookup semantics for already-mapped surfaces
0069 Batched persistent-log flushes

Key hardware facts

More in NOTES.md.

Credits

Built on Apple's open-source releases (xnu, IOHIDFamily, libpthread, hfs), BearSSL, blacktop/darwin-xnu-build, ipsw, Qualcomm/Xiaomi's published Linux kernel sources for the hardware details, and OrangeFox Recovery. iOS itself is Apple's and is not distributed here.

ios-sweet (dipa-studio/ios-sweet)

bare-metal
Searching Database…

What is this?ios-sweet ports Apple's open-source XNU kernel (xnu-8796, the iOS 16 generation) to the Xiaomi Redmi Note 10 Pro (sweet, Qualcomm SM7150), running the real iPhone X iOS 16.7.16 userland (launchd, SpringBoard, backboardd, stock apps) on the phone.
Is this a jailbreak tweak or a full kernel/OS port?It is a from-scratch bring-up: a custom bare-metal boot shim plus dozens of XNU kernel patches that port Apple's kernel to new hardware, not a jailbreak of an existing iPhone. The authors call it an experimental bring-up, not a usable phone OS.
How do I get this running on my own phone?You back up the phone's partitions, build the XNU kernel via the GitHub Actions workflow on macOS runners, build the iOS root HFS+ volume from the real iPhone X IPSW on Linux with apfs-fuse and hfsprogs, build the boot image with aarch64-linux-gnu-gcc and mkbootimg, then fastboot-flash root and boot images.
What hardware and tools do I need before starting?A Redmi Note 10 Pro (sweet, SM7150) with an unlocked bootloader, a Linux PC, a GitHub account for CI kernel builds, Apple's iPhone X 16.7.16 (20H392) IPSW, apfs-fuse/hfsprogs for the root image, and aarch64-linux-gnu-gcc plus mkbootimg for the boot image.
What doesn't work yet?There is no Wi-Fi, Bluetooth, cellular, audio, camera, sensors, GPS or Face ID/SEP, no GPU (everything renders on the CPU at 20-30 fps), you cannot leave an open app yet, boot takes about 4 minutes, and Apple's security model (AMFI, sandbox, data protection) is mostly switched off.
Is it safe to put personal data on this device?No. Code signing, sandbox policies and data protection are disabled and AppleKeyStore is just a stub, so the README explicitly warns against storing anything personal on it.
Does rendering use the GPU?No, there is no GPU driver. CoreAnimation renders entirely on the CPU and frames are copied into the bootloader's framebuffer at roughly 20-30 fps, and the two Cortex-A76 performance cores aren't used yet.
Can I leave an app once it's open?Not yet. The home gesture and AssistiveTouch Home don't do anything in the current bring-up, so you're stuck in whatever app you open.
Does flashing this wipe my Android phone?Yes, the iOS root is installed into the userdata partition and erases Android's user data, though the bootloader, recovery, modem and persist partitions are never touched.
How is the kernel log captured without a serial port?The board has no accessible debug UART, so the kernel keeps a persistent 4 MiB log ring at the end of userdata, which you pull from OrangeFox recovery using tools/sweet-log-pull.sh.
Size
0.4 MB
Stars
490
Updated
CommitOct 19
Age
5d
Commits · 90 Days