summaryrefslogtreecommitdiffstats
path: root/src/idevicerestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/idevicerestore.c')
-rw-r--r--src/idevicerestore.c339
1 files changed, 215 insertions, 124 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index aaff4d6..f03e30e 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -38,25 +38,203 @@
#include "recovery.h"
#include "idevicerestore.h"
-#define UNKNOWN_MODE 0
-#define DFU_MODE 1
-#define NORMAL_MODE 2
-#define RECOVERY_MODE 3
-#define RESTORE_MODE 4
-
+int idevicerestore_quit = 0;
int idevicerestore_debug = 0;
-static int idevicerestore_mode = 0;
-static int idevicerestore_quit = 0;
-static int idevicerestore_custom = 0;
+int idevicerestore_custom = 0;
+int idevicerestore_verbose = 0;
+idevicerestore_mode_t idevicerestore_mode = UNKNOWN_MODE;
+idevicerestore_device_t idevicerestore_device = UNKNOWN_DEVICE;
void usage(int argc, char* argv[]);
+int get_device(const char* uuid);
+idevicerestore_mode_t check_mode(const char* uuid);
+int get_ecid(const char* uuid, uint64_t* ecid);
+int get_bdid(const char* uuid, uint32_t* bdid);
+int get_cpid(const char* uuid, uint32_t* cpid);
int write_file(const char* filename, char* data, int size);
+int extract_buildmanifest(const char* ipsw, plist_t* buildmanifest);
int get_tss_data_by_name(plist_t tss, const char* entry, char** path, char** blob);
int get_tss_data_by_path(plist_t tss, const char* path, char** name, char** blob);
void device_callback(const idevice_event_t* event, void *user_data);
int get_signed_component_by_name(char* ipsw, plist_t tss, char* component, char** pdata, int* psize);
int get_signed_component_by_path(char* ipsw, plist_t tss, char* path, char** pdata, int* psize);
+idevicerestore_mode_t check_mode(const char* uuid) {
+ if(normal_check_mode(uuid) == 0) {
+ info("Found device in normal mode\n");
+ idevicerestore_mode = NORMAL_MODE;
+ }
+
+ else if(recovery_check_mode() == 0) {
+ info("Found device in recovery mode\n");
+ idevicerestore_mode = RECOVERY_MODE;
+ }
+
+ else if(dfu_check_mode() == 0) {
+ info("Found device in DFU mode\n");
+ idevicerestore_mode = DFU_MODE;
+ }
+
+ else if(restore_check_mode(uuid) == 0) {
+ info("Found device in restore mode\n");
+ idevicerestore_mode = RESTORE_MODE;
+ }
+
+ return idevicerestore_mode;
+}
+
+int get_device(const char* uuid) {
+ uint32_t bdid = 0;
+ uint32_t cpid = 0;
+
+ if(get_cpid(uuid, &cpid) < 0) {
+ error("ERROR: Unable to get device CPID\n");
+ return -1;
+ }
+
+ switch(cpid) {
+ case IPHONE2G_CPID:
+ // iPhone1,1 iPhone1,2 and iPod1,1 all share the same ChipID
+ // so we need to check the BoardID
+ if(get_bdid(uuid, &bdid) < 0) {
+ error("ERROR: Unable to get device BDID\n");
+ return -1;
+ }
+
+ switch(bdid) {
+ case IPHONE2G_BDID:
+ idevicerestore_device = IPHONE2G_DEVICE;
+ break;
+
+ case IPHONE3G_BDID:
+ idevicerestore_device = IPHONE3G_DEVICE;
+ break;
+
+ case IPOD1G_BDID:
+ idevicerestore_device = IPOD1G_DEVICE;
+ break;
+
+ default:
+ idevicerestore_device = UNKNOWN_DEVICE;
+ break;
+ }
+ break;
+
+ case IPHONE3GS_CPID:
+ idevicerestore_device = IPHONE3GS_DEVICE;
+ break;
+
+ case IPOD2G_CPID:
+ idevicerestore_device = IPOD2G_DEVICE;
+ break;
+
+ case IPOD3G_CPID:
+ idevicerestore_device = IPOD3G_DEVICE;
+ break;
+
+ case IPAD1G_CPID:
+ idevicerestore_device = IPAD1G_DEVICE;
+ break;
+
+ default:
+ idevicerestore_device = UNKNOWN_DEVICE;
+ break;
+ }
+
+ return idevicerestore_device;
+}
+
+int get_bdid(const char* uuid, uint32_t* bdid) {
+ switch(idevicerestore_mode) {
+ case NORMAL_MODE:
+ if(normal_get_bdid(uuid, bdid) < 0) {
+ *bdid = -1;
+ return -1;
+ }
+ break;
+
+ case RECOVERY_MODE:
+ if(recovery_get_bdid(bdid) < 0) {
+ *bdid = -1;
+ return -1;
+ }
+ break;
+
+ case DFU_MODE:
+ if(dfu_get_bdid(bdid) < 0) {
+ *bdid = -1;
+ return -1;
+ }
+ break;
+
+ default:
+ error("ERROR: Device is in an invalid state\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int get_cpid(const char* uuid, uint32_t* cpid) {
+ switch(idevicerestore_mode) {
+ case NORMAL_MODE:
+ if(normal_get_cpid(uuid, cpid) < 0) {
+ *cpid = -1;
+ return -1;
+ }
+ break;
+
+ case RECOVERY_MODE:
+ if(recovery_get_cpid(cpid) < 0) {
+ *cpid = -1;
+ return -1;
+ }
+ break;
+
+ case DFU_MODE:
+ if(dfu_get_cpid(cpid) < 0) {
+ *cpid = -1;
+ return -1;
+ }
+ break;
+
+ default:
+ error("ERROR: Device is in an invalid state\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int get_ecid(const char* uuid, uint64_t* ecid) {
+ if(normal_get_ecid(uuid, ecid) == 0) {
+ info("Found device in normal mode\n");
+ idevicerestore_mode = NORMAL_MODE;
+ }
+
+ else if(recovery_get_ecid(ecid) == 0) {
+ info("Found device in recovery mode\n");
+ idevicerestore_mode = RECOVERY_MODE;
+ }
+
+ else if(dfu_get_ecid(ecid) == 0) {
+ info("Found device in DFU mode\n");
+ idevicerestore_mode = DFU_MODE;
+ }
+
+ return idevicerestore_mode;
+}
+
+int extract_buildmanifest(const char* ipsw, plist_t* buildmanifest) {
+ int size = 0;
+ char* data = NULL;
+ if (ipsw_extract_to_memory(ipsw, "BuildManifest.plist", &data, &size) < 0) {
+ return -1;
+ }
+ plist_from_xml(data, size, buildmanifest);
+ return 0;
+}
+
int main(int argc, char* argv[]) {
int opt = 0;
char* ipsw = NULL;
@@ -68,16 +246,16 @@ int main(int argc, char* argv[]) {
usage(argc, argv);
break;
- case 'v':
- idevicerestore_debug += 1;
+ case 'd':
+ idevicerestore_debug = 1;
break;
case 'c':
idevicerestore_custom = 1;
break;
- case 'd':
- idevicerestore_debug = 3;
+ case 'v':
+ idevicerestore_verbose = 1;
break;
case 'u':
@@ -86,7 +264,7 @@ int main(int argc, char* argv[]) {
default:
usage(argc, argv);
- break;
+ return -1;
}
}
@@ -97,105 +275,40 @@ int main(int argc, char* argv[]) {
ipsw = argv[0];
if (ipsw == NULL) {
+ usage(argc, argv);
error("ERROR: Please supply an IPSW\n");
return -1;
}
- 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 = LOCKDOWN_E_SUCCESS;
-
- /* determine recovery or normal mode */
- info("Checking for device in normal mode...\n");
- device_error = idevice_new(&device, uuid);
- if (device_error != IDEVICE_E_SUCCESS) {
- info("Checking for the device in recovery mode...\n");
- recovery_error = irecv_open(&recovery);
- if (recovery_error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to find device, is it plugged in?\n");
- return -1;
- }
- info("Found device in recovery mode\n");
- idevicerestore_mode = RECOVERY_MODE;
-
- } else {
- info("Found device in normal mode\n");
- idevicerestore_mode = NORMAL_MODE;
- }
-
- /* retrieve ECID */
- if (idevicerestore_mode == NORMAL_MODE) {
- lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
- if (lockdown_error != LOCKDOWN_E_SUCCESS) {
- error("ERROR: Unable to connect to lockdownd\n");
- idevice_free(device);
- return -1;
- }
-
- plist_t unique_chip_node = NULL;
- lockdown_error = lockdownd_get_value(lockdown, NULL, "UniqueChipID", &unique_chip_node);
- if (lockdown_error != LOCKDOWN_E_SUCCESS) {
- error("ERROR: Unable to get UniqueChipID from lockdownd\n");
- lockdownd_client_free(lockdown);
- idevice_free(device);
- return -1;
- }
-
- if (!unique_chip_node || plist_get_node_type(unique_chip_node) != PLIST_UINT) {
- error("ERROR: Unable to get ECID\n");
- lockdownd_client_free(lockdown);
- idevice_free(device);
- return -1;
- }
-
- plist_get_uint_val(unique_chip_node, &ecid);
- lockdownd_client_free(lockdown);
- plist_free(unique_chip_node);
- idevice_free(device);
- lockdown = NULL;
- device = NULL;
-
- } else if (idevicerestore_mode == RECOVERY_MODE) {
- recovery_error = irecv_get_ecid(recovery, &ecid);
- if (recovery_error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to get device ECID\n");
- irecv_close(recovery);
- return -1;
- }
- irecv_close(recovery);
- recovery = NULL;
+ /* discover the device type */
+ if(get_device(uuid) < 0) {
+ error("ERROR: Unable to find device type\n");
+ return -1;
}
- if (ecid != 0) {
- info("Found ECID %llu\n", ecid);
- } else {
- error("Unable to find device ECID\n");
+ /* get the device ECID and determine mode */
+ if(get_ecid(uuid, &ecid) < 0 || ecid == 0) {
+ error("ERROR: Unable to find device ECID\n");
return -1;
}
+ info("Found ECID %llu\n", ecid);
- /* parse buildmanifest */
- int buildmanifest_size = 0;
- char* buildmanifest_data = NULL;
+ /* extract buildmanifest */
+ plist_t buildmanifest = NULL;
info("Extracting BuildManifest.plist from IPSW\n");
- if (ipsw_extract_to_memory(ipsw, "BuildManifest.plist", &buildmanifest_data, &buildmanifest_size) < 0) {
- error("ERROR: Unable to extract BuildManifest.plist IPSW\n");
+ if(extract_buildmanifest(ipsw, &buildmanifest) < 0) {
+ error("ERROR: Unable to extract BuildManifest from %s\n", ipsw);
return -1;
}
- plist_t manifest = NULL;
- plist_from_xml(buildmanifest_data, buildmanifest_size, &manifest);
-
info("Creating TSS request\n");
- plist_t tss_request = tss_create_request(manifest, ecid);
+ plist_t tss_request = tss_create_request(buildmanifest, ecid);
if (tss_request == NULL) {
error("ERROR: Unable to create TSS request\n");
- plist_free(manifest);
+ plist_free(buildmanifest);
return -1;
}
- plist_free(manifest);
+ plist_free(buildmanifest);
info("Sending TSS request\n");
plist_t tss_response = tss_send_request(tss_request);
@@ -240,34 +353,12 @@ int main(int argc, char* argv[]) {
/* place device into recovery mode if required */
if (idevicerestore_mode == NORMAL_MODE) {
info("Entering recovery mode...\n");
- device_error = idevice_new(&device, uuid);
- if (device_error != IDEVICE_E_SUCCESS) {
- error("ERROR: Unable to find device\n");
- plist_free(tss_response);
- return -1;
- }
-
- lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
- if (lockdown_error != LOCKDOWN_E_SUCCESS) {
- error("ERROR: Unable to connect to lockdownd service\n");
- plist_free(tss_response);
- idevice_free(device);
- return -1;
- }
-
- lockdown_error = lockdownd_enter_recovery(lockdown);
- if (lockdown_error != LOCKDOWN_E_SUCCESS) {
- error("ERROR: Unable to place device in recovery mode\n");
- lockdownd_client_free(lockdown);
+ if(normal_enter_recovery(uuid) < 0) {
+ error("ERROR: Unable to place device into recovery mode\n");
plist_free(tss_response);
- idevice_free(device);
return -1;
}
- lockdownd_client_free(lockdown);
- idevice_free(device);
- lockdown = NULL;
- device = NULL;
}
/* upload data to make device boot restore mode */
@@ -315,7 +406,8 @@ int main(int argc, char* argv[]) {
sleep(1);
}
- device_error = idevice_new(&device, uuid);
+ idevice_t device = NULL;
+ 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);
@@ -364,7 +456,7 @@ int main(int argc, char* argv[]) {
char *datatype = NULL;
plist_get_string_val(datatype_node, &datatype);
if (!strcmp(datatype, "SystemImageData")) {
- asr_send_system_image_data_from_file(device, restore, filesystem);
+ restore_send_filesystem(device, restore, filesystem);
} else if (!strcmp(datatype, "KernelCache")) {
int kernelcache_size = 0;
@@ -377,7 +469,7 @@ int main(int argc, char* argv[]) {
free(kernelcache_data);
} else if (!strcmp(datatype, "NORData")) {
- restore_send_nor_data(restore, ipsw, tss_response);
+ restore_send_nor(restore, ipsw, tss_response);
} else {
// Unknown DataType!!
@@ -428,9 +520,8 @@ void usage(int argc, char* argv[]) {
printf(" -u, \t\ttarget specific device by its 40-digit device UUID\n");
printf(" -h, \t\tprints usage information\n");
printf(" -c, \t\trestore with a custom firmware\n");
- printf(" -v, \t\tenable incremental levels of verboseness\n");
+ printf(" -v, \t\tenable verbose output\n");
printf("\n");
- exit(1);
}
int write_file(const char* filename, char* data, int size) {