#709

Add data-preserving iOS OTA workflow

Open0xJackywants to merge intofrom

What

An experimental, host-driven path that moves an installed iPhone/iPad guest from iOS 26 to 27.0.1 (24A446) without erasing its data. It installs Apple's full OTA System payload on a private clone of the stopped disk and keeps the APFS container, the encrypted Data/User volumes, SEPStorage, NVRAM and the guest's Preboot identity.

  • fw ota-stage: stages a full OTA into OTAUserland/. It refuses delta OTAs (PrerequisiteBuild), checks device and build against the OTA and the prepared IPSW, and validates every payload chunk and payloadv2/links.txt together (no absolute or traversing paths, no member below a symlink or other non-directory, no type changes, hard links only to archived regular files).
  • cfw install with the new system-exp-ota_userland patch (off in Standard and both TV presets): replaces System, kernelcache and TXM in one private-clone transaction. The new kernelcache and TXM IM4Ps go into the existing personalized IMG4s, so the IM4M is retained. The installer then restores the OTA's hard links through confined parent descriptors, reapplies the target Guest patches from a fresh receipt state and stages the target IPSW's staged_system_apps. Any compatibility-patch failure discards the clone; the original disk is never edited in place.
  • fw ota (capture, checkpoint, isolate, quiesce, prepare, complete, commit, verify, rollback, status): a durable journal outside the machine folder for coordinators. One disk/SEP/NVRAM snapshot plus APFS clones of host configuration and firmware inputs form the rollback unit. The network stays off until offline verification passes; rolling back a completed or committed update needs explicit flags.
  • fw ota-preflight: read-only check of a running source (migration result, service overrides) with the same gate capture applies.
  • vphoned: ota.apps.status / ota.apps.apply {force:true} (capability ota_system_apps) update already-installed removable Apple app programs in place from the staged target programs, keeping old programs and serialized placeholders under inactive names. display.auto_lock.set {seconds} writes the UserSettings input so profiled regenerates the effective policy.
  • scripts/ota-upgrade.zsh: a developer coordinator that runs the phases through vphone-launchpad-cli and rolls back on failure before the network commit.

Why

restore cannot keep a guest's data: the cloudOS erase ramdisk reformats the container even for an update (Research/Restore/native_restore_architecture.md). A full OTA's payload replaces System while the encrypted volumes stay put. Two things turned out to be required beyond extraction:

  • payloadv2/links.txt: the 24A446 iPad OTA leaves 24,835 duplicate paths out of its numbered chunks. Without them, per-device media resources are missing, audiomxd traps in CFRetain(NULL), and DataMigrator never finishes (locationd → liveactivitiesd → audiomxd).
  • Removable Apple apps live on Data and keep their 26.x programs, which fail against 27 frameworks (e.g. Calendar/Music widgets with missing symbols). The OTA only carries placeholders; the matching IPSW has the full 27 programs.

Compatibility

  • Opt-in only: the patch is off in every shipped preset, and the commands do nothing until called. Existing machines, restores and cfw install runs without the patch are unchanged.
  • No vphone-cli output or argument Launchpad relies on changes, so no series bump.
  • The path is pinned to iPhone/iPad 27.0.1 (24A446) with the source cloudOS kept; capture refuses anything else.
  • Protected third-party apps must already carry a container-required entitlement naming their existing data container; nothing is re-signed implicitly.

Tests

  • VPhoneCoreKitTests (new OTAUpdateTests: journal, checkpoint/resume, isolation/commit, rollback, path injection), VPhoneArchiveKitTests (94, including hard-link parsing and cross-chunk validation), CustomFirmwareKernelcacheSwapTests and FirmwarePatchSetCatalogTests (27, including the TXM swap).
  • scripts/tests/ota-upgrade-tests.zsh: success, preparation failure with rollback, checkpoint failure with source restart, wrong bundle binding, failure after the commit boundary.
  • On a canary iPad16,1 26.6.2 (23G90) guest: the OTA booted 27.0.1 (24A446), DataMigrator finished with success=true, a marker on the encrypted Data volume survived, and cold boots and guest reboots kept Setup complete. A clone of a machine with a third-party app reopened that app's existing data at 4/3/2 GB. The Auto-Lock convergence step is the one part of complete not yet seen passing end to end.

Details, evidence and the runbook: Research/Restore/data_preserving_full_ota.md.

🤖 Generated with Claude Code

Activity

0

No activity yet.