pymobiledevice3 5.0.1__py3-none-any.whl → 5.0.3__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.

Potentially problematic release.


This version of pymobiledevice3 might be problematic. Click here for more details.

Files changed (143) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. pymobiledevice3/__main__.py +128 -102
  4. pymobiledevice3/_version.py +2 -2
  5. pymobiledevice3/bonjour.py +36 -59
  6. pymobiledevice3/ca.py +32 -24
  7. pymobiledevice3/cli/activation.py +7 -7
  8. pymobiledevice3/cli/afc.py +19 -19
  9. pymobiledevice3/cli/amfi.py +4 -4
  10. pymobiledevice3/cli/apps.py +51 -39
  11. pymobiledevice3/cli/backup.py +58 -32
  12. pymobiledevice3/cli/bonjour.py +25 -18
  13. pymobiledevice3/cli/cli_common.py +112 -81
  14. pymobiledevice3/cli/companion_proxy.py +4 -4
  15. pymobiledevice3/cli/completions.py +10 -10
  16. pymobiledevice3/cli/crash.py +37 -31
  17. pymobiledevice3/cli/developer.py +602 -520
  18. pymobiledevice3/cli/diagnostics.py +38 -33
  19. pymobiledevice3/cli/lockdown.py +79 -74
  20. pymobiledevice3/cli/mounter.py +85 -68
  21. pymobiledevice3/cli/notification.py +10 -10
  22. pymobiledevice3/cli/pcap.py +19 -14
  23. pymobiledevice3/cli/power_assertion.py +12 -10
  24. pymobiledevice3/cli/processes.py +10 -10
  25. pymobiledevice3/cli/profile.py +88 -77
  26. pymobiledevice3/cli/provision.py +17 -17
  27. pymobiledevice3/cli/remote.py +186 -110
  28. pymobiledevice3/cli/restore.py +43 -40
  29. pymobiledevice3/cli/springboard.py +30 -28
  30. pymobiledevice3/cli/syslog.py +85 -58
  31. pymobiledevice3/cli/usbmux.py +21 -20
  32. pymobiledevice3/cli/version.py +3 -2
  33. pymobiledevice3/cli/webinspector.py +157 -79
  34. pymobiledevice3/common.py +1 -1
  35. pymobiledevice3/exceptions.py +154 -60
  36. pymobiledevice3/irecv.py +49 -53
  37. pymobiledevice3/irecv_devices.py +1489 -492
  38. pymobiledevice3/lockdown.py +396 -242
  39. pymobiledevice3/lockdown_service_provider.py +5 -7
  40. pymobiledevice3/osu/os_utils.py +18 -9
  41. pymobiledevice3/osu/posix_util.py +28 -15
  42. pymobiledevice3/osu/win_util.py +14 -8
  43. pymobiledevice3/pair_records.py +19 -19
  44. pymobiledevice3/remote/common.py +4 -4
  45. pymobiledevice3/remote/core_device/app_service.py +94 -67
  46. pymobiledevice3/remote/core_device/core_device_service.py +17 -14
  47. pymobiledevice3/remote/core_device/device_info.py +5 -5
  48. pymobiledevice3/remote/core_device/diagnostics_service.py +10 -8
  49. pymobiledevice3/remote/core_device/file_service.py +47 -33
  50. pymobiledevice3/remote/remote_service_discovery.py +53 -35
  51. pymobiledevice3/remote/remotexpc.py +64 -42
  52. pymobiledevice3/remote/tunnel_service.py +371 -293
  53. pymobiledevice3/remote/utils.py +12 -11
  54. pymobiledevice3/remote/xpc_message.py +145 -125
  55. pymobiledevice3/resources/dsc_uuid_map.py +19 -19
  56. pymobiledevice3/resources/firmware_notifications.py +16 -16
  57. pymobiledevice3/restore/asr.py +27 -27
  58. pymobiledevice3/restore/base_restore.py +90 -47
  59. pymobiledevice3/restore/consts.py +87 -66
  60. pymobiledevice3/restore/device.py +11 -11
  61. pymobiledevice3/restore/fdr.py +46 -46
  62. pymobiledevice3/restore/ftab.py +19 -19
  63. pymobiledevice3/restore/img4.py +130 -133
  64. pymobiledevice3/restore/mbn.py +35 -54
  65. pymobiledevice3/restore/recovery.py +125 -135
  66. pymobiledevice3/restore/restore.py +524 -523
  67. pymobiledevice3/restore/restore_options.py +122 -115
  68. pymobiledevice3/restore/restored_client.py +25 -22
  69. pymobiledevice3/restore/tss.py +378 -270
  70. pymobiledevice3/service_connection.py +50 -46
  71. pymobiledevice3/services/accessibilityaudit.py +137 -127
  72. pymobiledevice3/services/afc.py +350 -291
  73. pymobiledevice3/services/amfi.py +21 -18
  74. pymobiledevice3/services/companion.py +23 -19
  75. pymobiledevice3/services/crash_reports.py +60 -46
  76. pymobiledevice3/services/debugserver_applist.py +3 -3
  77. pymobiledevice3/services/device_arbitration.py +8 -8
  78. pymobiledevice3/services/device_link.py +56 -48
  79. pymobiledevice3/services/diagnostics.py +971 -968
  80. pymobiledevice3/services/dtfetchsymbols.py +8 -8
  81. pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
  82. pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
  83. pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
  84. pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
  85. pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
  86. pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +442 -421
  87. pymobiledevice3/services/dvt/instruments/device_info.py +11 -11
  88. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  89. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  90. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  91. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  92. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  93. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  94. pymobiledevice3/services/dvt/instruments/process_control.py +25 -10
  95. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  96. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  97. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
  98. pymobiledevice3/services/file_relay.py +10 -10
  99. pymobiledevice3/services/heartbeat.py +8 -7
  100. pymobiledevice3/services/house_arrest.py +12 -15
  101. pymobiledevice3/services/installation_proxy.py +119 -100
  102. pymobiledevice3/services/lockdown_service.py +12 -5
  103. pymobiledevice3/services/misagent.py +22 -19
  104. pymobiledevice3/services/mobile_activation.py +84 -72
  105. pymobiledevice3/services/mobile_config.py +330 -301
  106. pymobiledevice3/services/mobile_image_mounter.py +137 -116
  107. pymobiledevice3/services/mobilebackup2.py +188 -150
  108. pymobiledevice3/services/notification_proxy.py +11 -11
  109. pymobiledevice3/services/os_trace.py +69 -51
  110. pymobiledevice3/services/pcapd.py +306 -306
  111. pymobiledevice3/services/power_assertion.py +10 -9
  112. pymobiledevice3/services/preboard.py +4 -4
  113. pymobiledevice3/services/remote_fetch_symbols.py +16 -14
  114. pymobiledevice3/services/remote_server.py +176 -146
  115. pymobiledevice3/services/restore_service.py +16 -16
  116. pymobiledevice3/services/screenshot.py +13 -10
  117. pymobiledevice3/services/simulate_location.py +7 -7
  118. pymobiledevice3/services/springboard.py +15 -15
  119. pymobiledevice3/services/syslog.py +5 -5
  120. pymobiledevice3/services/web_protocol/alert.py +3 -3
  121. pymobiledevice3/services/web_protocol/automation_session.py +183 -179
  122. pymobiledevice3/services/web_protocol/cdp_screencast.py +44 -36
  123. pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
  124. pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
  125. pymobiledevice3/services/web_protocol/driver.py +47 -45
  126. pymobiledevice3/services/web_protocol/element.py +74 -63
  127. pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
  128. pymobiledevice3/services/web_protocol/selenium_api.py +3 -3
  129. pymobiledevice3/services/web_protocol/session_protocol.py +15 -10
  130. pymobiledevice3/services/web_protocol/switch_to.py +11 -12
  131. pymobiledevice3/services/webinspector.py +129 -117
  132. pymobiledevice3/tcp_forwarder.py +35 -22
  133. pymobiledevice3/tunneld/api.py +20 -15
  134. pymobiledevice3/tunneld/server.py +212 -133
  135. pymobiledevice3/usbmux.py +183 -138
  136. pymobiledevice3/utils.py +14 -11
  137. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.3.dist-info}/METADATA +1 -1
  138. pymobiledevice3-5.0.3.dist-info/RECORD +173 -0
  139. pymobiledevice3-5.0.1.dist-info/RECORD +0 -173
  140. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.3.dist-info}/WHEEL +0 -0
  141. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.3.dist-info}/entry_points.txt +0 -0
  142. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.3.dist-info}/licenses/LICENSE +0 -0
  143. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.3.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import contextlib
1
2
  import hashlib
2
3
  import logging
3
4
  import time
@@ -14,9 +15,9 @@ from pymobiledevice3.restore.consts import lpol_file
14
15
  from pymobiledevice3.restore.device import Device
15
16
  from pymobiledevice3.restore.tss import TSSRequest, TSSResponse
16
17
 
17
- RESTORE_VARIANT_ERASE_INSTALL = 'Erase Install (IPSW)'
18
- RESTORE_VARIANT_UPGRADE_INSTALL = 'Upgrade Install (IPSW)'
19
- RESTORE_VARIANT_MACOS_RECOVERY_OS = 'macOS Customer'
18
+ RESTORE_VARIANT_ERASE_INSTALL = "Erase Install (IPSW)"
19
+ RESTORE_VARIANT_UPGRADE_INSTALL = "Upgrade Install (IPSW)"
20
+ RESTORE_VARIANT_MACOS_RECOVERY_OS = "macOS Customer"
20
21
 
21
22
 
22
23
  class Recovery(BaseRestore):
@@ -27,21 +28,21 @@ class Recovery(BaseRestore):
27
28
  self.restore_boot_args = None
28
29
 
29
30
  def reconnect_irecv(self, is_recovery=None):
30
- self.logger.debug('waiting for device to reconnect...')
31
+ self.logger.debug("waiting for device to reconnect...")
31
32
  self.device.irecv = IRecv(ecid=self.device.ecid, is_recovery=is_recovery)
32
- self.logger.debug(f'connected mode: {self.device.irecv.mode}')
33
+ self.logger.debug(f"connected mode: {self.device.irecv.mode}")
33
34
 
34
35
  def get_preboard_manifest(self):
35
36
  overrides = {
36
- '@APTicket': True,
37
- 'ApProductionMode': 0,
38
- 'ApSecurityDomain': 0,
37
+ "@APTicket": True,
38
+ "ApProductionMode": 0,
39
+ "ApSecurityDomain": 0,
39
40
  }
40
41
 
41
42
  parameters = {
42
- 'ApProductionMode': False,
43
- 'ApSecurityMode': False,
44
- 'ApSupportsImg4': True,
43
+ "ApProductionMode": False,
44
+ "ApSecurityMode": False,
45
+ "ApSupportsImg4": True,
45
46
  }
46
47
 
47
48
  self.populate_tss_request_from_manifest(parameters)
@@ -49,7 +50,7 @@ class Recovery(BaseRestore):
49
50
  tss = TSSRequest()
50
51
  tss.add_common_tags(parameters, overrides)
51
52
 
52
- parameters['_OnlyFWComponents'] = True
53
+ parameters["_OnlyFWComponents"] = True
53
54
 
54
55
  tss.add_ap_tags(parameters)
55
56
 
@@ -57,22 +58,22 @@ class Recovery(BaseRestore):
57
58
 
58
59
  async def get_tss_response(self) -> TSSResponse:
59
60
  # populate parameters
60
- parameters = dict()
61
+ parameters = {}
61
62
 
62
- parameters['ApECID'] = self.device.ecid
63
+ parameters["ApECID"] = self.device.ecid
63
64
  if self.device.ap_nonce is not None:
64
- parameters['ApNonce'] = self.device.ap_nonce
65
+ parameters["ApNonce"] = self.device.ap_nonce
65
66
 
66
67
  if self.device.sep_nonce is not None:
67
- parameters['ApSepNonce'] = self.device.sep_nonce
68
+ parameters["ApSepNonce"] = self.device.sep_nonce
68
69
 
69
- parameters['ApProductionMode'] = True
70
+ parameters["ApProductionMode"] = True
70
71
 
71
72
  if self.device.is_image4_supported:
72
- parameters['ApSecurityMode'] = True
73
- parameters['ApSupportsImg4'] = True
73
+ parameters["ApSecurityMode"] = True
74
+ parameters["ApSupportsImg4"] = True
74
75
  else:
75
- parameters['ApSupportsImg4'] = False
76
+ parameters["ApSupportsImg4"] = False
76
77
 
77
78
  self.populate_tss_request_from_manifest(parameters)
78
79
 
@@ -95,48 +96,48 @@ class Recovery(BaseRestore):
95
96
  if self.device.lockdown is not None:
96
97
  pinfo = self.device.firmware_preflight_info
97
98
  if pinfo:
98
- self.logger.debug('adding firmware preflight info')
99
+ self.logger.debug("adding firmware preflight info")
99
100
 
100
- node = pinfo.get('Nonce')
101
+ node = pinfo.get("Nonce")
101
102
  if node is not None:
102
- parameters['BbNonce'] = node
103
+ parameters["BbNonce"] = node
103
104
 
104
- node = pinfo.get('ChipID')
105
+ node = pinfo.get("ChipID")
105
106
  if node is not None:
106
- parameters['BbChipID'] = node
107
+ parameters["BbChipID"] = node
107
108
 
108
- node = pinfo.get('CertID')
109
+ node = pinfo.get("CertID")
109
110
  if node is not None:
110
- parameters['BbGoldCertId'] = node
111
+ parameters["BbGoldCertId"] = node
111
112
 
112
- node = pinfo.get('ChipSerialNo')
113
+ node = pinfo.get("ChipSerialNo")
113
114
  if node is not None:
114
- parameters['BbSNUM'] = node
115
+ parameters["BbSNUM"] = node
115
116
 
116
117
  # add baseband parameters
117
118
  tss.add_baseband_tags(parameters)
118
119
 
119
- euiccchipid = pinfo.get('EUICCChipID')
120
+ euiccchipid = pinfo.get("EUICCChipID")
120
121
  if euiccchipid:
121
- self.logger.debug('adding EUICCChipID info')
122
- parameters['eUICC,ChipID'] = euiccchipid
122
+ self.logger.debug("adding EUICCChipID info")
123
+ parameters["eUICC,ChipID"] = euiccchipid
123
124
 
124
125
  if euiccchipid >= 5:
125
- node = pinfo.get('EUICCCSN')
126
+ node = pinfo.get("EUICCCSN")
126
127
  if node is not None:
127
- parameters['eUICC,EID'] = node
128
+ parameters["eUICC,EID"] = node
128
129
 
129
- node = pinfo.get('EUICCCertIdentifier')
130
+ node = pinfo.get("EUICCCertIdentifier")
130
131
  if node is not None:
131
- parameters['eUICC,RootKeyIdentifier'] = node
132
+ parameters["eUICC,RootKeyIdentifier"] = node
132
133
 
133
- node = pinfo.get('EUICCGoldNonce')
134
+ node = pinfo.get("EUICCGoldNonce")
134
135
  if node is not None:
135
- parameters['EUICCGoldNonce'] = node
136
+ parameters["EUICCGoldNonce"] = node
136
137
 
137
- node = pinfo.get('EUICCMainNonce')
138
+ node = pinfo.get("EUICCMainNonce")
138
139
  if node is not None:
139
- parameters['EUICCMainNonce'] = node
140
+ parameters["EUICCMainNonce"] = node
140
141
 
141
142
  tss.add_vinyl_tags(parameters)
142
143
 
@@ -146,40 +147,40 @@ class Recovery(BaseRestore):
146
147
  def get_local_policy_tss_response(self):
147
148
  # populate parameters
148
149
  parameters = {
149
- 'ApECID': self.device.ecid,
150
- 'Ap,LocalBoot': False,
151
- 'ApProductionMode': True,
150
+ "ApECID": self.device.ecid,
151
+ "Ap,LocalBoot": False,
152
+ "ApProductionMode": True,
152
153
  }
153
154
 
154
155
  if self.device.ap_nonce:
155
- parameters['ApNonce'] = self.device.ap_nonce
156
+ parameters["ApNonce"] = self.device.ap_nonce
156
157
 
157
158
  sep_nonce = self.device.sep_nonce
158
159
 
159
160
  if sep_nonce:
160
- parameters['ApSepNonce'] = sep_nonce
161
+ parameters["ApSepNonce"] = sep_nonce
161
162
 
162
163
  if self.device.is_image4_supported:
163
- parameters['ApSecurityMode'] = True
164
- parameters['ApSupportsImg4'] = True
164
+ parameters["ApSecurityMode"] = True
165
+ parameters["ApSupportsImg4"] = True
165
166
  else:
166
- parameters['ApSupportsImg4'] = False
167
+ parameters["ApSupportsImg4"] = False
167
168
 
168
169
  self.populate_tss_request_from_manifest(parameters)
169
170
 
170
171
  # Add Ap,LocalPolicy
171
172
  lpol = {
172
- 'Digest': hashlib.sha384(lpol_file).digest(),
173
- 'Trusted': True,
173
+ "Digest": hashlib.sha384(lpol_file).digest(),
174
+ "Trusted": True,
174
175
  }
175
176
 
176
- parameters['Ap,LocalPolicy'] = lpol
177
+ parameters["Ap,LocalPolicy"] = lpol
177
178
 
178
179
  # Add Ap,NextStageIM4MHash
179
180
  # Get previous TSS ticket
180
181
  ticket = self.tss.ap_img4_ticket
181
182
  # Hash it and add it as Ap,NextStageIM4MHash
182
- parameters['Ap,NextStageIM4MHash'] = hashlib.sha384(ticket).digest()
183
+ parameters["Ap,NextStageIM4MHash"] = hashlib.sha384(ticket).digest()
183
184
 
184
185
  # create basic request
185
186
  request = TSSRequest()
@@ -192,24 +193,24 @@ class Recovery(BaseRestore):
192
193
  def get_recoveryos_root_ticket_tss_response(self):
193
194
  # populate parameters
194
195
  parameters = {
195
- 'ApECID': self.device.ecid,
196
- 'Ap,LocalBoot': False,
197
- 'ApProductionMode': True,
196
+ "ApECID": self.device.ecid,
197
+ "Ap,LocalBoot": False,
198
+ "ApProductionMode": True,
198
199
  }
199
200
 
200
201
  if self.device.ap_nonce:
201
- parameters['ApNonce'] = self.device.ap_nonce
202
+ parameters["ApNonce"] = self.device.ap_nonce
202
203
 
203
204
  sep_nonce = self.device.sep_nonce
204
205
 
205
206
  if sep_nonce:
206
- parameters['ApSepNonce'] = sep_nonce
207
+ parameters["ApSepNonce"] = sep_nonce
207
208
 
208
209
  if self.device.is_image4_supported:
209
- parameters['ApSecurityMode'] = True
210
- parameters['ApSupportsImg4'] = True
210
+ parameters["ApSecurityMode"] = True
211
+ parameters["ApSupportsImg4"] = True
211
212
  else:
212
- parameters['ApSupportsImg4'] = False
213
+ parameters["ApSupportsImg4"] = False
213
214
 
214
215
  self.populate_tss_request_from_manifest(parameters)
215
216
 
@@ -231,10 +232,9 @@ class Recovery(BaseRestore):
231
232
  return request.send_receive()
232
233
 
233
234
  async def fetch_tss_record(self) -> TSSResponse:
234
- if self.ipsw.build_manifest.build_major > 8:
235
- if self.device.ap_nonce is None:
236
- # the first nonce request with older firmware releases can fail, and it's OK
237
- self.logger.info('NOTE: Unable to get nonce from device')
235
+ if self.ipsw.build_manifest.build_major > 8 and self.device.ap_nonce is None:
236
+ # the first nonce request with older firmware releases can fail, and it's OK
237
+ self.logger.info("NOTE: Unable to get nonce from device")
238
238
 
239
239
  self.tss = await self.get_tss_response()
240
240
 
@@ -242,7 +242,7 @@ class Recovery(BaseRestore):
242
242
  self.tss_localpolicy = self.get_local_policy_tss_response()
243
243
  self.tss_recoveryos_root_ticket = self.get_recoveryos_root_ticket_tss_response()
244
244
  else:
245
- recovery_variant = self.build_identity['Info'].get('RecoveryVariant')
245
+ recovery_variant = self.build_identity["Info"].get("RecoveryVariant")
246
246
  if recovery_variant is not None:
247
247
  self.tss_recoveryos_root_ticket = await self.get_tss_response()
248
248
 
@@ -252,13 +252,13 @@ class Recovery(BaseRestore):
252
252
  # Use a specific TSS ticket for the Ap,LocalPolicy component
253
253
  data = None
254
254
  tss = self.tss
255
- if name == 'Ap,LocalPolicy':
255
+ if name == "Ap,LocalPolicy":
256
256
  tss = self.tss_localpolicy
257
257
  # If Ap,LocalPolicy => Inject an empty policy
258
258
  data = lpol_file
259
259
 
260
260
  data = self.get_personalized_data(name, data=data, tss=tss)
261
- self.logger.info(f'Sending {name} ({len(data)} bytes)...')
261
+ self.logger.info(f"Sending {name} ({len(data)} bytes)...")
262
262
  self.device.irecv.send_buffer(data)
263
263
 
264
264
  def send_component_and_command(self, name, command):
@@ -266,114 +266,110 @@ class Recovery(BaseRestore):
266
266
  self.device.irecv.send_command(command)
267
267
 
268
268
  def send_ibec(self):
269
- component = 'iBEC'
269
+ component = "iBEC"
270
270
  self.send_component(component)
271
- self.device.irecv.send_command('go', b_request=1)
271
+ self.device.irecv.send_command("go", b_request=1)
272
272
  self.device.irecv.ctrl_transfer(0x21, 1)
273
273
 
274
274
  def send_applelogo(self, allow_missing=True):
275
- component = 'RestoreLogo'
275
+ component = "RestoreLogo"
276
276
 
277
277
  if not self.build_identity.has_component(component):
278
278
  if allow_missing:
279
- logging.warning(f'build_identity has no {component}')
279
+ logging.warning(f"build_identity has no {component}")
280
280
  return
281
281
  else:
282
- raise PyMobileDevice3Exception(f'missing component: {component}')
282
+ raise PyMobileDevice3Exception(f"missing component: {component}")
283
283
 
284
284
  self.send_component(component)
285
- self.device.irecv.send_command('setpicture 4')
286
- self.device.irecv.send_command('bgcolor 0 0 0')
285
+ self.device.irecv.send_command("setpicture 4")
286
+ self.device.irecv.send_command("bgcolor 0 0 0")
287
287
 
288
288
  def send_loaded_by_iboot(self):
289
- manifest = self.build_identity['Manifest']
289
+ manifest = self.build_identity["Manifest"]
290
290
  for key, node in manifest.items():
291
- iboot = node['Info'].get('IsLoadedByiBoot', False)
292
- iboot_stg1 = node['Info'].get('IsLoadedByiBootStage1', False)
291
+ iboot = node["Info"].get("IsLoadedByiBoot", False)
292
+ iboot_stg1 = node["Info"].get("IsLoadedByiBootStage1", False)
293
293
 
294
294
  assert isinstance(iboot, bool)
295
295
  assert isinstance(iboot_stg1, bool)
296
296
 
297
297
  if iboot and not iboot_stg1:
298
- self.logger.debug(f'{key} is loaded by iBoot')
299
- self.send_component_and_command(key, 'firmware')
298
+ self.logger.debug(f"{key} is loaded by iBoot")
299
+ self.send_component_and_command(key, "firmware")
300
300
 
301
301
  def send_iboot_stage1_components(self):
302
- manifest = self.build_identity['Manifest']
302
+ manifest = self.build_identity["Manifest"]
303
303
  for key, node in manifest.items():
304
- iboot = node['Info'].get('IsLoadedByiBoot', False)
305
- iboot_stg1 = node['Info'].get('IsLoadedByiBootStage1', False)
304
+ iboot = node["Info"].get("IsLoadedByiBoot", False)
305
+ iboot_stg1 = node["Info"].get("IsLoadedByiBootStage1", False)
306
306
 
307
307
  assert isinstance(iboot, bool)
308
308
  assert isinstance(iboot_stg1, bool)
309
309
 
310
310
  if iboot and iboot_stg1:
311
- self.logger.debug(f'{key} is loaded by iBoot Stage 1')
312
- self.send_component_and_command(key, 'firmware')
311
+ self.logger.debug(f"{key} is loaded by iBoot Stage 1")
312
+ self.send_component_and_command(key, "firmware")
313
313
 
314
314
  def send_ramdisk(self):
315
- component = 'RestoreRamDisk'
316
- ramdisk_size = self.device.irecv.getenv('ramdisk-size')
317
- self.logger.info(f'ramdisk-size: {ramdisk_size}')
315
+ component = "RestoreRamDisk"
316
+ ramdisk_size = self.device.irecv.getenv("ramdisk-size")
317
+ self.logger.info(f"ramdisk-size: {ramdisk_size}")
318
318
 
319
319
  self.send_component(component)
320
- ramdisk_delay = self.device.irecv.getenv('ramdisk-delay')
321
- self.logger.info(f'ramdisk-delay: {ramdisk_delay}')
320
+ ramdisk_delay = self.device.irecv.getenv("ramdisk-delay")
321
+ self.logger.info(f"ramdisk-delay: {ramdisk_delay}")
322
322
 
323
- self.device.irecv.send_command('ramdisk')
323
+ self.device.irecv.send_command("ramdisk")
324
324
 
325
325
  time.sleep(2)
326
326
 
327
327
  def send_kernelcache(self):
328
- component = 'RestoreKernelCache'
328
+ component = "RestoreKernelCache"
329
329
 
330
330
  self.send_component(component)
331
- try:
331
+ with contextlib.suppress(USBError):
332
332
  self.device.irecv.ctrl_transfer(0x21, 1)
333
- except USBError:
334
- pass
335
333
 
336
334
  if self.restore_boot_args:
337
- self.device.irecv.send_command(f'setenv boot-args {self.restore_boot_args}')
335
+ self.device.irecv.send_command(f"setenv boot-args {self.restore_boot_args}")
338
336
 
339
- try:
340
- self.device.irecv.send_command('bootx', b_request=1)
341
- except USBError:
342
- pass
337
+ with contextlib.suppress(USBError):
338
+ self.device.irecv.send_command("bootx", b_request=1)
343
339
 
344
340
  def set_autoboot(self, enable: bool):
345
341
  self.device.irecv.set_autoboot(enable)
346
342
 
347
343
  def enter_restore(self):
348
344
  if self.macos_variant:
349
- self.restore_boot_args = 'rd=md0 nand-enable-reformat=1 -progress -restore'
345
+ self.restore_boot_args = "rd=md0 nand-enable-reformat=1 -progress -restore"
350
346
  elif self.ipsw.build_manifest.build_major >= 8:
351
- self.restore_boot_args = 'rd=md0 nand-enable-reformat=1 -progress'
347
+ self.restore_boot_args = "rd=md0 nand-enable-reformat=1 -progress"
352
348
 
353
349
  # upload data to make device boot restore mode
354
350
 
355
351
  # Recovery Mode Environment:
356
352
  build_version = None
357
353
  while not build_version:
358
- self.logger.debug('build-version not yet supported. reconnecting...')
354
+ self.logger.debug("build-version not yet supported. reconnecting...")
359
355
  time.sleep(1)
360
356
 
361
357
  # sometimes we manage to connect before iBEC actually started running
362
- build_version = self.device.irecv.getenv('build-version')
358
+ build_version = self.device.irecv.getenv("build-version")
363
359
  self.reconnect_irecv()
364
360
 
365
- self.logger.info(f'iBoot build-version={build_version}')
361
+ self.logger.info(f"iBoot build-version={build_version}")
366
362
 
367
- build_style = self.device.irecv.getenv('build-style')
368
- self.logger.info(f'iBoot build-style={build_style}')
363
+ build_style = self.device.irecv.getenv("build-style")
364
+ self.logger.info(f"iBoot build-style={build_style}")
369
365
 
370
- radio_error = self.device.irecv.getenv('radio-error')
366
+ radio_error = self.device.irecv.getenv("radio-error")
371
367
  if radio_error:
372
368
  radio_error = int(radio_error)
373
- self.logger.info(f'radio-error: {radio_error}')
374
- radio_error_string = self.device.irecv.getenv('radio-error-string')
369
+ self.logger.info(f"radio-error: {radio_error}")
370
+ radio_error_string = self.device.irecv.getenv("radio-error-string")
375
371
  if radio_error_string:
376
- self.logger.info(f'radio-error-string: {radio_error_string}')
372
+ self.logger.info(f"radio-error-string: {radio_error_string}")
377
373
 
378
374
  self.set_autoboot(False)
379
375
 
@@ -387,23 +383,21 @@ class Recovery(BaseRestore):
387
383
  self.send_ramdisk()
388
384
 
389
385
  # send devicetree and load it
390
- self.send_component_and_command('RestoreDeviceTree', 'devicetree')
386
+ self.send_component_and_command("RestoreDeviceTree", "devicetree")
391
387
 
392
- if self.build_identity.has_component('RestoreSEP'):
388
+ if self.build_identity.has_component("RestoreSEP"):
393
389
  # attempt to send rsepfirmware and load it, otherwise continue
394
- try:
395
- self.send_component_and_command('RestoreSEP', 'rsepfirmware')
396
- except USBError:
397
- pass
390
+ with contextlib.suppress(USBError):
391
+ self.send_component_and_command("RestoreSEP", "rsepfirmware")
398
392
 
399
393
  self.send_kernelcache()
400
394
 
401
395
  async def dfu_enter_recovery(self) -> None:
402
- self.send_component('iBSS')
396
+ self.send_component("iBSS")
403
397
  self.reconnect_irecv()
404
398
 
405
- if 'SRTG' in self.device.irecv._device_info:
406
- raise PyMobileDevice3Exception('Device failed to enter recovery')
399
+ if "SRTG" in self.device.irecv._device_info:
400
+ raise PyMobileDevice3Exception("Device failed to enter recovery")
407
401
 
408
402
  if self.build_identity.build_manifest.build_major > 8:
409
403
  old_nonce = self.device.irecv.ap_nonce
@@ -421,43 +415,41 @@ class Recovery(BaseRestore):
421
415
  # Now, before sending iBEC, we must send necessary firmwares on new versions.
422
416
  if self.macos_variant:
423
417
  # Without this empty policy file & its special signature, iBEC won't start.
424
- self.send_component_and_command('Ap,LocalPolicy', 'lpolrestore')
418
+ self.send_component_and_command("Ap,LocalPolicy", "lpolrestore")
425
419
  self.send_iboot_stage1_components()
426
420
  self.device.irecv.set_autoboot(False)
427
- self.device.irecv.send_command('setenvnp boot-args rd=md0 nand-enable-reformat=1 -progress -restore')
421
+ self.device.irecv.send_command("setenvnp boot-args rd=md0 nand-enable-reformat=1 -progress -restore")
428
422
  self.send_applelogo(allow_missing=False)
429
423
 
430
424
  mode = self.device.irecv.mode
431
425
  # send iBEC
432
- self.send_component('iBEC')
426
+ self.send_component("iBEC")
433
427
 
434
428
  if self.device.irecv and mode.is_recovery:
435
429
  time.sleep(1)
436
- self.device.irecv.send_command('go', b_request=1)
430
+ self.device.irecv.send_command("go", b_request=1)
437
431
 
438
432
  if self.build_identity.build_manifest.build_major < 20:
439
- try:
433
+ with contextlib.suppress(USBError):
440
434
  self.device.irecv.ctrl_transfer(0x21, 1, timeout=5000)
441
- except USBError:
442
- pass
443
435
 
444
- self.logger.debug('Waiting for device to disconnect...')
436
+ self.logger.debug("Waiting for device to disconnect...")
445
437
  time.sleep(10)
446
438
 
447
- self.logger.debug('Waiting for device to reconnect in recovery mode...')
439
+ self.logger.debug("Waiting for device to reconnect in recovery mode...")
448
440
  self.reconnect_irecv(is_recovery=True)
449
441
 
450
442
  async def boot_ramdisk(self) -> None:
451
443
  if self.tss is None:
452
- self.logger.info('fetching TSS record')
444
+ self.logger.info("fetching TSS record")
453
445
  await self.fetch_tss_record()
454
446
 
455
447
  if self.device.lockdown:
456
448
  # normal mode
457
- self.logger.info('going into Recovery')
449
+ self.logger.info("going into Recovery")
458
450
 
459
451
  # In case lockdown has disconnected while waiting for a ticket
460
- self.device.lockdown = create_using_usbmux(serial=self.device.lockdown.udid, connection_type='USB')
452
+ self.device.lockdown = create_using_usbmux(serial=self.device.lockdown.udid, connection_type="USB")
461
453
  self.device.lockdown.enter_recovery()
462
454
 
463
455
  self.device.lockdown = None
@@ -470,14 +462,12 @@ class Recovery(BaseRestore):
470
462
 
471
463
  elif self.device.irecv.mode.is_recovery:
472
464
  # now we load the iBEC
473
- try:
465
+ with contextlib.suppress(USBError):
474
466
  self.send_ibec()
475
- except USBError:
476
- pass
477
467
 
478
468
  self.reconnect_irecv(is_recovery=True)
479
469
 
480
- self.logger.info('device booted into recovery')
470
+ self.logger.info("device booted into recovery")
481
471
 
482
472
  # now finally do the magic to put the device into restore mode
483
473
  self.enter_restore()