summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2024-03-21 01:31:48 +0100
committerGravatar Nikias Bassen2024-03-21 01:31:48 +0100
commitd3198a50e51674e0ec19284f44f4aeb027d160a3 (patch)
treee6b33b0757ba9ed14e5fcafb67bb83e62990138f
parentb55d215c25fd415b49430dc3c8423dde7d8f12aa (diff)
downloadlibirecovery-d3198a50e51674e0ec19284f44f4aeb027d160a3.tar.gz
libirecovery-d3198a50e51674e0ec19284f44f4aeb027d160a3.tar.bz2
Add support for Port DFU
Note: This does not allow restoring devices in Port DFU mode, this is handled in idevicerestore.
-rw-r--r--include/libirecovery.h3
-rw-r--r--src/libirecovery.c36
-rw-r--r--tools/irecovery.c3
3 files changed, 30 insertions, 12 deletions
diff --git a/include/libirecovery.h b/include/libirecovery.h
index 7b89d1f..04892c4 100644
--- a/include/libirecovery.h
+++ b/include/libirecovery.h
@@ -43,7 +43,8 @@ enum irecv_mode {
43 IRECV_K_RECOVERY_MODE_3 = 0x1282, 43 IRECV_K_RECOVERY_MODE_3 = 0x1282,
44 IRECV_K_RECOVERY_MODE_4 = 0x1283, 44 IRECV_K_RECOVERY_MODE_4 = 0x1283,
45 IRECV_K_WTF_MODE = 0x1222, 45 IRECV_K_WTF_MODE = 0x1222,
46 IRECV_K_DFU_MODE = 0x1227 46 IRECV_K_DFU_MODE = 0x1227,
47 IRECV_K_PORT_DFU_MODE = 0xf014
47}; 48};
48 49
49typedef enum { 50typedef enum {
diff --git a/src/libirecovery.c b/src/libirecovery.c
index 7d6c46c..b1b81e0 100644
--- a/src/libirecovery.c
+++ b/src/libirecovery.c
@@ -768,7 +768,9 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons
768 768
769 ptr = strstr(iboot_string, "BDID:"); 769 ptr = strstr(iboot_string, "BDID:");
770 if (ptr != NULL) { 770 if (ptr != NULL) {
771 sscanf(ptr, "BDID:%x", &client->device_info.bdid); 771 uint64_t bdid = 0;
772 sscanf(ptr, "BDID:%" SCNx64, &bdid);
773 client->device_info.bdid = (unsigned int)bdid;
772 } 774 }
773 775
774 ptr = strstr(iboot_string, "ECID:"); 776 ptr = strstr(iboot_string, "ECID:");
@@ -1136,6 +1138,7 @@ static irecv_error_t irecv_kis_load_device_info(irecv_client_t client)
1136static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L, 0xD61A, 0x4AF6, {0x9A, 0xB6, 0x11, 0xE5, 0x22, 0x36, 0xC5, 0x76}}; 1138static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L, 0xD61A, 0x4AF6, {0x9A, 0xB6, 0x11, 0xE5, 0x22, 0x36, 0xC5, 0x76}};
1137static const GUID GUID_DEVINTERFACE_DFU = {0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}}; 1139static const GUID GUID_DEVINTERFACE_DFU = {0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}};
1138static const GUID GUID_DEVINTERFACE_KIS = {0xB36F4137L, 0xF4EF, 0x4BFC, {0xA2, 0x5A, 0xC2, 0x41, 0x07, 0x68, 0xEE, 0x37}}; 1140static const GUID GUID_DEVINTERFACE_KIS = {0xB36F4137L, 0xF4EF, 0x4BFC, {0xA2, 0x5A, 0xC2, 0x41, 0x07, 0x68, 0xEE, 0x37}};
1141static const GUID GUID_DEVINTERFACE_PORTDFU = {0xAF633FF1L, 0x1170, 0x4CA6, {0xAE, 0x9E, 0x08, 0xD0, 0x01, 0x42, 0x1E, 0xAA}};
1139 1142
1140typedef struct usb_control_request { 1143typedef struct usb_control_request {
1141 uint8_t bmRequestType; 1144 uint8_t bmRequestType;
@@ -1150,7 +1153,7 @@ typedef struct usb_control_request {
1150static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) 1153static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid)
1151{ 1154{
1152 int found = 0; 1155 int found = 0;
1153 const GUID *guids[] = { &GUID_DEVINTERFACE_KIS, &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL }; 1156 const GUID *guids[] = { &GUID_DEVINTERFACE_KIS, &GUID_DEVINTERFACE_PORTDFU, &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL };
1154 irecv_client_t _client = (irecv_client_t) malloc(sizeof(struct irecv_client_private)); 1157 irecv_client_t _client = (irecv_client_t) malloc(sizeof(struct irecv_client_private));
1155 memset(_client, 0, sizeof(struct irecv_client_private)); 1158 memset(_client, 0, sizeof(struct irecv_client_private));
1156 1159
@@ -1187,6 +1190,7 @@ static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid)
1187 1190
1188 // make sure the current device is actually in the right mode for the given driver interface 1191 // make sure the current device is actually in the right mode for the given driver interface
1189 if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE) 1192 if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE)
1193 || (guids[k] == &GUID_DEVINTERFACE_PORTDFU && pid != IRECV_K_PORT_DFU_MODE)
1190 || (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4)) 1194 || (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4))
1191 || (guids[k] == &GUID_DEVINTERFACE_KIS && pid != 1) 1195 || (guids[k] == &GUID_DEVINTERFACE_KIS && pid != 1)
1192 ) { 1196 ) {
@@ -1599,7 +1603,7 @@ static irecv_error_t iokit_open_with_ecid(irecv_client_t* pclient, uint64_t ecid
1599 CFRange range; 1603 CFRange range;
1600 1604
1601 UInt16 wtf_pids[] = { IRECV_K_WTF_MODE, 0}; 1605 UInt16 wtf_pids[] = { IRECV_K_WTF_MODE, 0};
1602 UInt16 all_pids[] = { IRECV_K_WTF_MODE, IRECV_K_DFU_MODE, IRECV_K_RECOVERY_MODE_1, IRECV_K_RECOVERY_MODE_2, IRECV_K_RECOVERY_MODE_3, IRECV_K_RECOVERY_MODE_4, KIS_PRODUCT_ID, 0 }; 1606 UInt16 all_pids[] = { IRECV_K_WTF_MODE, IRECV_K_DFU_MODE, IRECV_K_PORT_DFU_MODE, IRECV_K_RECOVERY_MODE_1, IRECV_K_RECOVERY_MODE_2, IRECV_K_RECOVERY_MODE_3, IRECV_K_RECOVERY_MODE_4, KIS_PRODUCT_ID, 0 };
1603 UInt16 *pids = all_pids; 1607 UInt16 *pids = all_pids;
1604 int i; 1608 int i;
1605 1609
@@ -1737,6 +1741,7 @@ static irecv_error_t libusb_open_with_ecid(irecv_client_t* pclient, uint64_t eci
1737 usb_descriptor.idProduct == IRECV_K_RECOVERY_MODE_4 || 1741 usb_descriptor.idProduct == IRECV_K_RECOVERY_MODE_4 ||
1738 usb_descriptor.idProduct == IRECV_K_WTF_MODE || 1742 usb_descriptor.idProduct == IRECV_K_WTF_MODE ||
1739 usb_descriptor.idProduct == IRECV_K_DFU_MODE || 1743 usb_descriptor.idProduct == IRECV_K_DFU_MODE ||
1744 usb_descriptor.idProduct == IRECV_K_PORT_DFU_MODE ||
1740 usb_descriptor.idProduct == KIS_PRODUCT_ID) { 1745 usb_descriptor.idProduct == KIS_PRODUCT_ID) {
1741 1746
1742 if (ecid == IRECV_K_WTF_MODE) { 1747 if (ecid == IRECV_K_WTF_MODE) {
@@ -1814,7 +1819,7 @@ irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, uint64_t ecid)
1814 return error; 1819 return error;
1815 } 1820 }
1816 1821
1817 if (client->mode == IRECV_K_DFU_MODE || client->mode == IRECV_K_WTF_MODE || client->mode == KIS_PRODUCT_ID) { 1822 if (client->mode == IRECV_K_DFU_MODE || client->mode == IRECV_K_PORT_DFU_MODE || client->mode == IRECV_K_WTF_MODE || client->mode == KIS_PRODUCT_ID) {
1818 error = irecv_usb_set_interface(client, 0, 0); 1823 error = irecv_usb_set_interface(client, 0, 0);
1819 } else { 1824 } else {
1820 error = irecv_usb_set_interface(client, 0, 0); 1825 error = irecv_usb_set_interface(client, 0, 0);
@@ -2238,6 +2243,7 @@ static int _irecv_is_recovery_device(void *device)
2238 case IRECV_K_RECOVERY_MODE_2: 2243 case IRECV_K_RECOVERY_MODE_2:
2239 case IRECV_K_RECOVERY_MODE_3: 2244 case IRECV_K_RECOVERY_MODE_3:
2240 case IRECV_K_RECOVERY_MODE_4: 2245 case IRECV_K_RECOVERY_MODE_4:
2246 case IRECV_K_PORT_DFU_MODE:
2241 case KIS_PRODUCT_ID: 2247 case KIS_PRODUCT_ID:
2242 break; 2248 break;
2243 default: 2249 default:
@@ -2596,7 +2602,7 @@ static void *_irecv_event_handler(void* data)
2596 struct _irecv_event_handler_info* info = (struct _irecv_event_handler_info*)data; 2602 struct _irecv_event_handler_info* info = (struct _irecv_event_handler_info*)data;
2597#ifdef WIN32 2603#ifdef WIN32
2598 struct collection newDevices; 2604 struct collection newDevices;
2599 const GUID *guids[] = { &GUID_DEVINTERFACE_KIS, &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL }; 2605 const GUID *guids[] = { &GUID_DEVINTERFACE_KIS, &GUID_DEVINTERFACE_PORTDFU, &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL };
2600 int running = 1; 2606 int running = 1;
2601 2607
2602 collection_init(&newDevices); 2608 collection_init(&newDevices);
@@ -2693,6 +2699,7 @@ static void *_irecv_event_handler(void* data)
2693 // make sure the current device is actually in the right mode for the given driver interface 2699 // make sure the current device is actually in the right mode for the given driver interface
2694 int skip = 0; 2700 int skip = 0;
2695 if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE) 2701 if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE)
2702 || (guids[k] == &GUID_DEVINTERFACE_PORTDFU && pid != IRECV_K_PORT_DFU_MODE)
2696 || (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4)) 2703 || (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4))
2697 || (guids[k] == &GUID_DEVINTERFACE_KIS && pid != 1) 2704 || (guids[k] == &GUID_DEVINTERFACE_KIS && pid != 1)
2698 ) { 2705 ) {
@@ -2746,7 +2753,7 @@ static void *_irecv_event_handler(void* data)
2746 iokit_runloop = CFRunLoopGetCurrent(); 2753 iokit_runloop = CFRunLoopGetCurrent();
2747 CFRunLoopAddSource(iokit_runloop, runLoopSource, kCFRunLoopDefaultMode); 2754 CFRunLoopAddSource(iokit_runloop, runLoopSource, kCFRunLoopDefaultMode);
2748 2755
2749 uint16_t pids[8] = { IRECV_K_WTF_MODE, IRECV_K_DFU_MODE, IRECV_K_RECOVERY_MODE_1, IRECV_K_RECOVERY_MODE_2, IRECV_K_RECOVERY_MODE_3, IRECV_K_RECOVERY_MODE_4, KIS_PRODUCT_ID, 0 }; 2756 uint16_t pids[9] = { IRECV_K_WTF_MODE, IRECV_K_DFU_MODE, IRECV_K_RECOVERY_MODE_1, IRECV_K_RECOVERY_MODE_2, IRECV_K_RECOVERY_MODE_3, IRECV_K_RECOVERY_MODE_4, IRECV_K_PORT_DFU_MODE, KIS_PRODUCT_ID, 0 };
2750 int i = 0; 2757 int i = 0;
2751 while (pids[i] > 0) { 2758 while (pids[i] > 0) {
2752 CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName); 2759 CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
@@ -3005,7 +3012,7 @@ irecv_error_t irecv_close(irecv_client_t client)
3005 } 3012 }
3006#else 3013#else
3007 if (client->handle != NULL) { 3014 if (client->handle != NULL) {
3008 if ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE) && (client->isKIS == 0)) { 3015 if ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE) && (client->isKIS == 0)) {
3009 libusb_release_interface(client->handle, client->usb_interface); 3016 libusb_release_interface(client->handle, client->usb_interface);
3010 } 3017 }
3011 libusb_close(client->handle); 3018 libusb_close(client->handle);
@@ -3275,7 +3282,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
3275 return irecv_kis_send_buffer(client, buffer, length, dfu_notify_finished); 3282 return irecv_kis_send_buffer(client, buffer, length, dfu_notify_finished);
3276 3283
3277 irecv_error_t error = 0; 3284 irecv_error_t error = 0;
3278 int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)); 3285 int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE));
3279 3286
3280 if (check_context(client) != IRECV_E_SUCCESS) 3287 if (check_context(client) != IRECV_E_SUCCESS)
3281 return IRECV_E_NO_DEVICE; 3288 return IRECV_E_NO_DEVICE;
@@ -3806,7 +3813,7 @@ irecv_error_t irecv_reset_counters(irecv_client_t client)
3806 if (check_context(client) != IRECV_E_SUCCESS) 3813 if (check_context(client) != IRECV_E_SUCCESS)
3807 return IRECV_E_NO_DEVICE; 3814 return IRECV_E_NO_DEVICE;
3808 3815
3809 if ((client->mode == IRECV_K_DFU_MODE) || (client->mode == IRECV_K_WTF_MODE)) { 3816 if ((client->mode == IRECV_K_DFU_MODE) || (client->mode == IRECV_K_PORT_DFU_MODE) || (client->mode == IRECV_K_WTF_MODE)) {
3810 irecv_usb_control_transfer(client, 0x21, 4, 0, 0, 0, 0, USB_TIMEOUT); 3817 irecv_usb_control_transfer(client, 0x21, 4, 0, 0, 0, 0, USB_TIMEOUT);
3811 } 3818 }
3812 3819
@@ -3819,7 +3826,7 @@ irecv_error_t irecv_recv_buffer(irecv_client_t client, char* buffer, unsigned lo
3819#ifdef USE_DUMMY 3826#ifdef USE_DUMMY
3820 return IRECV_E_UNSUPPORTED; 3827 return IRECV_E_UNSUPPORTED;
3821#else 3828#else
3822 int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)); 3829 int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE));
3823 3830
3824 if (check_context(client) != IRECV_E_SUCCESS) 3831 if (check_context(client) != IRECV_E_SUCCESS)
3825 return IRECV_E_NO_DEVICE; 3832 return IRECV_E_NO_DEVICE;
@@ -3905,8 +3912,15 @@ irecv_error_t irecv_devices_get_device_by_client(irecv_client_t client, irecv_de
3905 return IRECV_E_UNKNOWN_ERROR; 3912 return IRECV_E_UNKNOWN_ERROR;
3906 } 3913 }
3907 3914
3915 unsigned int cpid_match = client->device_info.cpid;
3916 unsigned int bdid_match = client->device_info.bdid;
3917 if (client->mode == IRECV_K_PORT_DFU_MODE) {
3918 cpid_match = (client->device_info.bdid >> 8) & 0xFFFF;
3919 bdid_match = (client->device_info.bdid >> 24) & 0xFF;
3920 }
3921
3908 for (i = 0; irecv_devices[i].hardware_model != NULL; i++) { 3922 for (i = 0; irecv_devices[i].hardware_model != NULL; i++) {
3909 if (irecv_devices[i].chip_id == client->device_info.cpid && irecv_devices[i].board_id == client->device_info.bdid) { 3923 if (irecv_devices[i].chip_id == cpid_match && irecv_devices[i].board_id == bdid_match) {
3910 *device = &irecv_devices[i]; 3924 *device = &irecv_devices[i];
3911 return IRECV_E_SUCCESS; 3925 return IRECV_E_SUCCESS;
3912 } 3926 }
diff --git a/tools/irecovery.c b/tools/irecovery.c
index 6303b55..955d3ca 100644
--- a/tools/irecovery.c
+++ b/tools/irecovery.c
@@ -90,6 +90,9 @@ static const char* mode_to_str(int mode)
90 case IRECV_K_DFU_MODE: 90 case IRECV_K_DFU_MODE:
91 return "DFU"; 91 return "DFU";
92 break; 92 break;
93 case IRECV_K_PORT_DFU_MODE:
94 return "Port DFU";
95 break;
93 case IRECV_K_WTF_MODE: 96 case IRECV_K_WTF_MODE:
94 return "WTF"; 97 return "WTF";
95 break; 98 break;