diff options
author | 2024-01-12 03:16:24 +0100 | |
---|---|---|
committer | 2024-01-12 03:16:24 +0100 | |
commit | 4fa49416d47076a026d7d2858dbe2002aaa1537f (patch) | |
tree | 78fc2ac012a539d4c8408f7ff7047c60511e4a96 | |
parent | 63ea45b501d34471c3048fa0507dcbe2922e85c3 (diff) | |
download | libirecovery-4fa49416d47076a026d7d2858dbe2002aaa1537f.tar.gz libirecovery-4fa49416d47076a026d7d2858dbe2002aaa1537f.tar.bz2 |
win32: Implement support for Debug USB (KIS) mode
This requires and up-to-date AppleMobileDeviceSupport64.msi package
installed that contains the AppleKIS driver.
-rw-r--r-- | src/libirecovery.c | 212 |
1 files changed, 151 insertions, 61 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c index f0acce0..9742cb5 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c | |||
@@ -454,6 +454,26 @@ static unsigned int crc32_lookup_t1[256] = { | |||
454 | #define crc32_step(a,b) \ | 454 | #define crc32_step(a,b) \ |
455 | a = (crc32_lookup_t1[(a & 0xFF) ^ ((unsigned char)b)] ^ (a >> 8)) | 455 | a = (crc32_lookup_t1[(a & 0xFF) ^ ((unsigned char)b)] ^ (a >> 8)) |
456 | 456 | ||
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 | ||
457 | #pragma pack(1) | 477 | #pragma pack(1) |
458 | typedef struct { | 478 | typedef struct { |
459 | uint16_t sequence; // A sequence number | 479 | uint16_t sequence; // A sequence number |
@@ -525,6 +545,7 @@ typedef struct { | |||
525 | uint32_t status; | 545 | uint32_t status; |
526 | } KIS_generic_reply; | 546 | } KIS_generic_reply; |
527 | #pragma pack() | 547 | #pragma pack() |
548 | #endif | ||
528 | 549 | ||
529 | static THREAD_T th_event_handler = THREAD_T_NULL; | 550 | static THREAD_T th_event_handler = THREAD_T_NULL; |
530 | struct collection listeners; | 551 | struct collection listeners; |
@@ -873,6 +894,7 @@ static void irecv_copy_nonce_with_tag(irecv_client_t client, const char* tag, un | |||
873 | irecv_copy_nonce_with_tag_from_buffer(tag,nonce,nonce_size,buf); | 894 | irecv_copy_nonce_with_tag_from_buffer(tag,nonce,nonce_size,buf); |
874 | } | 895 | } |
875 | 896 | ||
897 | #ifndef WIN32 | ||
876 | static 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) | 898 | static 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) |
877 | { | 899 | { |
878 | if (argCount > UINT8_MAX) { | 900 | if (argCount > UINT8_MAX) { |
@@ -1001,9 +1023,11 @@ static int irecv_kis_read_string(KIS_device_info *di, size_t off, char *buf, siz | |||
1001 | 1023 | ||
1002 | return len/2; | 1024 | return len/2; |
1003 | } | 1025 | } |
1026 | #endif | ||
1004 | 1027 | ||
1005 | static irecv_error_t irecv_kis_init(irecv_client_t client) | 1028 | static irecv_error_t irecv_kis_init(irecv_client_t client) |
1006 | { | 1029 | { |
1030 | #ifndef WIN32 | ||
1007 | irecv_error_t err = irecv_kis_config_write32(client, KIS_PORTAL_CONFIG, KIS_INDEX_ENABLE_A, KIS_ENABLE_A_VAL); | 1031 | irecv_error_t err = irecv_kis_config_write32(client, KIS_PORTAL_CONFIG, KIS_INDEX_ENABLE_A, KIS_ENABLE_A_VAL); |
1008 | if (err != IRECV_E_SUCCESS) { | 1032 | if (err != IRECV_E_SUCCESS) { |
1009 | debug("Failed to write to KIS_INDEX_ENABLE_A, error %d\n", err); | 1033 | 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) | |||
1015 | debug("Failed to write to KIS_INDEX_ENABLE_B, error %d\n", err); | 1039 | debug("Failed to write to KIS_INDEX_ENABLE_B, error %d\n", err); |
1016 | return err; | 1040 | return err; |
1017 | } | 1041 | } |
1018 | 1042 | #endif | |
1019 | client->isKIS = 1; | 1043 | client->isKIS = 1; |
1020 | 1044 | ||
1021 | return IRECV_E_SUCCESS; | 1045 | return IRECV_E_SUCCESS; |
@@ -1024,7 +1048,23 @@ static irecv_error_t irecv_kis_init(irecv_client_t client) | |||
1024 | static irecv_error_t irecv_kis_load_device_info(irecv_client_t client) | 1048 | static irecv_error_t irecv_kis_load_device_info(irecv_client_t client) |
1025 | { | 1049 | { |
1026 | debug("Loading device info in KIS mode...\n"); | 1050 | 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 | ||
1028 | KIS_req_header req = {}; | 1068 | KIS_req_header req = {}; |
1029 | KIS_device_info di = {}; | 1069 | KIS_device_info di = {}; |
1030 | irecv_error_t err = irecv_kis_request_init(&req, KIS_PORTAL_RSM, KIS_INDEX_GET_INFO, 0, 0, sizeof(di.deviceInfo)/4); | 1070 | 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) | |||
1072 | debug("PID: 0x%04x\n", di.deviceDescriptor.idProduct); | 1112 | debug("PID: 0x%04x\n", di.deviceDescriptor.idProduct); |
1073 | 1113 | ||
1074 | client->mode = di.deviceDescriptor.idProduct; | 1114 | client->mode = di.deviceDescriptor.idProduct; |
1075 | 1115 | #endif | |
1076 | return IRECV_E_SUCCESS; | 1116 | return IRECV_E_SUCCESS; |
1077 | } | 1117 | } |
1078 | 1118 | ||
1079 | #ifdef WIN32 | 1119 | #ifdef WIN32 |
1080 | static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L, 0xD61A, 0x4AF6, {0x9A, 0xB6, 0x11, 0xE5, 0x22, 0x36, 0xC5, 0x76}}; | 1120 | static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L, 0xD61A, 0x4AF6, {0x9A, 0xB6, 0x11, 0xE5, 0x22, 0x36, 0xC5, 0x76}}; |
1081 | static const GUID GUID_DEVINTERFACE_DFU = {0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}}; | 1121 | static 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}}; | ||
1082 | 1123 | ||
1083 | typedef struct usb_control_request { | 1124 | typedef struct usb_control_request { |
1084 | uint8_t bmRequestType; | 1125 | uint8_t bmRequestType; |
@@ -1093,7 +1134,7 @@ typedef struct usb_control_request { | |||
1093 | static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) | 1134 | static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) |
1094 | { | 1135 | { |
1095 | int found = 0; | 1136 | 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 }; |
1097 | irecv_client_t _client = (irecv_client_t) malloc(sizeof(struct irecv_client_private)); | 1138 | irecv_client_t _client = (irecv_client_t) malloc(sizeof(struct irecv_client_private)); |
1098 | memset(_client, 0, sizeof(struct irecv_client_private)); | 1139 | memset(_client, 0, sizeof(struct irecv_client_private)); |
1099 | 1140 | ||
@@ -1117,21 +1158,32 @@ static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) | |||
1117 | } | 1158 | } |
1118 | 1159 | ||
1119 | unsigned int pid = 0; | 1160 | unsigned int pid = 0; |
1120 | if (sscanf(details->DevicePath, "\\\\?\\usb#vid_05ac&pid_%04x", &pid)!= 1) { | 1161 | unsigned int vid = 0; |
1121 | debug("%s: ERROR: failed to parse PID! path: %s\n", __func__, details->DevicePath); | 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); | ||
1122 | free(details); | 1164 | free(details); |
1123 | continue; | 1165 | continue; |
1124 | } | 1166 | } |
1167 | if (vid != APPLE_VENDOR_ID) { | ||
1168 | free(details); | ||
1169 | continue; | ||
1170 | } | ||
1171 | |||
1125 | // make sure the current device is actually in the right mode for the given driver interface | 1172 | // make sure the current device is actually in the right mode for the given driver interface |
1126 | if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE) | 1173 | if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE) |
1127 | || (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4)) | 1174 | || (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) | ||
1128 | ) { | 1176 | ) { |
1129 | free(details); | 1177 | free(details); |
1130 | continue; | 1178 | continue; |
1131 | } | 1179 | } |
1180 | if (guids[k] == &GUID_DEVINTERFACE_KIS) { | ||
1181 | pid = KIS_PRODUCT_ID; | ||
1182 | } | ||
1132 | 1183 | ||
1133 | _client->handle = CreateFileA(details->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); | 1184 | _client->handle = CreateFileA(details->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); |
1134 | if (_client->handle == INVALID_HANDLE_VALUE) { | 1185 | if (_client->handle == INVALID_HANDLE_VALUE) { |
1186 | debug("%s: Failed to open device path %s: %d\n", __func__, details->DevicePath, (int)GetLastError()); | ||
1135 | free(details); | 1187 | free(details); |
1136 | continue; | 1188 | continue; |
1137 | } | 1189 | } |
@@ -1158,34 +1210,35 @@ static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) | |||
1158 | char serial_str[256]; | 1210 | char serial_str[256]; |
1159 | serial_str[0] = '\0'; | 1211 | serial_str[0] = '\0'; |
1160 | 1212 | ||
1161 | char *p = (char*)details->DevicePath; | 1213 | if (_client->mode != KIS_PRODUCT_ID) { |
1162 | while ((p = strstr(p, "\\usb"))) { | 1214 | char *p = (char*)details->DevicePath; |
1163 | if (sscanf(p, "\\usb#vid_05ac&pid_%*04x#%s", serial_str) == 1) | 1215 | while ((p = strstr(p, "\\usb"))) { |
1164 | break; | 1216 | if (sscanf(p, "\\usb#vid_05ac&pid_%*04x#%s", serial_str) == 1) |
1165 | p += 4; | 1217 | break; |
1166 | } | 1218 | p += 4; |
1167 | free(details); | 1219 | } |
1168 | 1220 | free(details); | |
1169 | if (serial_str[0] == '\0') { | ||
1170 | CloseHandle(_client->handle); | ||
1171 | continue; | ||
1172 | } | ||
1173 | 1221 | ||
1174 | p = strchr(serial_str, '#'); | 1222 | if (serial_str[0] == '\0') { |
1175 | if (p) { | 1223 | CloseHandle(_client->handle); |
1176 | *p = '\0'; | 1224 | continue; |
1177 | } | 1225 | } |
1226 | p = strchr(serial_str, '#'); | ||
1227 | if (p) { | ||
1228 | *p = '\0'; | ||
1229 | } | ||
1178 | 1230 | ||
1179 | unsigned int j; | 1231 | unsigned int j; |
1180 | for (j = 0; j < strlen(serial_str); j++) { | 1232 | for (j = 0; j < strlen(serial_str); j++) { |
1181 | if (serial_str[j] == '_') { | 1233 | if (serial_str[j] == '_') { |
1182 | serial_str[j] = ' '; | 1234 | serial_str[j] = ' '; |
1183 | } else { | 1235 | } else { |
1184 | serial_str[j] = toupper(serial_str[j]); | 1236 | serial_str[j] = toupper(serial_str[j]); |
1237 | } | ||
1185 | } | 1238 | } |
1186 | } | ||
1187 | 1239 | ||
1188 | irecv_load_device_info_from_iboot_string(_client, serial_str); | 1240 | irecv_load_device_info_from_iboot_string(_client, serial_str); |
1241 | } | ||
1189 | 1242 | ||
1190 | if (ecid != 0) { | 1243 | if (ecid != 0) { |
1191 | if (_client->device_info.ecid != ecid) { | 1244 | if (_client->device_info.ecid != ecid) { |
@@ -1434,7 +1487,7 @@ int irecv_usb_bulk_transfer(irecv_client_t client, | |||
1434 | #endif | 1487 | #endif |
1435 | #else | 1488 | #else |
1436 | if (endpoint==0x4) { | 1489 | 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); |
1438 | } else { | 1491 | } else { |
1439 | ret = 0; | 1492 | ret = 0; |
1440 | } | 1493 | } |
@@ -2202,40 +2255,51 @@ static void* _irecv_handle_device_add(void *userdata) | |||
2202 | 2255 | ||
2203 | unsigned int pid = 0; | 2256 | unsigned int pid = 0; |
2204 | 2257 | ||
2205 | char *p = result; | 2258 | if (strncmp(result, "\\\\?\\kis#", 8) == 0) { |
2206 | while ((p = strstr(p, "\\usb"))) { | 2259 | pid = KIS_PRODUCT_ID; |
2207 | if (sscanf(p, "\\usb#vid_05ac&pid_%04x#%s", &pid, serial_str) == 2) | 2260 | } else { |
2208 | break; | 2261 | char *p = result; |
2209 | p += 4; | 2262 | while ((p = strstr(p, "\\usb"))) { |
2210 | } | 2263 | if (sscanf(p, "\\usb#vid_05ac&pid_%04x#%s", &pid, serial_str) == 2) |
2211 | 2264 | break; | |
2212 | if (serial_str[0] == '\0') { | 2265 | p += 4; |
2213 | debug("%s: ERROR: failed to parse DevicePath?!\n", __func__); | 2266 | } |
2214 | return NULL; | ||
2215 | } | ||
2216 | |||
2217 | if (!_irecv_is_recovery_device(p)) { | ||
2218 | return NULL; | ||
2219 | } | ||
2220 | 2267 | ||
2221 | p = strchr(serial_str, '#'); | 2268 | if (serial_str[0] == '\0') { |
2222 | if (p) { | 2269 | debug("%s: ERROR: failed to parse DevicePath?!\n", __func__); |
2223 | *p = '\0'; | 2270 | return NULL; |
2224 | } | 2271 | } |
2225 | 2272 | ||
2226 | unsigned int j; | 2273 | if (!_irecv_is_recovery_device(p)) { |
2227 | for (j = 0; j < strlen(serial_str); j++) { | 2274 | return NULL; |
2228 | if (serial_str[j] == '_') { | ||
2229 | serial_str[j] = ' '; | ||
2230 | } else { | ||
2231 | serial_str[j] = toupper(serial_str[j]); | ||
2232 | } | 2275 | } |
2233 | } | 2276 | } |
2277 | |||
2234 | product_id = (uint16_t)pid; | 2278 | product_id = (uint16_t)pid; |
2235 | 2279 | ||
2236 | if (product_id == KIS_PRODUCT_ID) { | 2280 | if (product_id == KIS_PRODUCT_ID) { |
2237 | debug("%s: ERROR: KIS currently not supported with this backend!\n", __func__); | 2281 | client = (irecv_client_t)malloc(sizeof(struct irecv_client_private)); |
2238 | return NULL; | 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 | } | ||
2239 | } | 2303 | } |
2240 | 2304 | ||
2241 | #else /* !WIN32 */ | 2305 | #else /* !WIN32 */ |
@@ -2523,7 +2587,7 @@ static void *_irecv_event_handler(void* data) | |||
2523 | struct _irecv_event_handler_info* info = (struct _irecv_event_handler_info*)data; | 2587 | struct _irecv_event_handler_info* info = (struct _irecv_event_handler_info*)data; |
2524 | #ifdef WIN32 | 2588 | #ifdef WIN32 |
2525 | struct collection newDevices; | 2589 | 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 }; |
2527 | int running = 1; | 2591 | int running = 1; |
2528 | 2592 | ||
2529 | collection_init(&newDevices); | 2593 | collection_init(&newDevices); |
@@ -2606,15 +2670,22 @@ static void *_irecv_event_handler(void* data) | |||
2606 | } ENDFOREACH | 2670 | } ENDFOREACH |
2607 | 2671 | ||
2608 | unsigned int pid = 0; | 2672 | unsigned int pid = 0; |
2609 | if (sscanf(details->DevicePath, "\\\\?\\usb#vid_05ac&pid_%04x", &pid)!= 1) { | 2673 | unsigned int vid = 0; |
2610 | debug("%s: ERROR: failed to parse PID! path: %s\n", __func__, details->DevicePath); | 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); | ||
2611 | free(details); | 2676 | free(details); |
2612 | continue; | 2677 | continue; |
2613 | } | 2678 | } |
2679 | if (vid != APPLE_VENDOR_ID) { | ||
2680 | free(details); | ||
2681 | continue; | ||
2682 | } | ||
2683 | |||
2614 | // make sure the current device is actually in the right mode for the given driver interface | 2684 | // make sure the current device is actually in the right mode for the given driver interface |
2615 | int skip = 0; | 2685 | int skip = 0; |
2616 | if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE) | 2686 | if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE) |
2617 | || (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4)) | 2687 | || (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) | ||
2618 | ) { | 2689 | ) { |
2619 | skip = 1; | 2690 | skip = 1; |
2620 | } | 2691 | } |
@@ -3109,6 +3180,11 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char* | |||
3109 | if (toUpload > 0x4000) | 3180 | if (toUpload > 0x4000) |
3110 | toUpload = 0x4000; | 3181 | toUpload = 0x4000; |
3111 | 3182 | ||
3183 | #ifdef WIN32 | ||
3184 | memcpy(chunk->data, buffer, toUpload); | ||
3185 | chunk->size = toUpload; | ||
3186 | chunk->address = address; | ||
3187 | #else | ||
3112 | irecv_error_t error = irecv_kis_request_init(&chunk->hdr, KIS_PORTAL_RSM, KIS_INDEX_UPLOAD, 3, toUpload, 0); | 3188 | irecv_error_t error = irecv_kis_request_init(&chunk->hdr, KIS_PORTAL_RSM, KIS_INDEX_UPLOAD, 3, toUpload, 0); |
3113 | if (error != IRECV_E_SUCCESS) { | 3189 | if (error != IRECV_E_SUCCESS) { |
3114 | free(chunk); | 3190 | free(chunk); |
@@ -3119,10 +3195,17 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char* | |||
3119 | chunk->address = address; | 3195 | chunk->address = address; |
3120 | chunk->size = toUpload; | 3196 | chunk->size = toUpload; |
3121 | memcpy(chunk->data, buffer, toUpload); | 3197 | memcpy(chunk->data, buffer, toUpload); |
3198 | #endif | ||
3122 | 3199 | ||
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 | ||
3123 | KIS_generic_reply reply; | 3205 | KIS_generic_reply reply; |
3124 | size_t rcvSize = sizeof(reply); | 3206 | size_t rcvSize = sizeof(reply); |
3125 | error = irecv_kis_request(client, &chunk->hdr, sizeof(*chunk) - (0x4000 - toUpload), &reply.hdr, &rcvSize); | 3207 | error = irecv_kis_request(client, &chunk->hdr, sizeof(*chunk) - (0x4000 - toUpload), &reply.hdr, &rcvSize); |
3208 | #endif | ||
3126 | if (error != IRECV_E_SUCCESS) { | 3209 | if (error != IRECV_E_SUCCESS) { |
3127 | free(chunk); | 3210 | free(chunk); |
3128 | debug("Failed to upload chunk, error %d\n", error); | 3211 | 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* | |||
3147 | free(chunk); | 3230 | free(chunk); |
3148 | 3231 | ||
3149 | if (dfu_notify_finished) { | 3232 | 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 | ||
3150 | irecv_error_t error = irecv_kis_config_write32(client, KIS_PORTAL_RSM, KIS_INDEX_BOOT_IMG, origLen); | 3239 | irecv_error_t error = irecv_kis_config_write32(client, KIS_PORTAL_RSM, KIS_INDEX_BOOT_IMG, origLen); |
3240 | #endif | ||
3151 | if (error != IRECV_E_SUCCESS) { | 3241 | if (error != IRECV_E_SUCCESS) { |
3152 | debug("Failed to boot image, error %d\n", error); | 3242 | debug("Failed to boot image, error %d\n", error); |
3153 | return error; | 3243 | return error; |