diff options
-rw-r--r-- | src/idevicerestore.c | 84 | ||||
-rw-r--r-- | src/normal.c | 30 | ||||
-rw-r--r-- | src/recovery.c | 41 | ||||
-rw-r--r-- | src/recovery.h | 1 | ||||
-rw-r--r-- | src/tss.c | 1 |
5 files changed, 101 insertions, 56 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c index cc9c4ba..7d382eb 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -94,7 +94,8 @@ int get_device(const char* uuid) { switch (idevicerestore_mode) { case NORMAL_MODE: - if (normal_get_device(uuid) < 0) { + device = normal_get_device(uuid); + if (device < 0) { device = UNKNOWN_DEVICE; } break; @@ -282,6 +283,7 @@ int extract_buildmanifest(const char* ipsw, plist_t* buildmanifest) { } plist_t get_build_identity(plist_t buildmanifest, uint32_t identity) { + // fetch build identities array from BuildManifest plist_t build_identities_array = plist_dict_get_item(buildmanifest, "BuildIdentities"); if (!build_identities_array || plist_get_node_type(build_identities_array) != PLIST_ARRAY) { @@ -300,19 +302,25 @@ plist_t get_build_identity(plist_t buildmanifest, uint32_t identity) { return NULL; } - return build_identity; + return plist_copy(build_identity); } int extract_filesystem(const char* ipsw, plist_t build_identity, char** filesystem) { char* filename = NULL; - plist_t manifest_node = plist_dict_get_item(build_identity, "OS"); + int sz = 0; + char* xml = NULL; + plist_to_xml(build_identity, &xml, &sz); + debug("%s", xml); + free(xml); + + plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest"); if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { error("ERROR: Unable to find manifest node\n"); return -1; } - plist_t filesystem_node = plist_dict_get_item(build_identity, "OS"); + plist_t filesystem_node = plist_dict_get_item(manifest_node, "OS"); if (!filesystem_node || plist_get_node_type(filesystem_node) != PLIST_DICT) { error("ERROR: Unable to find filesystem node\n"); return -1; @@ -438,7 +446,7 @@ int main(int argc, char* argv[]) { // devices are listed in order from oldest to newest // devices that come after iPod2g require personalized firmwares plist_t tss_request = NULL; - plist_t tss_response = NULL; + plist_t tss = NULL; if(idevicerestore_device > IPOD2G_DEVICE) { info("Creating TSS request\n"); @@ -455,11 +463,10 @@ int main(int argc, char* argv[]) { plist_free(buildmanifest); return -1; } - plist_free(buildmanifest); info("Sending TSS request\n"); - tss_response = tss_send_request(tss_request); - if (tss_response == NULL) { + tss = tss_send_request(tss_request); + if (tss == NULL) { error("ERROR: Unable to get response from TSS server\n"); plist_free(tss_request); return -1; @@ -472,7 +479,7 @@ int main(int argc, char* argv[]) { char* filesystem = NULL; if(extract_filesystem(ipsw, build_identity, &filesystem) < 0) { error("ERROR: Unable to extract filesystem from IPSW\n"); - if(tss_response) plist_free(tss_response); + if(tss) plist_free(tss); plist_free(buildmanifest); return -1; } @@ -482,47 +489,20 @@ int main(int argc, char* argv[]) { info("Entering recovery mode...\n"); if (normal_enter_recovery(uuid) < 0) { error("ERROR: Unable to place device into recovery mode\n"); - plist_free(tss_response); + if(tss) plist_free(tss); + plist_free(buildmanifest); return -1; } } - /* upload data to make device boot restore mode */ - if (recovery_send_ibec(ipsw, tss_response) < 0) { - error("ERROR: Unable to send iBEC\n"); - plist_free(tss_response); - return -1; - } - sleep(1); - - if (recovery_send_applelogo(ipsw, tss_response) < 0) { - error("ERROR: Unable to send AppleLogo\n"); - plist_free(tss_response); - return -1; - } - - if (recovery_send_devicetree(ipsw, tss_response) < 0) { - error("ERROR: Unable to send DeviceTree\n"); - plist_free(tss_response); - return -1; - } - - if (recovery_send_ramdisk(ipsw, tss_response) < 0) { - error("ERROR: Unable to send Ramdisk\n"); - plist_free(tss_response); - return -1; - } - - // for some reason iboot requires a hard reset after ramdisk - // or things start getting wacky - printf("Please unplug your device, then plug it back in\n"); - printf("Hit any key to continue..."); - getchar(); - - if (recovery_send_kernelcache(ipsw, tss_response) < 0) { - error("ERROR: Unable to send KernelCache\n"); - plist_free(tss_response); - return -1; + // place device into restore mode if required + if (idevicerestore_mode == RECOVERY_MODE) { + if (recovery_enter_restore(ipsw, tss) < 0) { + error("ERROR: Unable to place device into restore mode\n"); + if(tss) plist_free(tss); + plist_free(buildmanifest); + return -1; + } } idevice_event_subscribe(&device_callback, NULL); @@ -536,7 +516,7 @@ int main(int argc, char* argv[]) { idevice_error_t device_error = idevice_new(&device, uuid); if (device_error != IDEVICE_E_SUCCESS) { error("ERROR: Unable to open device\n"); - plist_free(tss_response); + plist_free(tss); return -1; } @@ -544,7 +524,7 @@ int main(int argc, char* argv[]) { restored_error_t restore_error = restored_client_new(device, &restore, "idevicerestore"); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to start restored client\n"); - plist_free(tss_response); + plist_free(tss); idevice_free(device); return -1; } @@ -553,7 +533,7 @@ int main(int argc, char* argv[]) { uint64_t version = 0; if (restored_query_type(restore, &type, &version) != RESTORE_E_SUCCESS) { error("ERROR: Device is not in restore mode. QueryType returned \"%s\"\n", type); - plist_free(tss_response); + plist_free(tss); restored_client_free(restore); idevice_free(device); return -1; @@ -587,7 +567,7 @@ int main(int argc, char* argv[]) { } else if (!strcmp(datatype, "KernelCache")) { int kernelcache_size = 0; char* kernelcache_data = NULL; - if (get_signed_component_by_name(ipsw, tss_response, "KernelCache", &kernelcache_data, &kernelcache_size) < 0) { + if (get_signed_component_by_name(ipsw, tss, "KernelCache", &kernelcache_data, &kernelcache_size) < 0) { error("ERROR: Unable to get kernelcache file\n"); return -1; } @@ -595,7 +575,7 @@ int main(int argc, char* argv[]) { free(kernelcache_data); } else if (!strcmp(datatype, "NORData")) { - restore_send_nor(restore, ipsw, tss_response); + restore_send_nor(restore, ipsw, tss); } else { // Unknown DataType!! @@ -624,7 +604,7 @@ int main(int argc, char* argv[]) { } restored_client_free(restore); - plist_free(tss_response); + plist_free(tss); idevice_free(device); unlink(filesystem); return 0; diff --git a/src/normal.c b/src/normal.c index 0420a82..3c2bf5c 100644 --- a/src/normal.c +++ b/src/normal.c @@ -21,10 +21,12 @@ #include <stdio.h> #include <stdint.h> +#include <libirecovery.h> #include <libimobiledevice/lockdown.h> #include <libimobiledevice/libimobiledevice.h> #include "normal.h" +#include "recovery.h" #include "idevicerestore.h" int normal_check_mode(const char* uuid) { @@ -112,9 +114,11 @@ int normal_get_device(const char* uuid) { int normal_enter_recovery(const char* uuid) { idevice_t device = NULL; + irecv_client_t recovery = NULL; lockdownd_client_t lockdown = NULL; + irecv_error_t recovery_error = IRECV_E_SUCCESS; idevice_error_t device_error = IDEVICE_E_SUCCESS; - lockdownd_error_t lockdown_error = IDEVICE_E_SUCCESS; + lockdownd_error_t lockdown_error = LOCKDOWN_E_SUCCESS; device_error = idevice_new(&device, uuid); if (device_error != IDEVICE_E_SUCCESS) { @@ -141,6 +145,29 @@ int normal_enter_recovery(const char* uuid) { idevice_free(device); lockdown = NULL; device = NULL; + + if(recovery_open_with_timeout(&recovery) < 0) { + error("ERROR: Unable to enter recovery mode\n"); + return -1; + } + + recovery_error = irecv_send_command(recovery, "setenv auto-boot true"); + if (recovery_error != IRECV_E_SUCCESS) { + error("ERROR: Unable to reset auto-boot variable\n"); + irecv_close(recovery); + return -1; + } + + recovery_error = irecv_send_command(recovery, "saveenv"); + if (recovery_error != IRECV_E_SUCCESS) { + error("ERROR: Unable to save auto-boot variable\n"); + irecv_close(recovery); + return -1; + } + + idevicerestore_mode = RECOVERY_MODE; + irecv_close(recovery); + recovery = NULL; return 0; } @@ -192,4 +219,5 @@ int normal_get_ecid(const char* uuid, uint64_t* ecid) { idevice_free(device); lockdown = NULL; device = NULL; + return 0; } diff --git a/src/recovery.c b/src/recovery.c index 9885982..3bfb97e 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -48,6 +48,43 @@ int recovery_check_mode() { return 0; } +int recovery_enter_restore(const char* ipsw, plist_t tss) { + // upload data to make device boot restore mode + if (recovery_send_ibec(ipsw, tss) < 0) { + error("ERROR: Unable to send iBEC\n"); + return -1; + } + sleep(1); + + if (recovery_send_applelogo(ipsw, tss) < 0) { + error("ERROR: Unable to send AppleLogo\n"); + return -1; + } + + if (recovery_send_devicetree(ipsw, tss) < 0) { + error("ERROR: Unable to send DeviceTree\n"); + return -1; + } + + if (recovery_send_ramdisk(ipsw, tss) < 0) { + error("ERROR: Unable to send Ramdisk\n"); + return -1; + } + + // for some reason iboot requires a hard reset after ramdisk + // or things start getting wacky + printf("Please unplug your device, then plug it back in\n"); + printf("Hit any key to continue..."); + getchar(); + + if (recovery_send_kernelcache(ipsw, tss) < 0) { + error("ERROR: Unable to send KernelCache\n"); + return -1; + } + + return 0; +} + int recovery_send_signed_component(irecv_client_t client, const char* ipsw, plist_t tss, char* component) { int size = 0; char* data = NULL; @@ -306,7 +343,7 @@ int recovery_get_cpid(uint32_t* cpid) { return -1; } - irecv_error_t error = irecv_get_ecid(recovery, cpid); + irecv_error_t error = irecv_get_cpid(recovery, cpid); if (error != IRECV_E_SUCCESS) { irecv_close(recovery); return -1; @@ -323,7 +360,7 @@ int recovery_get_bdid(uint32_t* bdid) { return -1; } - irecv_error_t error = irecv_get_ecid(recovery, bdid); + irecv_error_t error = irecv_get_bdid(recovery, bdid); if (error != IRECV_E_SUCCESS) { irecv_close(recovery); return -1; diff --git a/src/recovery.h b/src/recovery.h index 86e3af2..b191aa5 100644 --- a/src/recovery.h +++ b/src/recovery.h @@ -26,6 +26,7 @@ #include <plist/plist.h> int recovery_check_mode(); +int recovery_enter_restore(const char* ipsw, plist_t tss); int recovery_send_signed_component(irecv_client_t client, const char* ipsw, plist_t tss, char* component); irecv_error_t recovery_open_with_timeout(irecv_client_t* client); int recovery_send_ibec(const char* ipsw, plist_t tss); @@ -124,7 +124,6 @@ plist_t tss_create_request(plist_t build_identity, uint64_t ecid) { plist_dict_insert_item(tss_request, key, tss_entry); free(key); } - plist_free(manifest_node); int sz = 0; char* xml = NULL; |