@@ -454,6 +454,26 @@ static unsigned int crc32_lookup_t1[256] = {
454454#define crc32_step (a ,b ) \
455455 a = (crc32_lookup_t1[(a & 0xFF) ^ ((unsigned char)b)] ^ (a >> 8))
456456
457+ #ifdef WIN32
458+ #pragma pack(1)
459+ typedef struct {
460+ uint16_t vid ;
461+ uint16_t pid ;
462+ uint32_t unk ;
463+ char nonces [255 ];
464+ char serial [255 ];
465+ char manufacturer [255 ];
466+ char product [255 ];
467+ } KIS_device_info ;
468+
469+ typedef struct {
470+ uint8_t data [0x4000 ];
471+ uint32_t size ;
472+ uint32_t unused ;
473+ uint64_t address ;
474+ } KIS_upload_chunk ;
475+ #pragma pack()
476+ #else
457477#pragma pack(1)
458478typedef struct {
459479 uint16_t sequence ; // A sequence number
@@ -525,6 +545,7 @@ typedef struct {
525545 uint32_t status ;
526546} KIS_generic_reply ;
527547#pragma pack()
548+ #endif
528549
529550static THREAD_T th_event_handler = THREAD_T_NULL ;
530551struct collection listeners ;
@@ -873,6 +894,7 @@ static void irecv_copy_nonce_with_tag(irecv_client_t client, const char* tag, un
873894 irecv_copy_nonce_with_tag_from_buffer (tag ,nonce ,nonce_size ,buf );
874895}
875896
897+ #ifndef WIN32
876898static irecv_error_t irecv_kis_request_init (KIS_req_header * hdr , uint8_t portal , uint16_t index , size_t argCount , size_t payloadSize , size_t rplWords )
877899{
878900 if (argCount > UINT8_MAX ) {
@@ -1001,9 +1023,11 @@ static int irecv_kis_read_string(KIS_device_info *di, size_t off, char *buf, siz
10011023
10021024 return len /2 ;
10031025}
1026+ #endif
10041027
10051028static irecv_error_t irecv_kis_init (irecv_client_t client )
10061029{
1030+ #ifndef WIN32
10071031 irecv_error_t err = irecv_kis_config_write32 (client , KIS_PORTAL_CONFIG , KIS_INDEX_ENABLE_A , KIS_ENABLE_A_VAL );
10081032 if (err != IRECV_E_SUCCESS ) {
10091033 debug ("Failed to write to KIS_INDEX_ENABLE_A, error %d\n" , err );
@@ -1015,7 +1039,7 @@ static irecv_error_t irecv_kis_init(irecv_client_t client)
10151039 debug ("Failed to write to KIS_INDEX_ENABLE_B, error %d\n" , err );
10161040 return err ;
10171041 }
1018-
1042+ #endif
10191043 client -> isKIS = 1 ;
10201044
10211045 return IRECV_E_SUCCESS ;
@@ -1024,7 +1048,23 @@ static irecv_error_t irecv_kis_init(irecv_client_t client)
10241048static irecv_error_t irecv_kis_load_device_info (irecv_client_t client )
10251049{
10261050 debug ("Loading device info in KIS mode...\n" );
1027-
1051+ #ifdef WIN32
1052+ KIS_device_info kisInfo ;
1053+ DWORD transferred = 0 ;
1054+ int ret = DeviceIoControl (client -> handle , 0x220004 , NULL , 0 , & kisInfo , sizeof (kisInfo ), (PDWORD )& transferred , NULL );
1055+ if (ret ) {
1056+ debug ("Serial: %s\n" , kisInfo .serial );
1057+ irecv_load_device_info_from_iboot_string (client , kisInfo .serial );
1058+ debug ("Manufacturer: %s\n" , kisInfo .manufacturer );
1059+ debug ("Product: %s\n" , kisInfo .product );
1060+ debug ("Nonces: %s\n" , kisInfo .nonces );
1061+ irecv_copy_nonce_with_tag_from_buffer ("NONC" , & client -> device_info .ap_nonce , & client -> device_info .ap_nonce_size , kisInfo .nonces );
1062+ irecv_copy_nonce_with_tag_from_buffer ("SNON" , & client -> device_info .sep_nonce , & client -> device_info .sep_nonce_size , kisInfo .nonces );
1063+ debug ("VID: 0x%04x\n" , kisInfo .vid );
1064+ debug ("PID: 0x%04x\n" , kisInfo .pid );
1065+ }
1066+ client -> mode = kisInfo .pid ;
1067+ #else
10281068 KIS_req_header req = {};
10291069 KIS_device_info di = {};
10301070 irecv_error_t err = irecv_kis_request_init (& req , KIS_PORTAL_RSM , KIS_INDEX_GET_INFO , 0 , 0 , sizeof (di .deviceInfo )/4 );
@@ -1072,13 +1112,14 @@ static irecv_error_t irecv_kis_load_device_info(irecv_client_t client)
10721112 debug ("PID: 0x%04x\n" , di .deviceDescriptor .idProduct );
10731113
10741114 client -> mode = di .deviceDescriptor .idProduct ;
1075-
1115+ #endif
10761116 return IRECV_E_SUCCESS ;
10771117}
10781118
10791119#ifdef WIN32
10801120static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L , 0xD61A , 0x4AF6 , {0x9A , 0xB6 , 0x11 , 0xE5 , 0x22 , 0x36 , 0xC5 , 0x76 }};
10811121static const GUID GUID_DEVINTERFACE_DFU = {0xB8085869L , 0xFEB9 , 0x404B , {0x8C , 0xB1 , 0x1E , 0x5C , 0x14 , 0xFA , 0x8C , 0x54 }};
1122+ static const GUID GUID_DEVINTERFACE_KIS = {0xB36F4137L , 0xF4EF , 0x4BFC , {0xA2 , 0x5A , 0xC2 , 0x41 , 0x07 , 0x68 , 0xEE , 0x37 }};
10821123
10831124typedef struct usb_control_request {
10841125 uint8_t bmRequestType ;
@@ -1093,7 +1134,7 @@ typedef struct usb_control_request {
10931134static irecv_error_t win32_open_with_ecid (irecv_client_t * client , uint64_t ecid )
10941135{
10951136 int found = 0 ;
1096- const GUID * guids [] = { & GUID_DEVINTERFACE_DFU , & GUID_DEVINTERFACE_IBOOT , NULL };
1137+ const GUID * guids [] = { & GUID_DEVINTERFACE_KIS , & GUID_DEVINTERFACE_DFU , & GUID_DEVINTERFACE_IBOOT , NULL };
10971138 irecv_client_t _client = (irecv_client_t ) malloc (sizeof (struct irecv_client_private ));
10981139 memset (_client , 0 , sizeof (struct irecv_client_private ));
10991140
@@ -1117,21 +1158,32 @@ static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid)
11171158 }
11181159
11191160 unsigned int pid = 0 ;
1120- if (sscanf (details -> DevicePath , "\\\\?\\usb#vid_05ac&pid_%04x" , & pid )!= 1 ) {
1121- debug ("%s: ERROR: failed to parse PID! path: %s\n" , __func__ , details -> DevicePath );
1161+ unsigned int vid = 0 ;
1162+ if (sscanf (details -> DevicePath , "\\\\?\\%*3s#vid_%04x&pid_%04x" , & vid , & pid ) != 2 ) {
1163+ debug ("%s: ERROR: failed to parse VID/PID! path: %s\n" , __func__ , details -> DevicePath );
11221164 free (details );
11231165 continue ;
11241166 }
1167+ if (vid != APPLE_VENDOR_ID ) {
1168+ free (details );
1169+ continue ;
1170+ }
1171+
11251172 // make sure the current device is actually in the right mode for the given driver interface
11261173 if ((guids [k ] == & GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE )
11271174 || (guids [k ] == & GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4 ))
1175+ || (guids [k ] == & GUID_DEVINTERFACE_KIS && pid != 1 )
11281176 ) {
11291177 free (details );
11301178 continue ;
11311179 }
1180+ if (guids [k ] == & GUID_DEVINTERFACE_KIS ) {
1181+ pid = KIS_PRODUCT_ID ;
1182+ }
11321183
11331184 _client -> handle = CreateFileA (details -> DevicePath , GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_FLAG_OVERLAPPED , NULL );
11341185 if (_client -> handle == INVALID_HANDLE_VALUE ) {
1186+ debug ("%s: Failed to open device path %s: %d\n" , __func__ , details -> DevicePath , (int )GetLastError ());
11351187 free (details );
11361188 continue ;
11371189 }
@@ -1158,34 +1210,35 @@ static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid)
11581210 char serial_str [256 ];
11591211 serial_str [0 ] = '\0' ;
11601212
1161- char * p = (char * )details -> DevicePath ;
1162- while ((p = strstr (p , "\\usb" ))) {
1163- if (sscanf (p , "\\usb#vid_05ac&pid_%*04x#%s" , serial_str ) == 1 )
1164- break ;
1165- p += 4 ;
1166- }
1167- free (details );
1168-
1169- if (serial_str [0 ] == '\0' ) {
1170- CloseHandle (_client -> handle );
1171- continue ;
1172- }
1213+ if (_client -> mode != KIS_PRODUCT_ID ) {
1214+ char * p = (char * )details -> DevicePath ;
1215+ while ((p = strstr (p , "\\usb" ))) {
1216+ if (sscanf (p , "\\usb#vid_05ac&pid_%*04x#%s" , serial_str ) == 1 )
1217+ break ;
1218+ p += 4 ;
1219+ }
1220+ free (details );
11731221
1174- p = strchr (serial_str , '#' );
1175- if (p ) {
1176- * p = '\0' ;
1177- }
1222+ if (serial_str [0 ] == '\0' ) {
1223+ CloseHandle (_client -> handle );
1224+ continue ;
1225+ }
1226+ p = strchr (serial_str , '#' );
1227+ if (p ) {
1228+ * p = '\0' ;
1229+ }
11781230
1179- unsigned int j ;
1180- for (j = 0 ; j < strlen (serial_str ); j ++ ) {
1181- if (serial_str [j ] == '_' ) {
1182- serial_str [j ] = ' ' ;
1183- } else {
1184- serial_str [j ] = toupper (serial_str [j ]);
1231+ unsigned int j ;
1232+ for (j = 0 ; j < strlen (serial_str ); j ++ ) {
1233+ if (serial_str [j ] == '_' ) {
1234+ serial_str [j ] = ' ' ;
1235+ } else {
1236+ serial_str [j ] = toupper (serial_str [j ]);
1237+ }
11851238 }
1186- }
11871239
1188- irecv_load_device_info_from_iboot_string (_client , serial_str );
1240+ irecv_load_device_info_from_iboot_string (_client , serial_str );
1241+ }
11891242
11901243 if (ecid != 0 ) {
11911244 if (_client -> device_info .ecid != ecid ) {
@@ -1434,7 +1487,7 @@ int irecv_usb_bulk_transfer(irecv_client_t client,
14341487#endif
14351488#else
14361489 if (endpoint == 0x4 ) {
1437- ret = DeviceIoControl (client -> handle , 0x220195 , data , length , data , length , (PDWORD ) transferred , NULL );
1490+ ret = DeviceIoControl (client -> handle , 0x2201B6 , data , length , data , length , (PDWORD ) transferred , NULL );
14381491 } else {
14391492 ret = 0 ;
14401493 }
@@ -2202,40 +2255,51 @@ static void* _irecv_handle_device_add(void *userdata)
22022255
22032256 unsigned int pid = 0 ;
22042257
2205- char * p = result ;
2206- while ((p = strstr (p , "\\usb" ))) {
2207- if (sscanf (p , "\\usb#vid_05ac&pid_%04x#%s" , & pid , serial_str ) == 2 )
2208- break ;
2209- p += 4 ;
2210- }
2211-
2212- if (serial_str [0 ] == '\0' ) {
2213- debug ("%s: ERROR: failed to parse DevicePath?!\n" , __func__ );
2214- return NULL ;
2215- }
2216-
2217- if (!_irecv_is_recovery_device (p )) {
2218- return NULL ;
2219- }
2258+ if (strncmp (result , "\\\\?\\kis#" , 8 ) == 0 ) {
2259+ pid = KIS_PRODUCT_ID ;
2260+ } else {
2261+ char * p = result ;
2262+ while ((p = strstr (p , "\\usb" ))) {
2263+ if (sscanf (p , "\\usb#vid_05ac&pid_%04x#%s" , & pid , serial_str ) == 2 )
2264+ break ;
2265+ p += 4 ;
2266+ }
22202267
2221- p = strchr (serial_str , '#' );
2222- if ( p ) {
2223- * p = '\0' ;
2224- }
2268+ if (serial_str [ 0 ] == '\0' ) {
2269+ debug ( "%s: ERROR: failed to parse DevicePath?!\n" , __func__ );
2270+ return NULL ;
2271+ }
22252272
2226- unsigned int j ;
2227- for (j = 0 ; j < strlen (serial_str ); j ++ ) {
2228- if (serial_str [j ] == '_' ) {
2229- serial_str [j ] = ' ' ;
2230- } else {
2231- serial_str [j ] = toupper (serial_str [j ]);
2273+ if (!_irecv_is_recovery_device (p )) {
2274+ return NULL ;
22322275 }
22332276 }
2277+
22342278 product_id = (uint16_t )pid ;
22352279
22362280 if (product_id == KIS_PRODUCT_ID ) {
2237- debug ("%s: ERROR: KIS currently not supported with this backend!\n" , __func__ );
2238- return NULL ;
2281+ client = (irecv_client_t )malloc (sizeof (struct irecv_client_private ));
2282+ client -> handle = CreateFileA (result , GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_FLAG_OVERLAPPED , NULL );
2283+ if (client -> handle == INVALID_HANDLE_VALUE ) {
2284+ debug ("%s: Failed to open device path %s\n" , __func__ , result );
2285+ free (client );
2286+ return NULL ;
2287+ }
2288+ client -> mode = pid ;
2289+ } else {
2290+ char * p = strchr (serial_str , '#' );
2291+ if (p ) {
2292+ * p = '\0' ;
2293+ }
2294+
2295+ unsigned int j ;
2296+ for (j = 0 ; j < strlen (serial_str ); j ++ ) {
2297+ if (serial_str [j ] == '_' ) {
2298+ serial_str [j ] = ' ' ;
2299+ } else {
2300+ serial_str [j ] = toupper (serial_str [j ]);
2301+ }
2302+ }
22392303 }
22402304
22412305#else /* !WIN32 */
@@ -2523,7 +2587,7 @@ static void *_irecv_event_handler(void* data)
25232587 struct _irecv_event_handler_info * info = (struct _irecv_event_handler_info * )data ;
25242588#ifdef WIN32
25252589 struct collection newDevices ;
2526- const GUID * guids [] = { & GUID_DEVINTERFACE_DFU , & GUID_DEVINTERFACE_IBOOT , NULL };
2590+ const GUID * guids [] = { & GUID_DEVINTERFACE_KIS , & GUID_DEVINTERFACE_DFU , & GUID_DEVINTERFACE_IBOOT , NULL };
25272591 int running = 1 ;
25282592
25292593 collection_init (& newDevices );
@@ -2606,15 +2670,22 @@ static void *_irecv_event_handler(void* data)
26062670 } ENDFOREACH
26072671
26082672 unsigned int pid = 0 ;
2609- if (sscanf (details -> DevicePath , "\\\\?\\usb#vid_05ac&pid_%04x" , & pid )!= 1 ) {
2610- debug ("%s: ERROR: failed to parse PID! path: %s\n" , __func__ , details -> DevicePath );
2673+ unsigned int vid = 0 ;
2674+ if (sscanf (details -> DevicePath , "\\\\?\\%*3s#vid_%04x&pid_%04x" , & vid , & pid )!= 2 ) {
2675+ debug ("%s: ERROR: failed to parse VID/PID! path: %s\n" , __func__ , details -> DevicePath );
26112676 free (details );
26122677 continue ;
26132678 }
2679+ if (vid != APPLE_VENDOR_ID ) {
2680+ free (details );
2681+ continue ;
2682+ }
2683+
26142684 // make sure the current device is actually in the right mode for the given driver interface
26152685 int skip = 0 ;
26162686 if ((guids [k ] == & GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE )
26172687 || (guids [k ] == & GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4 ))
2688+ || (guids [k ] == & GUID_DEVINTERFACE_KIS && pid != 1 )
26182689 ) {
26192690 skip = 1 ;
26202691 }
@@ -3109,6 +3180,11 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char*
31093180 if (toUpload > 0x4000 )
31103181 toUpload = 0x4000 ;
31113182
3183+ #ifdef WIN32
3184+ memcpy (chunk -> data , buffer , toUpload );
3185+ chunk -> size = toUpload ;
3186+ chunk -> address = address ;
3187+ #else
31123188 irecv_error_t error = irecv_kis_request_init (& chunk -> hdr , KIS_PORTAL_RSM , KIS_INDEX_UPLOAD , 3 , toUpload , 0 );
31133189 if (error != IRECV_E_SUCCESS ) {
31143190 free (chunk );
@@ -3119,10 +3195,17 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char*
31193195 chunk -> address = address ;
31203196 chunk -> size = toUpload ;
31213197 memcpy (chunk -> data , buffer , toUpload );
3198+ #endif
31223199
3200+ #ifdef WIN32
3201+ DWORD transferred = 0 ;
3202+ int ret = DeviceIoControl (client -> handle , 0x220008 , chunk , sizeof (* chunk ), NULL , 0 , (PDWORD )& transferred , NULL );
3203+ irecv_error_t error = (ret ) ? IRECV_E_SUCCESS : IRECV_E_USB_UPLOAD ;
3204+ #else
31233205 KIS_generic_reply reply ;
31243206 size_t rcvSize = sizeof (reply );
31253207 error = irecv_kis_request (client , & chunk -> hdr , sizeof (* chunk ) - (0x4000 - toUpload ), & reply .hdr , & rcvSize );
3208+ #endif
31263209 if (error != IRECV_E_SUCCESS ) {
31273210 free (chunk );
31283211 debug ("Failed to upload chunk, error %d\n" , error );
@@ -3147,7 +3230,14 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char*
31473230 free (chunk );
31483231
31493232 if (dfu_notify_finished ) {
3233+ #ifdef WIN32
3234+ DWORD amount = (DWORD )origLen ;
3235+ DWORD transferred = 0 ;
3236+ int ret = DeviceIoControl (client -> handle , 0x22000C , & amount , 4 , NULL , 0 , (PDWORD )& transferred , NULL );
3237+ irecv_error_t error = (ret ) ? IRECV_E_SUCCESS : IRECV_E_USB_UPLOAD ;
3238+ #else
31503239 irecv_error_t error = irecv_kis_config_write32 (client , KIS_PORTAL_RSM , KIS_INDEX_BOOT_IMG , origLen );
3240+ #endif
31513241 if (error != IRECV_E_SUCCESS ) {
31523242 debug ("Failed to boot image, error %d\n" , error );
31533243 return error ;
0 commit comments