summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar tihmstar2023-12-14 01:14:00 +0100
committerGravatar Nikias Bassen2025-09-06 20:04:57 +0200
commit7a84cd9f639a1962d5e73118263a1b2fbab52b14 (patch)
tree5a3c5662effefaf1dc0f4d09c1cdf06ab9f199d4 /src
parent52a81e111664cb267bd5b646ece9cb90c1a6fa94 (diff)
downloadlibirecovery-7a84cd9f639a1962d5e73118263a1b2fbab52b14.tar.gz
libirecovery-7a84cd9f639a1962d5e73118263a1b2fbab52b14.tar.bz2
Add iOS 2 support
Diffstat (limited to 'src')
-rw-r--r--src/libirecovery.c54
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
795 ptr = strstr(iboot_string, "CPID:"); 795 ptr = strstr(iboot_string, "CPID:");
796 if (ptr != NULL) { 796 if (ptr != NULL) {
797 sscanf(ptr, "CPID:%x", &client->device_info.cpid); 797 sscanf(ptr, "CPID:%x", &client->device_info.cpid);
798 client->device_info.have_cpid = 1;
798 } else { 799 } else {
799 // early iOS 1 doesn't identify itself 800 // early iOS 1 doesn't identify itself
800 client->device_info.cpid = 0x8900; 801 client->device_info.cpid = 0x8900;
@@ -803,16 +804,19 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons
803 ptr = strstr(iboot_string, "CPRV:"); 804 ptr = strstr(iboot_string, "CPRV:");
804 if (ptr != NULL) { 805 if (ptr != NULL) {
805 sscanf(ptr, "CPRV:%x", &client->device_info.cprv); 806 sscanf(ptr, "CPRV:%x", &client->device_info.cprv);
807 client->device_info.have_cprv = 1;
806 } 808 }
807 809
808 ptr = strstr(iboot_string, "CPFM:"); 810 ptr = strstr(iboot_string, "CPFM:");
809 if (ptr != NULL) { 811 if (ptr != NULL) {
810 sscanf(ptr, "CPFM:%x", &client->device_info.cpfm); 812 sscanf(ptr, "CPFM:%x", &client->device_info.cpfm);
813 client->device_info.have_cpfm = 1;
811 } 814 }
812 815
813 ptr = strstr(iboot_string, "SCEP:"); 816 ptr = strstr(iboot_string, "SCEP:");
814 if (ptr != NULL) { 817 if (ptr != NULL) {
815 sscanf(ptr, "SCEP:%x", &client->device_info.scep); 818 sscanf(ptr, "SCEP:%x", &client->device_info.scep);
819 client->device_info.have_scep = 1;
816 } 820 }
817 821
818 ptr = strstr(iboot_string, "BDID:"); 822 ptr = strstr(iboot_string, "BDID:");
@@ -820,16 +824,19 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons
820 uint64_t bdid = 0; 824 uint64_t bdid = 0;
821 sscanf(ptr, "BDID:%" SCNx64, &bdid); 825 sscanf(ptr, "BDID:%" SCNx64, &bdid);
822 client->device_info.bdid = (unsigned int)bdid; 826 client->device_info.bdid = (unsigned int)bdid;
827 client->device_info.have_bdid = 1;
823 } 828 }
824 829
825 ptr = strstr(iboot_string, "ECID:"); 830 ptr = strstr(iboot_string, "ECID:");
826 if (ptr != NULL) { 831 if (ptr != NULL) {
827 sscanf(ptr, "ECID:%" SCNx64, &client->device_info.ecid); 832 sscanf(ptr, "ECID:%" SCNx64, &client->device_info.ecid);
833 client->device_info.have_ecid = 1;
828 } 834 }
829 835
830 ptr = strstr(iboot_string, "IBFL:"); 836 ptr = strstr(iboot_string, "IBFL:");
831 if (ptr != NULL) { 837 if (ptr != NULL) {
832 sscanf(ptr, "IBFL:%x", &client->device_info.ibfl); 838 sscanf(ptr, "IBFL:%x", &client->device_info.ibfl);
839 client->device_info.have_ibfl = 1;
833 } 840 }
834 841
835 char tmp[256]; 842 char tmp[256];
@@ -3143,7 +3150,7 @@ irecv_error_t irecv_device_event_unsubscribe(irecv_device_event_context_t contex
3143#endif 3150#endif
3144} 3151}
3145 3152
3146irecv_error_t irecv_close(irecv_client_t client) 3153static irecv_error_t irecv_cleanup(irecv_client_t client)
3147{ 3154{
3148#ifdef USE_DUMMY 3155#ifdef USE_DUMMY
3149 return IRECV_E_UNSUPPORTED; 3156 return IRECV_E_UNSUPPORTED;
@@ -3187,15 +3194,23 @@ irecv_error_t irecv_close(irecv_client_t client)
3187 free(client->device_info.serial_string); 3194 free(client->device_info.serial_string);
3188 free(client->device_info.ap_nonce); 3195 free(client->device_info.ap_nonce);
3189 free(client->device_info.sep_nonce); 3196 free(client->device_info.sep_nonce);
3190
3191 free(client);
3192 client = NULL;
3193 } 3197 }
3194 3198
3195 return IRECV_E_SUCCESS; 3199 return IRECV_E_SUCCESS;
3196#endif 3200#endif
3197} 3201}
3198 3202
3203irecv_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
3199void irecv_set_debug_level(int level) 3214void irecv_set_debug_level(int level)
3200{ 3215{
3201 libirecovery_debug = level; 3216 libirecovery_debug = level;
@@ -3472,6 +3487,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
3472 irecv_error_t error = 0; 3487 irecv_error_t error = 0;
3473 int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)); 3488 int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE));
3474 int legacy_recovery_mode = 0; 3489 int legacy_recovery_mode = 0;
3490 int isiOS2 = 0;
3475 3491
3476 if (recovery_mode && client->device_info.cpid == 0x8900 && !client->device_info.ecid) { 3492 if (recovery_mode && client->device_info.cpid == 0x8900 && !client->device_info.ecid) {
3477#ifdef DEBUG 3493#ifdef DEBUG
@@ -3484,6 +3500,17 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
3484 legacy_recovery_mode = 1; 3500 legacy_recovery_mode = 1;
3485 } 3501 }
3486 3502
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
3487 if (check_context(client) != IRECV_E_SUCCESS) 3514 if (check_context(client) != IRECV_E_SUCCESS)
3488 return IRECV_E_NO_DEVICE; 3515 return IRECV_E_NO_DEVICE;
3489 3516
@@ -3536,6 +3563,14 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
3536 case 2: 3563 case 2:
3537 /* DFU IDLE */ 3564 /* DFU IDLE */
3538 break; 3565 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;
3539 case 10: 3574 case 10:
3540 debug("DFU ERROR, issuing CLRSTATUS\n"); 3575 debug("DFU ERROR, issuing CLRSTATUS\n");
3541 irecv_usb_control_transfer(client, 0x21, 4, 0, 0, NULL, 0, USB_TIMEOUT); 3576 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
3673 } 3708 }
3674 3709
3675 irecv_reset(client); 3710 irecv_reset(client);
3711
3712 if (isiOS2) {
3713 irecv_reconnect(client, 0);
3714 }
3676 } 3715 }
3677 3716
3678 if (legacy_recovery_mode) { 3717 if (legacy_recovery_mode) {
@@ -4228,7 +4267,7 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause)
4228 uint64_t ecid = client->device_info.ecid; 4267 uint64_t ecid = client->device_info.ecid;
4229 4268
4230 if (check_context(client) == IRECV_E_SUCCESS) { 4269 if (check_context(client) == IRECV_E_SUCCESS) {
4231 irecv_close(client); 4270 irecv_cleanup(client);
4232 } 4271 }
4233 4272
4234 if (initial_pause > 0) { 4273 if (initial_pause > 0) {
@@ -4248,6 +4287,11 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause)
4248 new_client->postcommand_callback = postcommand_callback; 4287 new_client->postcommand_callback = postcommand_callback;
4249 new_client->disconnected_callback = disconnected_callback; 4288 new_client->disconnected_callback = disconnected_callback;
4250 4289
4290 // keep old handle valid
4291 memcpy(client, new_client, sizeof(*client));
4292 free(new_client);
4293 new_client = client;
4294
4251 if (new_client->connected_callback != NULL) { 4295 if (new_client->connected_callback != NULL) {
4252 irecv_event_t event; 4296 irecv_event_t event;
4253 event.size = 0; 4297 event.size = 0;