pymobiledevice3 4.14.6__py3-none-any.whl → 7.0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. misc/understanding_idevice_protocol_layers.md +15 -10
  4. pymobiledevice3/__main__.py +317 -127
  5. pymobiledevice3/_version.py +22 -4
  6. pymobiledevice3/bonjour.py +358 -113
  7. pymobiledevice3/ca.py +253 -16
  8. pymobiledevice3/cli/activation.py +31 -23
  9. pymobiledevice3/cli/afc.py +49 -40
  10. pymobiledevice3/cli/amfi.py +16 -21
  11. pymobiledevice3/cli/apps.py +87 -42
  12. pymobiledevice3/cli/backup.py +160 -90
  13. pymobiledevice3/cli/bonjour.py +44 -40
  14. pymobiledevice3/cli/cli_common.py +204 -198
  15. pymobiledevice3/cli/companion_proxy.py +14 -14
  16. pymobiledevice3/cli/crash.py +105 -56
  17. pymobiledevice3/cli/developer/__init__.py +62 -0
  18. pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
  19. pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
  20. pymobiledevice3/cli/developer/arbitration.py +50 -0
  21. pymobiledevice3/cli/developer/condition.py +33 -0
  22. pymobiledevice3/cli/developer/core_device.py +294 -0
  23. pymobiledevice3/cli/developer/debugserver.py +244 -0
  24. pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
  25. pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
  26. pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
  27. pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
  28. pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
  29. pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
  30. pymobiledevice3/cli/developer/simulate_location.py +51 -0
  31. pymobiledevice3/cli/diagnostics/__init__.py +75 -0
  32. pymobiledevice3/cli/diagnostics/battery.py +47 -0
  33. pymobiledevice3/cli/idam.py +42 -0
  34. pymobiledevice3/cli/lockdown.py +108 -103
  35. pymobiledevice3/cli/mounter.py +158 -99
  36. pymobiledevice3/cli/notification.py +38 -26
  37. pymobiledevice3/cli/pcap.py +45 -24
  38. pymobiledevice3/cli/power_assertion.py +18 -17
  39. pymobiledevice3/cli/processes.py +17 -23
  40. pymobiledevice3/cli/profile.py +165 -109
  41. pymobiledevice3/cli/provision.py +35 -34
  42. pymobiledevice3/cli/remote.py +217 -129
  43. pymobiledevice3/cli/restore.py +159 -143
  44. pymobiledevice3/cli/springboard.py +63 -53
  45. pymobiledevice3/cli/syslog.py +193 -86
  46. pymobiledevice3/cli/usbmux.py +73 -33
  47. pymobiledevice3/cli/version.py +5 -7
  48. pymobiledevice3/cli/webinspector.py +376 -214
  49. pymobiledevice3/common.py +3 -1
  50. pymobiledevice3/exceptions.py +182 -58
  51. pymobiledevice3/irecv.py +52 -53
  52. pymobiledevice3/irecv_devices.py +1489 -464
  53. pymobiledevice3/lockdown.py +473 -275
  54. pymobiledevice3/lockdown_service_provider.py +15 -8
  55. pymobiledevice3/osu/os_utils.py +27 -9
  56. pymobiledevice3/osu/posix_util.py +34 -15
  57. pymobiledevice3/osu/win_util.py +14 -8
  58. pymobiledevice3/pair_records.py +102 -21
  59. pymobiledevice3/remote/common.py +8 -4
  60. pymobiledevice3/remote/core_device/app_service.py +94 -67
  61. pymobiledevice3/remote/core_device/core_device_service.py +17 -14
  62. pymobiledevice3/remote/core_device/device_info.py +5 -5
  63. pymobiledevice3/remote/core_device/diagnostics_service.py +19 -4
  64. pymobiledevice3/remote/core_device/file_service.py +53 -23
  65. pymobiledevice3/remote/remote_service_discovery.py +79 -45
  66. pymobiledevice3/remote/remotexpc.py +73 -44
  67. pymobiledevice3/remote/tunnel_service.py +442 -317
  68. pymobiledevice3/remote/utils.py +14 -13
  69. pymobiledevice3/remote/xpc_message.py +145 -125
  70. pymobiledevice3/resources/dsc_uuid_map.py +19 -19
  71. pymobiledevice3/resources/firmware_notifications.py +20 -16
  72. pymobiledevice3/resources/notifications.txt +144 -0
  73. pymobiledevice3/restore/asr.py +27 -27
  74. pymobiledevice3/restore/base_restore.py +110 -21
  75. pymobiledevice3/restore/consts.py +87 -66
  76. pymobiledevice3/restore/device.py +59 -12
  77. pymobiledevice3/restore/fdr.py +46 -48
  78. pymobiledevice3/restore/ftab.py +19 -19
  79. pymobiledevice3/restore/img4.py +163 -0
  80. pymobiledevice3/restore/mbn.py +587 -0
  81. pymobiledevice3/restore/recovery.py +151 -151
  82. pymobiledevice3/restore/restore.py +562 -544
  83. pymobiledevice3/restore/restore_options.py +131 -110
  84. pymobiledevice3/restore/restored_client.py +51 -31
  85. pymobiledevice3/restore/tss.py +385 -267
  86. pymobiledevice3/service_connection.py +252 -59
  87. pymobiledevice3/services/accessibilityaudit.py +202 -120
  88. pymobiledevice3/services/afc.py +962 -365
  89. pymobiledevice3/services/amfi.py +24 -30
  90. pymobiledevice3/services/companion.py +23 -19
  91. pymobiledevice3/services/crash_reports.py +71 -47
  92. pymobiledevice3/services/debugserver_applist.py +3 -3
  93. pymobiledevice3/services/device_arbitration.py +8 -8
  94. pymobiledevice3/services/device_link.py +101 -79
  95. pymobiledevice3/services/diagnostics.py +973 -967
  96. pymobiledevice3/services/dtfetchsymbols.py +8 -8
  97. pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
  98. pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
  99. pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
  100. pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
  101. pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
  102. pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
  103. pymobiledevice3/services/dvt/instruments/device_info.py +20 -11
  104. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  105. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  106. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  107. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  108. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  109. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  110. pymobiledevice3/services/dvt/instruments/process_control.py +35 -10
  111. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  112. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  113. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
  114. pymobiledevice3/services/file_relay.py +10 -10
  115. pymobiledevice3/services/heartbeat.py +9 -8
  116. pymobiledevice3/services/house_arrest.py +16 -15
  117. pymobiledevice3/services/idam.py +20 -0
  118. pymobiledevice3/services/installation_proxy.py +173 -81
  119. pymobiledevice3/services/lockdown_service.py +20 -10
  120. pymobiledevice3/services/misagent.py +22 -19
  121. pymobiledevice3/services/mobile_activation.py +147 -64
  122. pymobiledevice3/services/mobile_config.py +331 -294
  123. pymobiledevice3/services/mobile_image_mounter.py +141 -113
  124. pymobiledevice3/services/mobilebackup2.py +203 -145
  125. pymobiledevice3/services/notification_proxy.py +11 -11
  126. pymobiledevice3/services/os_trace.py +134 -74
  127. pymobiledevice3/services/pcapd.py +314 -302
  128. pymobiledevice3/services/power_assertion.py +10 -9
  129. pymobiledevice3/services/preboard.py +4 -4
  130. pymobiledevice3/services/remote_fetch_symbols.py +21 -14
  131. pymobiledevice3/services/remote_server.py +176 -146
  132. pymobiledevice3/services/restore_service.py +16 -16
  133. pymobiledevice3/services/screenshot.py +15 -12
  134. pymobiledevice3/services/simulate_location.py +7 -7
  135. pymobiledevice3/services/springboard.py +15 -15
  136. pymobiledevice3/services/syslog.py +5 -5
  137. pymobiledevice3/services/web_protocol/alert.py +11 -11
  138. pymobiledevice3/services/web_protocol/automation_session.py +251 -239
  139. pymobiledevice3/services/web_protocol/cdp_screencast.py +46 -37
  140. pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
  141. pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
  142. pymobiledevice3/services/web_protocol/driver.py +114 -111
  143. pymobiledevice3/services/web_protocol/element.py +124 -111
  144. pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
  145. pymobiledevice3/services/web_protocol/selenium_api.py +49 -49
  146. pymobiledevice3/services/web_protocol/session_protocol.py +18 -12
  147. pymobiledevice3/services/web_protocol/switch_to.py +30 -27
  148. pymobiledevice3/services/webinspector.py +189 -155
  149. pymobiledevice3/tcp_forwarder.py +87 -69
  150. pymobiledevice3/tunneld/__init__.py +0 -0
  151. pymobiledevice3/tunneld/api.py +63 -0
  152. pymobiledevice3/tunneld/server.py +603 -0
  153. pymobiledevice3/usbmux.py +198 -147
  154. pymobiledevice3/utils.py +14 -11
  155. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +55 -28
  156. pymobiledevice3-7.0.6.dist-info/RECORD +188 -0
  157. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +1 -1
  158. pymobiledevice3/cli/developer.py +0 -1215
  159. pymobiledevice3/cli/diagnostics.py +0 -99
  160. pymobiledevice3/tunneld.py +0 -524
  161. pymobiledevice3-4.14.6.dist-info/RECORD +0 -168
  162. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
  163. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info/licenses}/LICENSE +0 -0
  164. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
@@ -9,31 +9,33 @@ from ipsw_parser.ipsw import IPSW
9
9
 
10
10
  from pymobiledevice3.exceptions import PyMobileDevice3Exception
11
11
  from pymobiledevice3.restore.device import Device
12
+ from pymobiledevice3.restore.img4 import stitch_component
12
13
  from pymobiledevice3.restore.tss import TSSResponse
13
14
 
14
- RESTORE_VARIANT_ERASE_INSTALL = 'Erase Install (IPSW)'
15
- RESTORE_VARIANT_UPGRADE_INSTALL = 'Upgrade Install (IPSW)'
16
- RESTORE_VARIANT_MACOS_RECOVERY_OS = 'macOS Customer'
15
+ RESTORE_VARIANT_ERASE_INSTALL = "Erase Install (IPSW)"
16
+ RESTORE_VARIANT_UPGRADE_INSTALL = "Upgrade Install (IPSW)"
17
+ RESTORE_VARIANT_MACOS_RECOVERY_OS = "macOS Customer"
17
18
 
18
19
 
19
20
  class Behavior(Enum):
20
- Update = 'Update'
21
- Erase = 'Erase'
21
+ Update = "Update"
22
+ Erase = "Erase"
22
23
 
23
24
 
24
25
  class BaseRestore:
25
- def __init__(self, ipsw: ZipFile, device: Device, tss: Optional[dict] = None,
26
- behavior: Behavior = Behavior.Update) -> None:
26
+ def __init__(
27
+ self, ipsw: ZipFile, device: Device, tss: Optional[dict] = None, behavior: Behavior = Behavior.Update
28
+ ) -> None:
27
29
  self.ipsw = IPSW(ipsw)
28
30
  self.device = device
29
31
  self.tss = TSSResponse(tss) if tss is not None else None
30
32
 
31
33
  if not self.device.is_image4_supported:
32
- raise NotImplementedError('is_image4_supported is False')
34
+ raise NotImplementedError("is_image4_supported is False")
33
35
 
34
- self.logger.info(f'connected device: {self.device}')
36
+ self.logger.info(f"connected device: {self.device}")
35
37
 
36
- self.logger.debug('scanning BuildManifest.plist for the correct BuildIdentity')
38
+ self.logger.debug("scanning BuildManifest.plist for the correct BuildIdentity")
37
39
 
38
40
  variant = {
39
41
  Behavior.Update: RESTORE_VARIANT_UPGRADE_INSTALL,
@@ -41,33 +43,120 @@ class BaseRestore:
41
43
  }[behavior]
42
44
 
43
45
  try:
44
- self.build_identity = self.ipsw.build_manifest.get_build_identity(self.device.hardware_model,
45
- restore_behavior=behavior.value,
46
- variant=variant)
46
+ self.build_identity = self.ipsw.build_manifest.get_build_identity(
47
+ self.device.hardware_model, restore_behavior=behavior.value, variant=variant
48
+ )
47
49
  except NoSuchBuildIdentityError:
48
50
  if behavior == Behavior.Update:
49
- self.build_identity = self.ipsw.build_manifest.get_build_identity(self.device.hardware_model,
50
- restore_behavior=behavior.value)
51
+ self.build_identity = self.ipsw.build_manifest.get_build_identity(
52
+ self.device.hardware_model, restore_behavior=behavior.value
53
+ )
51
54
  else:
52
55
  raise
53
56
 
54
57
  self.macos_variant = None
55
58
  try:
56
59
  self.macos_variant = self.ipsw.build_manifest.get_build_identity(
57
- self.device.hardware_model,
58
- variant=RESTORE_VARIANT_MACOS_RECOVERY_OS)
59
- self.logger.info('Performing macOS restore')
60
+ self.device.hardware_model, variant=RESTORE_VARIANT_MACOS_RECOVERY_OS
61
+ )
62
+ self.logger.info("Performing macOS restore")
60
63
  except NoSuchBuildIdentityError:
61
64
  pass
62
65
 
63
- build_info = self.build_identity.get('Info')
66
+ build_info = self.build_identity.get("Info")
64
67
  if build_info is None:
65
68
  raise PyMobileDevice3Exception('build identity does not contain an "Info" element')
66
69
 
67
- device_class = build_info.get('DeviceClass')
70
+ device_class = build_info.get("DeviceClass")
68
71
  if device_class is None:
69
72
  raise PyMobileDevice3Exception('build identity does not contain an "DeviceClass" element')
70
73
 
71
74
  @property
72
75
  def logger(self) -> logging.Logger:
73
- return logging.getLogger(f'{asyncio.current_task().get_name()}-{self.__class__.__module__}')
76
+ return logging.getLogger(f"{asyncio.current_task().get_name()}-{self.__class__.__module__}")
77
+
78
+ def get_personalized_data(
79
+ self,
80
+ component_name: str,
81
+ data: Optional[bytes] = None,
82
+ tss: Optional[TSSResponse] = None,
83
+ path: Optional[str] = None,
84
+ ) -> bytes:
85
+ return stitch_component(
86
+ component_name,
87
+ self.build_identity.get_component(component_name, tss=tss, data=data, path=path).data,
88
+ tss,
89
+ self.build_identity,
90
+ self.device.ap_parameters,
91
+ )
92
+
93
+ def populate_tss_request_from_manifest(self, parameters: dict, additional_keys: Optional[list[str]] = None) -> None:
94
+ """equivalent to idevicerestore:tss_parameters_add_from_manifest"""
95
+ key_list = ["ApBoardID", "ApChipID"]
96
+ if additional_keys is None:
97
+ key_list += [
98
+ "UniqueBuildID",
99
+ "Ap,OSLongVersion",
100
+ "Ap,OSReleaseType",
101
+ "Ap,ProductType",
102
+ "Ap,SDKPlatform",
103
+ "Ap,SikaFuse",
104
+ "Ap,Target",
105
+ "Ap,TargetType",
106
+ "ApBoardID",
107
+ "ApChipID",
108
+ "ApSecurityDomain",
109
+ "BMU,BoardID",
110
+ "BMU,ChipID",
111
+ "BbChipID",
112
+ "BbProvisioningManifestKeyHash",
113
+ "BbActivationManifestKeyHash",
114
+ "BbCalibrationManifestKeyHash",
115
+ "Ap,ProductMarketingVersion",
116
+ "BbFactoryActivationManifestKeyHash",
117
+ "BbFDRSecurityKeyHash",
118
+ "BbSkeyId",
119
+ "SE,ChipID",
120
+ "Savage,ChipID",
121
+ "Savage,PatchEpoch",
122
+ "Yonkers,BoardID",
123
+ "Yonkers,ChipID",
124
+ "Yonkers,PatchEpoch",
125
+ "Rap,BoardID",
126
+ "Rap,ChipID",
127
+ "Rap,SecurityDomain",
128
+ "Baobab,BoardID",
129
+ "Baobab,ChipID",
130
+ "Baobab,ManifestEpoch",
131
+ "Baobab,SecurityDomain",
132
+ "eUICC,ChipID",
133
+ "PearlCertificationRootPub",
134
+ "Timer,BoardID,1",
135
+ "Timer,BoardID,2",
136
+ "Timer,ChipID,1",
137
+ "Timer,ChipID,2",
138
+ "Timer,SecurityDomain,1",
139
+ "Timer,SecurityDomain,2",
140
+ "Manifest",
141
+ "NeRDEpoch",
142
+ ]
143
+ else:
144
+ key_list += additional_keys
145
+
146
+ for k in key_list:
147
+ try:
148
+ v = self.build_identity[k]
149
+ if isinstance(v, str) and v.startswith("0x"):
150
+ v = int(v, 16)
151
+ parameters[k] = v
152
+ except KeyError:
153
+ pass
154
+
155
+ if additional_keys is None:
156
+ # special treat for RequiresUIDMode
157
+ info = self.build_identity.get("Info")
158
+ if info is None:
159
+ return
160
+ requires_uid_mode = info.get("RequiresUIDMode")
161
+ if requires_uid_mode is not None:
162
+ parameters["RequiresUIDMode"] = requires_uid_mode
@@ -1,70 +1,91 @@
1
- lpol_file = bytes([0x30, 0x14, 0x16, 0x04, 0x49, 0x4d, 0x34, 0x50,
2
- 0x16, 0x04, 0x6c, 0x70, 0x6f, 0x6c, 0x16, 0x03,
3
- 0x31, 0x2e, 0x30, 0x04, 0x01, 0x00])
1
+ lpol_file = bytes([
2
+ 0x30,
3
+ 0x14,
4
+ 0x16,
5
+ 0x04,
6
+ 0x49,
7
+ 0x4D,
8
+ 0x34,
9
+ 0x50,
10
+ 0x16,
11
+ 0x04,
12
+ 0x6C,
13
+ 0x70,
14
+ 0x6F,
15
+ 0x6C,
16
+ 0x16,
17
+ 0x03,
18
+ 0x31,
19
+ 0x2E,
20
+ 0x30,
21
+ 0x04,
22
+ 0x01,
23
+ 0x00,
24
+ ])
4
25
 
5
26
  # extracted from ac2
6
27
  PROGRESS_BAR_OPERATIONS = {
7
- 11: 'CREATE_PARTITION_MAP',
8
- 12: 'CREATE_FILESYSTEM',
9
- 13: 'RESTORE_IMAGE',
10
- 14: 'VERIFY_RESTORE',
11
- 15: 'CHECK_FILESYSTEMS',
12
- 16: 'MOUNT_FILESYSTEMS',
13
- 17: 'FIXUP_VAR',
14
- 18: 'FLASH_FIRMWARE',
15
- 19: 'UPDATE_BASEBAND',
16
- 20: 'SET_BOOT_STAGE',
17
- 21: 'REBOOT_DEVICE',
18
- 22: 'SHUTDOWN_DEVICE',
19
- 23: 'TURN_ON_ACCESSORY_POWER',
20
- 24: 'CLEAR_BOOTARGS',
21
- 25: 'MODIFY_BOOTARGS',
22
- 26: 'INSTALL_ROOT',
23
- 27: 'INSTALL_KERNELCACHE',
24
- 28: 'WAIT_FOR_NAND',
25
- 29: 'UNMOUNT_FILESYSTEMS',
26
- 30: 'SET_DATETIME',
27
- 31: 'EXEC_IBOOT',
28
- 32: 'FINALIZE_NAND_EPOCH_UPDATE',
29
- 33: 'CHECK_INAPPR_BOOT_PARTITIONS',
30
- 34: 'CREATE_FACTORY_RESTORE_MARKER',
31
- 35: 'LOAD_FIRMWARE',
32
- 36: 'REQUESTING_FUD_DATA',
33
- 37: 'REMOVING_ACTIVATION_RECORD',
34
- 38: 'CHECK_BATTERY_VOLTAGE',
35
- 39: 'WAIT_BATTERY_CHARGE',
36
- 40: 'CLOSE_MODEM_TICKETS',
37
- 41: 'MIGRATE_DATA',
38
- 42: 'WIPE_STORAGE_DEVICE',
39
- 43: 'SEND_APPLE_LOGO',
40
- 44: 'CHECK_LOGS',
41
- 46: 'CLEAR_NVRAM',
42
- 47: 'UPDATE_GAS_GAUGE',
43
- 48: 'PREPARE_BASEBAND_UPDATE',
44
- 49: 'BOOT_BASEBAND',
45
- 50: 'CREATE_SYSTEM_KEYBAG',
46
- 51: 'UPDATE_IR_MCU_FIRMWARE',
47
- 52: 'RESIZE_SYSTEM_PARTITION',
48
- 53: 'COLLECTING_UPDATER_OUTPUT',
49
- 54: 'PAIR_STOCKHOLM',
50
- 55: 'UPDATE_STOCKHOLM',
51
- 56: 'UPDATE_SWDHID',
52
- 57: 'CERTIFY_SEP',
53
- 58: 'UPDATE_NAND_FIRMWARE',
54
- 59: 'UPDATE_SE_FIRMWARE',
55
- 60: 'UPDATE_SAVAGE',
56
- 61: 'INSTALLING_DEVICETREE',
57
- 62: 'CERTIFY_SAVAGE',
58
- 63: 'SUBMITTING_PROVINFO',
59
- 64: 'CERTIFY_YONKERS',
60
- 65: 'UPDATE_ROSE',
61
- 66: 'UPDATE_VERIDIAN',
62
- 67: 'CREATING_PROTECTED_VOLUME',
63
- 68: 'RESIZING_MAIN_FS_PARTITION',
64
- 69: 'CREATING_RECOVERY_OS_VOLUME',
65
- 70: 'INSTALLING_RECOVERY_OS_FILES',
66
- 71: 'INSTALLING_RECOVERY_OS_IMAGE',
67
- 74: 'REQUESTING_EAN_DATA',
68
- 77: 'SEALING_SYSTEM_VOLUME',
69
- 81: 'UPDATING_APPLETCON',
28
+ 11: "CREATE_PARTITION_MAP",
29
+ 12: "CREATE_FILESYSTEM",
30
+ 13: "RESTORE_IMAGE",
31
+ 14: "VERIFY_RESTORE",
32
+ 15: "CHECK_FILESYSTEMS",
33
+ 16: "MOUNT_FILESYSTEMS",
34
+ 17: "FIXUP_VAR",
35
+ 18: "FLASH_FIRMWARE",
36
+ 19: "UPDATE_BASEBAND",
37
+ 20: "SET_BOOT_STAGE",
38
+ 21: "REBOOT_DEVICE",
39
+ 22: "SHUTDOWN_DEVICE",
40
+ 23: "TURN_ON_ACCESSORY_POWER",
41
+ 24: "CLEAR_BOOTARGS",
42
+ 25: "MODIFY_BOOTARGS",
43
+ 26: "INSTALL_ROOT",
44
+ 27: "INSTALL_KERNELCACHE",
45
+ 28: "WAIT_FOR_NAND",
46
+ 29: "UNMOUNT_FILESYSTEMS",
47
+ 30: "SET_DATETIME",
48
+ 31: "EXEC_IBOOT",
49
+ 32: "FINALIZE_NAND_EPOCH_UPDATE",
50
+ 33: "CHECK_INAPPR_BOOT_PARTITIONS",
51
+ 34: "CREATE_FACTORY_RESTORE_MARKER",
52
+ 35: "LOAD_FIRMWARE",
53
+ 36: "REQUESTING_FUD_DATA",
54
+ 37: "REMOVING_ACTIVATION_RECORD",
55
+ 38: "CHECK_BATTERY_VOLTAGE",
56
+ 39: "WAIT_BATTERY_CHARGE",
57
+ 40: "CLOSE_MODEM_TICKETS",
58
+ 41: "MIGRATE_DATA",
59
+ 42: "WIPE_STORAGE_DEVICE",
60
+ 43: "SEND_APPLE_LOGO",
61
+ 44: "CHECK_LOGS",
62
+ 46: "CLEAR_NVRAM",
63
+ 47: "UPDATE_GAS_GAUGE",
64
+ 48: "PREPARE_BASEBAND_UPDATE",
65
+ 49: "BOOT_BASEBAND",
66
+ 50: "CREATE_SYSTEM_KEYBAG",
67
+ 51: "UPDATE_IR_MCU_FIRMWARE",
68
+ 52: "RESIZE_SYSTEM_PARTITION",
69
+ 53: "COLLECTING_UPDATER_OUTPUT",
70
+ 54: "PAIR_STOCKHOLM",
71
+ 55: "UPDATE_STOCKHOLM",
72
+ 56: "UPDATE_SWDHID",
73
+ 57: "CERTIFY_SEP",
74
+ 58: "UPDATE_NAND_FIRMWARE",
75
+ 59: "UPDATE_SE_FIRMWARE",
76
+ 60: "UPDATE_SAVAGE",
77
+ 61: "INSTALLING_DEVICETREE",
78
+ 62: "CERTIFY_SAVAGE",
79
+ 63: "SUBMITTING_PROVINFO",
80
+ 64: "CERTIFY_YONKERS",
81
+ 65: "UPDATE_ROSE",
82
+ 66: "UPDATE_VERIDIAN",
83
+ 67: "CREATING_PROTECTED_VOLUME",
84
+ 68: "RESIZING_MAIN_FS_PARTITION",
85
+ 69: "CREATING_RECOVERY_OS_VOLUME",
86
+ 70: "INSTALLING_RECOVERY_OS_FILES",
87
+ 71: "INSTALLING_RECOVERY_OS_IMAGE",
88
+ 74: "REQUESTING_EAN_DATA",
89
+ 77: "SEALING_SYSTEM_VOLUME",
90
+ 81: "UPDATING_APPLETCON",
70
91
  }
@@ -1,5 +1,6 @@
1
1
  from contextlib import suppress
2
2
  from functools import cached_property
3
+ from typing import Optional, overload
3
4
 
4
5
  from pymobiledevice3.exceptions import MissingValueError
5
6
  from pymobiledevice3.irecv import IRecv
@@ -7,18 +8,42 @@ from pymobiledevice3.lockdown import LockdownClient
7
8
 
8
9
 
9
10
  class Device:
10
- def __init__(self, lockdown: LockdownClient = None, irecv: IRecv = None):
11
- self.lockdown = lockdown
12
- self.irecv = irecv
11
+ @overload
12
+ def __init__(self, lockdown: LockdownClient, irecv: None = None) -> None: ...
13
+
14
+ @overload
15
+ def __init__(self, lockdown: None = None, *, irecv: IRecv) -> None: ...
16
+
17
+ def __init__(self, lockdown: Optional[LockdownClient] = None, irecv: Optional[IRecv] = None) -> None:
18
+ self._lockdown: Optional[LockdownClient] = lockdown
19
+ self._irecv: Optional[IRecv] = irecv
13
20
 
14
21
  def __repr__(self) -> str:
15
22
  return (
16
- f'<{self.__class__.__name__} '
17
- f'ecid: {self.ecid} '
18
- f'hardware_model: {self.hardware_model} '
19
- f'image4-support: {self.is_image4_supported}>'
23
+ f"<{self.__class__.__name__} "
24
+ f"ecid: {self.ecid} "
25
+ f"hardware_model: {self.hardware_model} "
26
+ f"image4-support: {self.is_image4_supported}>"
20
27
  )
21
28
 
29
+ @cached_property
30
+ def is_lockdown(self) -> bool:
31
+ return self._lockdown is not None
32
+
33
+ @cached_property
34
+ def is_irecv(self) -> bool:
35
+ return self._irecv is not None
36
+
37
+ @cached_property
38
+ def lockdown(self) -> LockdownClient:
39
+ assert self._lockdown is not None
40
+ return self._lockdown
41
+
42
+ @cached_property
43
+ def irecv(self) -> IRecv:
44
+ assert self._irecv is not None
45
+ return self._irecv
46
+
22
47
  @cached_property
23
48
  def ecid(self):
24
49
  if self.lockdown:
@@ -28,34 +53,56 @@ class Device:
28
53
  @cached_property
29
54
  def hardware_model(self):
30
55
  if self.lockdown:
31
- return self.lockdown.all_values['HardwareModel'].lower()
56
+ return self.lockdown.all_values["HardwareModel"].lower()
32
57
  return self.irecv.hardware_model
33
58
 
34
59
  @cached_property
35
60
  def is_image4_supported(self):
36
61
  if self.lockdown:
37
- return self.lockdown.get_value(key='Image4Supported')
62
+ return self.lockdown.get_value(key="Image4Supported")
38
63
  return self.irecv.is_image4_supported
39
64
 
65
+ @cached_property
66
+ def ap_parameters(self) -> dict:
67
+ if self.lockdown:
68
+ try:
69
+ return self.lockdown.get_value(key="ApParameters")
70
+ except MissingValueError:
71
+ pass
72
+ return {}
73
+
40
74
  @cached_property
41
75
  def ap_nonce(self):
42
76
  if self.lockdown:
43
- return self.lockdown.get_value(key='ApNonce')
77
+ ap_nonce_from_ap_parameters = self.ap_parameters.get("ApNonce")
78
+ if ap_nonce_from_ap_parameters:
79
+ return ap_nonce_from_ap_parameters
80
+ return self.lockdown.get_value(key="ApNonce")
44
81
  return self.irecv.ap_nonce
45
82
 
46
83
  @cached_property
47
84
  def sep_nonce(self):
48
85
  if self.lockdown:
49
- return self.lockdown.get_value(key='SEPNonce')
86
+ sep_nonce_from_ap_parameters = self.ap_parameters.get("SepNonce")
87
+ if sep_nonce_from_ap_parameters:
88
+ return sep_nonce_from_ap_parameters
89
+ return self.lockdown.get_value(key="SEPNonce")
50
90
  return self.irecv.sep_nonce
51
91
 
52
92
  @cached_property
53
- def preflight_info(self):
93
+ def preflight_info(self) -> Optional[dict]:
54
94
  if self.lockdown:
55
95
  with suppress(MissingValueError):
56
96
  return self.lockdown.preflight_info
57
97
  return None
58
98
 
99
+ @cached_property
100
+ def firmware_preflight_info(self) -> Optional[dict]:
101
+ if self.lockdown:
102
+ with suppress(MissingValueError):
103
+ return self.lockdown.firmware_preflight_info
104
+ return None
105
+
59
106
  @cached_property
60
107
  def product_type(self) -> str:
61
108
  if self.lockdown: