diff options
author | 2023-12-14 01:14:00 +0100 | |
---|---|---|
committer | 2025-09-06 20:04:57 +0200 | |
commit | 7a84cd9f639a1962d5e73118263a1b2fbab52b14 (patch) | |
tree | 5a3c5662effefaf1dc0f4d09c1cdf06ab9f199d4 /src | |
parent | 52a81e111664cb267bd5b646ece9cb90c1a6fa94 (diff) | |
download | libirecovery-7a84cd9f639a1962d5e73118263a1b2fbab52b14.tar.gz libirecovery-7a84cd9f639a1962d5e73118263a1b2fbab52b14.tar.bz2 |
Add iOS 2 support
Diffstat (limited to 'src')
-rw-r--r-- | src/libirecovery.c | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c index dd07110..3146e40 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -795,6 +795,7 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons ptr = strstr(iboot_string, "CPID:"); if (ptr != NULL) { sscanf(ptr, "CPID:%x", &client->device_info.cpid); + client->device_info.have_cpid = 1; } else { // early iOS 1 doesn't identify itself client->device_info.cpid = 0x8900; @@ -803,16 +804,19 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons ptr = strstr(iboot_string, "CPRV:"); if (ptr != NULL) { sscanf(ptr, "CPRV:%x", &client->device_info.cprv); + client->device_info.have_cprv = 1; } ptr = strstr(iboot_string, "CPFM:"); if (ptr != NULL) { sscanf(ptr, "CPFM:%x", &client->device_info.cpfm); + client->device_info.have_cpfm = 1; } ptr = strstr(iboot_string, "SCEP:"); if (ptr != NULL) { sscanf(ptr, "SCEP:%x", &client->device_info.scep); + client->device_info.have_scep = 1; } ptr = strstr(iboot_string, "BDID:"); @@ -820,16 +824,19 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons uint64_t bdid = 0; sscanf(ptr, "BDID:%" SCNx64, &bdid); client->device_info.bdid = (unsigned int)bdid; + client->device_info.have_bdid = 1; } ptr = strstr(iboot_string, "ECID:"); if (ptr != NULL) { sscanf(ptr, "ECID:%" SCNx64, &client->device_info.ecid); + client->device_info.have_ecid = 1; } ptr = strstr(iboot_string, "IBFL:"); if (ptr != NULL) { sscanf(ptr, "IBFL:%x", &client->device_info.ibfl); + client->device_info.have_ibfl = 1; } char tmp[256]; @@ -3143,7 +3150,7 @@ irecv_error_t irecv_device_event_unsubscribe(irecv_device_event_context_t contex #endif } -irecv_error_t irecv_close(irecv_client_t client) +static irecv_error_t irecv_cleanup(irecv_client_t client) { #ifdef USE_DUMMY return IRECV_E_UNSUPPORTED; @@ -3187,15 +3194,23 @@ irecv_error_t irecv_close(irecv_client_t client) free(client->device_info.serial_string); free(client->device_info.ap_nonce); free(client->device_info.sep_nonce); - - free(client); - client = NULL; } return IRECV_E_SUCCESS; #endif } +irecv_error_t irecv_close(irecv_client_t client) +{ + irecv_error_t ret = IRECV_E_SUCCESS; + if (client) { + ret = irecv_cleanup(client); + free(client); + client = NULL; + } + return ret; +} + void irecv_set_debug_level(int level) { libirecovery_debug = level; @@ -3472,6 +3487,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un irecv_error_t error = 0; int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)); int legacy_recovery_mode = 0; + int isiOS2 = 0; if (recovery_mode && client->device_info.cpid == 0x8900 && !client->device_info.ecid) { #ifdef DEBUG @@ -3484,6 +3500,17 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un legacy_recovery_mode = 1; } + if (recovery_mode && !legacy_recovery_mode) { + // we are in recovery mode and we are not dealing with iOS 1.x + if ((client->device_info.cpid == 0x8900 || client->device_info.cpid == 0x8720) && !client->device_info.have_ibfl) { + // iOS 2.x doesn't have IBFL tag, but iOS 3 does + // Also, to avoid false activation of this codepath, restrict it to the only two CPID which can run iOS 2 + recovery_mode = 0; // iOS 2 recovery mode works same as DFU mode + isiOS2 = 1; + options |= IRECV_SEND_OPT_DFU_NOTIFY_FINISH; + } + } + if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -3536,6 +3563,14 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un case 2: /* DFU IDLE */ break; + case 8: + /* DFU WAIT RESET */ + if (!isiOS2) { + debug("Unexpected state %d in non-iOS2 mode!, issuing ABORT\n", state); + irecv_usb_control_transfer(client, 0x21, 6, 0, 0, NULL, 0, USB_TIMEOUT); + error = IRECV_E_USB_UPLOAD; + } + break; case 10: debug("DFU ERROR, issuing CLRSTATUS\n"); 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 } irecv_reset(client); + + if (isiOS2) { + irecv_reconnect(client, 0); + } } if (legacy_recovery_mode) { @@ -4228,7 +4267,7 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause) uint64_t ecid = client->device_info.ecid; if (check_context(client) == IRECV_E_SUCCESS) { - irecv_close(client); + irecv_cleanup(client); } if (initial_pause > 0) { @@ -4248,6 +4287,11 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause) new_client->postcommand_callback = postcommand_callback; new_client->disconnected_callback = disconnected_callback; + // keep old handle valid + memcpy(client, new_client, sizeof(*client)); + free(new_client); + new_client = client; + if (new_client->connected_callback != NULL) { irecv_event_t event; event.size = 0; |