diff options
Diffstat (limited to 'src/idevicerestore.c')
-rw-r--r-- | src/idevicerestore.c | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 93c6766..4efc0d4 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -217,6 +217,75 @@ int main(int argc, char* argv[]) { } info("Found device in %s mode\n", client->mode->string); + if (client->mode->index == MODE_WTF) { + int cpid = 0; + + if (dfu_client_new(client) != 0) { + error("ERROR: Could not open device in WTF mode\n"); + return -1; + } + if ((dfu_get_cpid(client, &cpid) < 0) || (cpid == 0)) { + error("ERROR: Could not get CPID for WTF mode device\n"); + dfu_client_free(client); + return -1; + } + + char* s_wtfurl = NULL; + plist_t wtfurl = plist_access_path(client->version_data, 7, "MobileDeviceSoftwareVersionsByVersion", "5", "RecoverySoftwareVersions", "WTF", "304218112", "5", "FirmwareURL"); + if (wtfurl && (plist_get_node_type(wtfurl) == PLIST_STRING)) { + plist_get_string_val(wtfurl, &s_wtfurl); + } + if (!s_wtfurl) { + info("Using hardcoded x12220000_5_Recovery.ipsw URL\n"); + s_wtfurl = strdup("http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPhone/061-6618.20090617.Xse7Y/x12220000_5_Recovery.ipsw"); + } + + // make a local file name + char* fnpart = strrchr(s_wtfurl, '/'); + if (!fnpart) { + fnpart = "x12220000_5_Recovery.ipsw"; + } else { + fnpart++; + } + struct stat fst; + char wtfipsw[256]; + sprintf(wtfipsw, "cache/%s", fnpart); + if (stat(wtfipsw, &fst) != 0) { + __mkdir("cache", 0755); + download_to_file(s_wtfurl, wtfipsw); + } + + char wtfname[256]; + sprintf(wtfname, "Firmware/dfu/WTF.s5l%04dxall.RELEASE.dfu", cpid); + char* wtftmp = NULL; + uint32_t wtfsize = 0; + ipsw_extract_to_memory(wtfipsw, wtfname, &wtftmp, &wtfsize); + if (!wtftmp) { + error("ERROR: Could not extract WTF\n"); + } + + char xbuf[16] = {0xff, 0xff, 0xff, 0xff, 0xac, 0x05, 0x00, 0x01, 0x55, 0x46, 0x44, 0x10, 0xcb, 0x55, 0xa4, 0x05}; + char *wtfbuf = (char*)malloc(wtfsize + 16); + if (!wtfbuf) { + error("ERROR: Out of Memory\n"); + return -1; + } + memcpy(wtfbuf, wtftmp, wtfsize); + free(wtftmp); + memcpy(wtfbuf+wtfsize, xbuf, 16); + wtfsize += 16; + + if (dfu_send_buffer(client, wtfbuf, wtfsize) != 0) { + error("ERROR: Could not send WTF...\n"); + } + dfu_client_free(client); + + sleep(1); + + free(wtfbuf); + client->mode = &idevicerestore_modes[MODE_DFU]; + } + // discover the device type if (check_device(client) < 0 || client->device->index == DEVICE_UNKNOWN) { error("ERROR: Unable to discover device type\n"); @@ -657,13 +726,14 @@ int main(int argc, char* argv[]) { int check_mode(struct idevicerestore_client_t* client) { int mode = MODE_UNKNOWN; + int dfumode = MODE_UNKNOWN; if (recovery_check_mode() == 0) { mode = MODE_RECOVERY; } - else if (dfu_check_mode() == 0) { - mode = MODE_DFU; + else if (dfu_check_mode(&dfumode) == 0) { + mode = dfumode; } else if (normal_check_mode(client->uuid) == 0) { |