summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/idevicerestore.c84
-rw-r--r--src/normal.c30
-rw-r--r--src/recovery.c41
-rw-r--r--src/recovery.h1
-rw-r--r--src/tss.c1
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);
diff --git a/src/tss.c b/src/tss.c
index f36bc5f..a9e9456 100644
--- a/src/tss.c
+++ b/src/tss.c
@@ -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;