Skip to content

Commit 7a84cd9

Browse files
tihmstarnikias
authored andcommitted
Add iOS 2 support
1 parent 52a81e1 commit 7a84cd9

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

include/libirecovery.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ struct irecv_device_info {
106106
unsigned char* sep_nonce;
107107
unsigned int sep_nonce_size;
108108
uint16_t pid;
109+
unsigned int have_cpid : 1;
110+
unsigned int have_cprv : 1;
111+
unsigned int have_cpfm : 1;
112+
unsigned int have_scep : 1;
113+
unsigned int have_bdid : 1;
114+
unsigned int have_ecid : 1;
115+
unsigned int have_ibfl : 1;
109116
};
110117

111118
typedef enum {

src/libirecovery.c

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons
795795
ptr = strstr(iboot_string, "CPID:");
796796
if (ptr != NULL) {
797797
sscanf(ptr, "CPID:%x", &client->device_info.cpid);
798+
client->device_info.have_cpid = 1;
798799
} else {
799800
// early iOS 1 doesn't identify itself
800801
client->device_info.cpid = 0x8900;
@@ -803,33 +804,39 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons
803804
ptr = strstr(iboot_string, "CPRV:");
804805
if (ptr != NULL) {
805806
sscanf(ptr, "CPRV:%x", &client->device_info.cprv);
807+
client->device_info.have_cprv = 1;
806808
}
807809

808810
ptr = strstr(iboot_string, "CPFM:");
809811
if (ptr != NULL) {
810812
sscanf(ptr, "CPFM:%x", &client->device_info.cpfm);
813+
client->device_info.have_cpfm = 1;
811814
}
812815

813816
ptr = strstr(iboot_string, "SCEP:");
814817
if (ptr != NULL) {
815818
sscanf(ptr, "SCEP:%x", &client->device_info.scep);
819+
client->device_info.have_scep = 1;
816820
}
817821

818822
ptr = strstr(iboot_string, "BDID:");
819823
if (ptr != NULL) {
820824
uint64_t bdid = 0;
821825
sscanf(ptr, "BDID:%" SCNx64, &bdid);
822826
client->device_info.bdid = (unsigned int)bdid;
827+
client->device_info.have_bdid = 1;
823828
}
824829

825830
ptr = strstr(iboot_string, "ECID:");
826831
if (ptr != NULL) {
827832
sscanf(ptr, "ECID:%" SCNx64, &client->device_info.ecid);
833+
client->device_info.have_ecid = 1;
828834
}
829835

830836
ptr = strstr(iboot_string, "IBFL:");
831837
if (ptr != NULL) {
832838
sscanf(ptr, "IBFL:%x", &client->device_info.ibfl);
839+
client->device_info.have_ibfl = 1;
833840
}
834841

835842
char tmp[256];
@@ -3143,7 +3150,7 @@ irecv_error_t irecv_device_event_unsubscribe(irecv_device_event_context_t contex
31433150
#endif
31443151
}
31453152

3146-
irecv_error_t irecv_close(irecv_client_t client)
3153+
static irecv_error_t irecv_cleanup(irecv_client_t client)
31473154
{
31483155
#ifdef USE_DUMMY
31493156
return IRECV_E_UNSUPPORTED;
@@ -3187,15 +3194,23 @@ irecv_error_t irecv_close(irecv_client_t client)
31873194
free(client->device_info.serial_string);
31883195
free(client->device_info.ap_nonce);
31893196
free(client->device_info.sep_nonce);
3190-
3191-
free(client);
3192-
client = NULL;
31933197
}
31943198

31953199
return IRECV_E_SUCCESS;
31963200
#endif
31973201
}
31983202

3203+
irecv_error_t irecv_close(irecv_client_t client)
3204+
{
3205+
irecv_error_t ret = IRECV_E_SUCCESS;
3206+
if (client) {
3207+
ret = irecv_cleanup(client);
3208+
free(client);
3209+
client = NULL;
3210+
}
3211+
return ret;
3212+
}
3213+
31993214
void irecv_set_debug_level(int level)
32003215
{
32013216
libirecovery_debug = level;
@@ -3472,6 +3487,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
34723487
irecv_error_t error = 0;
34733488
int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE));
34743489
int legacy_recovery_mode = 0;
3490+
int isiOS2 = 0;
34753491

34763492
if (recovery_mode && client->device_info.cpid == 0x8900 && !client->device_info.ecid) {
34773493
#ifdef DEBUG
@@ -3484,6 +3500,17 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
34843500
legacy_recovery_mode = 1;
34853501
}
34863502

3503+
if (recovery_mode && !legacy_recovery_mode) {
3504+
// we are in recovery mode and we are not dealing with iOS 1.x
3505+
if ((client->device_info.cpid == 0x8900 || client->device_info.cpid == 0x8720) && !client->device_info.have_ibfl) {
3506+
// iOS 2.x doesn't have IBFL tag, but iOS 3 does
3507+
// Also, to avoid false activation of this codepath, restrict it to the only two CPID which can run iOS 2
3508+
recovery_mode = 0; // iOS 2 recovery mode works same as DFU mode
3509+
isiOS2 = 1;
3510+
options |= IRECV_SEND_OPT_DFU_NOTIFY_FINISH;
3511+
}
3512+
}
3513+
34873514
if (check_context(client) != IRECV_E_SUCCESS)
34883515
return IRECV_E_NO_DEVICE;
34893516

@@ -3536,6 +3563,14 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
35363563
case 2:
35373564
/* DFU IDLE */
35383565
break;
3566+
case 8:
3567+
/* DFU WAIT RESET */
3568+
if (!isiOS2) {
3569+
debug("Unexpected state %d in non-iOS2 mode!, issuing ABORT\n", state);
3570+
irecv_usb_control_transfer(client, 0x21, 6, 0, 0, NULL, 0, USB_TIMEOUT);
3571+
error = IRECV_E_USB_UPLOAD;
3572+
}
3573+
break;
35393574
case 10:
35403575
debug("DFU ERROR, issuing CLRSTATUS\n");
35413576
irecv_usb_control_transfer(client, 0x21, 4, 0, 0, NULL, 0, USB_TIMEOUT);
@@ -3673,6 +3708,10 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
36733708
}
36743709

36753710
irecv_reset(client);
3711+
3712+
if (isiOS2) {
3713+
irecv_reconnect(client, 0);
3714+
}
36763715
}
36773716

36783717
if (legacy_recovery_mode) {
@@ -4228,7 +4267,7 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause)
42284267
uint64_t ecid = client->device_info.ecid;
42294268

42304269
if (check_context(client) == IRECV_E_SUCCESS) {
4231-
irecv_close(client);
4270+
irecv_cleanup(client);
42324271
}
42334272

42344273
if (initial_pause > 0) {
@@ -4248,6 +4287,11 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause)
42484287
new_client->postcommand_callback = postcommand_callback;
42494288
new_client->disconnected_callback = disconnected_callback;
42504289

4290+
// keep old handle valid
4291+
memcpy(client, new_client, sizeof(*client));
4292+
free(new_client);
4293+
new_client = client;
4294+
42514295
if (new_client->connected_callback != NULL) {
42524296
irecv_event_t event;
42534297
event.size = 0;

0 commit comments

Comments
 (0)