Files
UniXNU/scripts/seed-data-skip-setup.py
T
rpone ab11a8cb68 feat(scripts): iPadOS 27 kernel, driver, GPU addon and seed build steps
Source-driver and source-storage builds, the arm64e PAC rewrite for the Rust bridge, the IOAccelerator base ABI of 24A446, the bridge with mimalloc and link-time optimisation, the plugin with the prime list, addon options for a prime list, a pipeline pack and cache export, wallpaper overlay and seed changes, and payload, kernel and userdata steps for the new profile.
2026-10-28 09:20:55 +08:00

107 lines
6.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Make a Data seed that boots to SpringBoard instead of Setup: the preference changes github.com/dipa-studio/ios-sweet
(tools/sweet-root-tweaks.py) established on hardware, applied to a copy of an existing packed Data seed.
seed-data-skip-setup.py BASE.dbr OUTPUT.dbr [--no-auto-dim] [--build=BUILD]
BASE is a DBRDISK1 packed APFS container (drivers/DarwinBoot/Test/packed_ramdisk.py format). It is expanded to a raw image, attached
read-write on this Mac, the preference files below are merged into /private/var/mobile/Library/Preferences, and the result is packed
again. The volume UUID is unchanged. Nothing is written to Git or to the OS inputs; BASE is not modified.
com.apple.purplebuddy SetupDone, SetupFinishedAllSteps, SetupVersion 11, daemonizeNeedsToRun false (skips Setup)
com.apple.purplebuddy.notbackedup the mini-buddy flags false
com.apple.managedconfiguration.notbackedup LockdownActivationIndicatesCloudConfigurationAvailable false
com.apple.springboard BKNoWatchdogs, FBLaunchWatchdogExceptions{com.apple.purplebuddy: 100}, MCForceShowCloudConfigurationUI false
com.apple.migration LastSystemVersion (no data migration on every boot)
and the container directories under /private/var/containers that on a device live on the data volume.
--build names the OS build the seed boots (default 21H461): LastSystemVersion must equal it, or the system migrates its data on
the first boot (the progress bar under the Apple logo).
--no-auto-dim also sets com.apple.springboard SBDisableAutoDim, SBDontDimOrLockOnAC and SBDisableIdleSleep (as UniXNU-qemu's
build-os-root.py does): a board without input would otherwise turn its display off about 30 seconds after SpringBoard starts
and put the system to sleep.
"""
import hashlib, json, os, plistlib, subprocess, sys, tempfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / 'drivers/DarwinBoot/Test'))
import packed_ramdisk
BUILD, VERSION = '21H461', '17.7.11'
MOBILE = 501
def merge_pref(var, name, values):
path = var / 'mobile/Library/Preferences' / (name + '.plist')
path.parent.mkdir(parents=True, exist_ok=True)
data = plistlib.loads(path.read_bytes()) if path.exists() else {}
data.update(values)
path.write_bytes(plistlib.dumps(data, fmt=plistlib.FMT_BINARY))
os.chmod(path, 0o600)
print('pref', name, sorted(values))
def main():
global BUILD
no_auto_dim = '--no-auto-dim' in sys.argv[1:]
for arg in sys.argv[1:]:
if arg.startswith('--build='):
BUILD = arg.split('=', 1)[1]
positional = [arg for arg in sys.argv[1:] if arg != '--no-auto-dim' and not arg.startswith('--build=')]
if len(positional) != 2:
sys.exit(__doc__)
base, output = Path(positional[0]).resolve(), Path(positional[1]).resolve()
if output.exists():
sys.exit('Refuse to overwrite ' + str(output))
blob = base.read_bytes()
logical, extents = packed_ramdisk.regions(blob)
with tempfile.TemporaryDirectory(prefix='data-seed-', dir=str(ROOT / 'build')) as td:
raw = Path(td) / 'seed.raw'
with raw.open('wb') as f:
f.truncate(logical)
for offset, data in extents:
f.seek(offset)
f.write(data)
mount = Path(td) / 'mount'
mount.mkdir()
attached = plistlib.loads(subprocess.check_output(
['hdiutil', 'attach', '-imagekey', 'diskimage-class=CRawDiskImage', '-nobrowse', '-owners', 'off',
'-mountpoint', str(mount), '-plist', str(raw)]))
device = attached['system-entities'][0]['dev-entry']
try:
if not (mount / 'mobile').is_dir():
sys.exit('The Data seed has no /mobile; wrong base image?')
merge_pref(mount, 'com.apple.migration', {
'LastSystemVersion': BUILD,
'DMUserDataDisposition': {'SyntheticDidUpgrade': False, 'buildVersion': BUILD}})
merge_pref(mount, 'com.apple.springboard', {
'BKNoWatchdogs': True,
'FBLaunchWatchdogExceptions': {'com.apple.purplebuddy': 100.0},
'MCForceShowCloudConfigurationUI': False,
**({'SBDisableAutoDim': True, 'SBDontDimOrLockOnAC': True, 'SBDisableIdleSleep': True} if no_auto_dim else {})})
merge_pref(mount, 'com.apple.purplebuddy', {
'SetupDone': True, 'SetupFinishedAllSteps': True, 'SetupVersion': 11, 'daemonizeNeedsToRun': False})
merge_pref(mount, 'com.apple.purplebuddy.notbackedup', {
k: False for k in ('ShouldRunDiagnosticsMiniBuddy', 'ShouldRunHSA2MiniBuddy', 'ShouldRunKeychainSyncMiniBuddy',
'ShouldRunMesaMiniBuddy', 'ShouldRunPaymentMiniBuddy', 'ShouldRunStandardMiniBuddy',
'SilentICDPUpgrade')})
merge_pref(mount, 'com.apple.managedconfiguration.notbackedup', {
'LockdownActivationIndicatesCloudConfigurationAvailable': False})
for sub in ('Bundle', 'Data/System', 'Shared/SystemGroup', 'Temp'):
d = mount / 'containers' / sub
if not d.is_dir():
d.mkdir(parents=True)
os.chmod(d, 0o755)
print('mkdir', d.relative_to(mount))
finally:
subprocess.run(['hdiutil', 'detach', device], check=True)
if raw.read_bytes()[32:36] != b'NXSB':
sys.exit('The edited image is no APFS container any more')
metadata = packed_ramdisk.pack(raw, output)
report = dict(base_sha256=packed_ramdisk.inspect(base)[0]['sha256'], output=metadata,
preferences=['com.apple.migration', 'com.apple.springboard', 'com.apple.purplebuddy',
'com.apple.purplebuddy.notbackedup', 'com.apple.managedconfiguration.notbackedup'],
no_auto_dim=no_auto_dim, build=BUILD, source='github.com/dipa-studio/ios-sweet tools/sweet-root-tweaks.py')
output.with_suffix('.json').write_text(json.dumps(report, indent=2) + '\n')
print(json.dumps(report, indent=2))
if __name__ == '__main__':
main()