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.
107 lines
6.1 KiB
Python
Executable File
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()
|