Files
UniXNU/scripts/seed-data-skip-setup.py
T
xVanTuring 12c5d446e3 feat(payload): pass board arguments to the skip-setup tool, add --no-auto-dim
[payload] skip_setup_args (optional) is passed to skip_setup_tool after
the two paths, and the edited seed is cached by the hash of the base and
of those arguments.

seed-data-skip-setup.py --no-auto-dim also sets SBDisableAutoDim,
SBDontDimOrLockOnAC and SBDisableIdleSleep in com.apple.springboard, as
UniXNU-qemu's build-os-root.py does: a board without buttons or a working
idle timer otherwise turns its display off about 30 seconds after
SpringBoard starts and puts the system to sleep.
2026-10-22 19:04:37 +08:00

101 lines
5.7 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]
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.
--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():
no_auto_dim = '--no-auto-dim' in sys.argv[1:]
positional = [arg for arg in sys.argv[1:] if arg != '--no-auto-dim']
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()