summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dfu.c28
-rw-r--r--src/dfu.h7
-rw-r--r--src/idevicerestore.c339
-rw-r--r--src/idevicerestore.h55
-rw-r--r--src/img3.h4
-rw-r--r--src/ipsw.h4
-rw-r--r--src/normal.c169
-rw-r--r--src/normal.h11
-rw-r--r--src/recovery.c78
-rw-r--r--src/recovery.h19
-rw-r--r--src/restore.c43
-rw-r--r--src/restore.h9
-rw-r--r--src/tss.h4
13 files changed, 609 insertions, 161 deletions
diff --git a/src/dfu.c b/src/dfu.c
index 5e13f38..1da895d 100644
--- a/src/dfu.c
+++ b/src/dfu.c
@@ -20,9 +20,37 @@
*/
#include <stdint.h>
+#include <libirecovery.h>
#include "dfu.h"
+int dfu_check_mode() {
+ irecv_client_t dfu = NULL;
+ irecv_error_t dfu_error = IRECV_E_SUCCESS;
+
+ dfu_error = irecv_open(&dfu);
+ if (dfu_error != IRECV_E_SUCCESS) {
+ return -1;
+ }
+
+ if(dfu->mode != kDfuMode) {
+ irecv_close(dfu);
+ return -1;
+ }
+
+ irecv_close(dfu);
+ dfu = NULL;
+ return 0;
+}
+
+int dfu_get_cpid(uint32_t* cpid) {
+ return 0;
+}
+
+int dfu_get_bdid(uint32_t* bdid) {
+ return 0;
+}
+
int dfu_get_ecid(uint64_t* ecid) {
return 0;
}
diff --git a/src/dfu.h b/src/dfu.h
index ef9d911..f8f34fc 100644
--- a/src/dfu.h
+++ b/src/dfu.h
@@ -19,11 +19,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef DFU_H
-#define DFU_H
+#ifndef IDEVICERESTORE_DFU_H
+#define IDEVICERESTORE_DFU_H
#include <stdint.h>
+int dfu_check_mode();
+int dfu_get_cpid(uint32_t* cpid);
+int dfu_get_bdid(uint32_t* bdid);
int dfu_get_ecid(uint64_t* ecid);
#endif
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) {
diff --git a/src/idevicerestore.h b/src/idevicerestore.h
index 3dcf1d5..f1861e9 100644
--- a/src/idevicerestore.h
+++ b/src/idevicerestore.h
@@ -22,10 +22,61 @@
#ifndef IDEVICERESTORE_H
#define IDEVICERESTORE_H
+#define info(...) printf(__VA_ARGS__)
#define error(...) fprintf(stderr, __VA_ARGS__)
-#define info(...) if(idevicerestore_debug >= 1) fprintf(stderr, __VA_ARGS__)
-#define debug(...) if(idevicerestore_debug >= 2) fprintf(stderr, __VA_ARGS__)
+#define debug(...) if(idevicerestore_debug >= 1) fprintf(stderr, __VA_ARGS__)
+#define IPHONE2G_CPID 8900
+#define IPHONE3G_CPID 8900
+#define IPHONE3GS_CPID 8920
+#define IPOD1G_CPID 8900
+#define IPOD2G_CPID 8720
+#define IPOD3G_CPID 8922
+#define IPAD1G_CPID 8930
+
+#define IPHONE2G_BDID 0
+#define IPHONE3G_BDID 4
+#define IPHONE3GS_BDID 0
+#define IPOD1G_BDID 2
+#define IPOD2G_BDID 0
+#define IPOD3G_BDID 2
+#define IPAD1G_BDID 2
+
+typedef enum {
+ UNKNOWN_MODE = -1,
+ DFU_MODE = 0,
+ NORMAL_MODE = 1,
+ RECOVERY_MODE = 2,
+ RESTORE_MODE = 3
+} idevicerestore_mode_t;
+
+typedef enum {
+ UNKNOWN_DEVICE = -1,
+ IPHONE2G_DEVICE = 0,
+ IPHONE3G_DEVICE = 1,
+ IPHONE3GS_DEVICE = 2,
+ IPOD1G_DEVICE = 3,
+ IPOD2G_DEVICE = 4,
+ IPOD3G_DEVICE = 5,
+ IPAD1G_DEVICE = 6
+} idevicerestore_device_t;
+
+static char* idevicerestore_products[] = {
+ "iPhone1,1",
+ "iPhone1,2",
+ "iPhone2,1",
+ "iPod1,1",
+ "iPod2,1",
+ "iPod3,1",
+ "iPad1,1",
+ NULL
+};
+
+extern int idevicerestore_quit;
extern int idevicerestore_debug;
+extern int idevicerestore_custom;
+extern int idevicerestore_verbose;
+extern idevicerestore_mode_t idevicerestore_mode;
+extern idevicerestore_device_t idevicerestore_device;
#endif
diff --git a/src/img3.h b/src/img3.h
index a19ae99..c172455 100644
--- a/src/img3.h
+++ b/src/img3.h
@@ -19,8 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef IMG3_H
-#define IMG3_H
+#ifndef IDEVICERESTORE_IMG3_H
+#define IDEVICERESTORE_IMG3_H
typedef enum {
kNorContainer = 0x696D6733, // img3
diff --git a/src/ipsw.h b/src/ipsw.h
index f764611..20f6bf5 100644
--- a/src/ipsw.h
+++ b/src/ipsw.h
@@ -19,8 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef IPSW_H
-#define IPSW_H
+#ifndef IDEVICERESTORE_IPSW_H
+#define IDEVICERESTORE_IPSW_H
#include <zip.h>
diff --git a/src/normal.c b/src/normal.c
index c7baefd..0420a82 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -19,10 +19,177 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <stdio.h>
#include <stdint.h>
+#include <libimobiledevice/lockdown.h>
+#include <libimobiledevice/libimobiledevice.h>
#include "normal.h"
+#include "idevicerestore.h"
-int normal_get_ecid(uint64_t* ecid) {
+int normal_check_mode(const char* uuid) {
+ char* type = NULL;
+ idevice_t device = NULL;
+ lockdownd_client_t lockdown = NULL;
+ idevice_error_t device_error = IDEVICE_E_SUCCESS;
+ lockdownd_error_t lockdown_error = IDEVICE_E_SUCCESS;
+
+ device_error = idevice_new(&device, uuid);
+ if (device_error != IDEVICE_E_SUCCESS) {
+ return -1;
+ }
+
+ lockdown_error = lockdownd_client_new(device, &lockdown, "idevicerestore");
+ if (lockdown_error != LOCKDOWN_E_SUCCESS) {
+ idevice_free(device);
+ return -1;
+ }
+
+ lockdown_error = lockdownd_query_type(lockdown, &type);
+ if (lockdown_error != LOCKDOWN_E_SUCCESS) {
+ lockdownd_client_free(lockdown);
+ idevice_free(device);
+ return -1;
+ }
+
+ lockdownd_client_free(lockdown);
+ idevice_free(device);
+ lockdown = NULL;
+ device = NULL;
return 0;
}
+
+int normal_get_device(const char* uuid) {
+ idevice_t device = NULL;
+ char* product_type = NULL;
+ plist_t product_type_node = NULL;
+ lockdownd_client_t lockdown = NULL;
+ idevice_error_t device_error = IDEVICE_E_SUCCESS;
+ lockdownd_error_t lockdown_error = IDEVICE_E_SUCCESS;
+
+ device_error = idevice_new(&device, uuid);
+ if (device_error != IDEVICE_E_SUCCESS) {
+ return -1;
+ }
+
+ lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
+ if (lockdown_error != LOCKDOWN_E_SUCCESS) {
+ idevice_free(device);
+ return -1;
+ }
+
+ lockdown_error = lockdownd_get_value(lockdown, NULL, "ProductType", &product_type_node);
+ if (lockdown_error != LOCKDOWN_E_SUCCESS) {
+ lockdownd_client_free(lockdown);
+ idevice_free(device);
+ return -1;
+ }
+
+ if (!product_type_node || plist_get_node_type(product_type_node) != PLIST_STRING) {
+ if(product_type_node) plist_free(product_type_node);
+ lockdownd_client_free(lockdown);
+ idevice_free(device);
+ return -1;
+ }
+ plist_get_string_val(product_type_node, &product_type);
+ plist_free(product_type_node);
+
+ lockdownd_client_free(lockdown);
+ idevice_free(device);
+ lockdown = NULL;
+ device = NULL;
+
+ int i = 0;
+ for(i = 0; idevicerestore_products[i] != NULL; i++) {
+ if(!strcmp(product_type, idevicerestore_products[i])) {
+ idevicerestore_device = i;
+ break;
+ }
+ }
+
+ return idevicerestore_device;
+}
+
+int normal_enter_recovery(const char* uuid) {
+ idevice_t device = NULL;
+ lockdownd_client_t lockdown = NULL;
+ idevice_error_t device_error = IDEVICE_E_SUCCESS;
+ lockdownd_error_t lockdown_error = IDEVICE_E_SUCCESS;
+
+ device_error = idevice_new(&device, uuid);
+ if (device_error != IDEVICE_E_SUCCESS) {
+ error("ERROR: Unable to find device\n");
+ return -1;
+ }
+
+ lockdown_error = lockdownd_client_new(device, &lockdown, "idevicerestore");
+ if (lockdown_error != LOCKDOWN_E_SUCCESS) {
+ error("ERROR: Unable to connect to lockdownd service\n");
+ 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);
+ idevice_free(device);
+ return -1;
+ }
+
+ lockdownd_client_free(lockdown);
+ idevice_free(device);
+ lockdown = NULL;
+ device = NULL;
+ return 0;
+}
+
+int normal_get_cpid(const char* uuid, uint32_t* cpid) {
+ return 0;
+}
+
+int normal_get_bdid(const char* uuid, uint32_t* bdid) {
+ return 0;
+}
+
+int normal_get_ecid(const char* uuid, uint64_t* ecid) {
+ idevice_t device = NULL;
+ plist_t unique_chip_node = NULL;
+ lockdownd_client_t lockdown = NULL;
+ idevice_error_t device_error = IDEVICE_E_SUCCESS;
+ lockdownd_error_t lockdown_error = IDEVICE_E_SUCCESS;
+
+ device_error = idevice_new(&device, uuid);
+ if(device_error != IDEVICE_E_SUCCESS) {
+ 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\n");
+ idevice_free(device);
+ return -1;
+ }
+
+ 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);
+ plist_free(unique_chip_node);
+
+ lockdownd_client_free(lockdown);
+ idevice_free(device);
+ lockdown = NULL;
+ device = NULL;
+}
diff --git a/src/normal.h b/src/normal.h
index 3e2868d..bde1de0 100644
--- a/src/normal.h
+++ b/src/normal.h
@@ -19,11 +19,16 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef NORMAL_H
-#define NORMAL_H
+#ifndef IDEVICERESTORE_NORMAL_H
+#define IDEVICERESTORE_NORMAL_H
#include <stdint.h>
-int normal_get_ecid(uint64_t* ecid);
+int normal_check_mode(const char* uuid);
+int normal_get_device(const char* uuid);
+int normal_enter_recovery(const char* uuid);
+int normal_get_cpid(const char* uuid, uint32_t* cpid);
+int normal_get_bdid(const char* uuid, uint32_t* cpid);
+int normal_get_ecid(const char* uuid, uint64_t* ecid);
#endif
diff --git a/src/recovery.c b/src/recovery.c
index 4e2e7ad..9885982 100644
--- a/src/recovery.c
+++ b/src/recovery.c
@@ -29,7 +29,26 @@
#include "recovery.h"
#include "idevicerestore.h"
-int recovery_send_signed_component(irecv_client_t client, char* ipsw, plist_t tss, char* component) {
+int recovery_check_mode() {
+ irecv_client_t recovery = NULL;
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
+
+ recovery_error = irecv_open(&recovery);
+ if (recovery_error != IRECV_E_SUCCESS) {
+ return -1;
+ }
+
+ if(recovery->mode == kDfuMode) {
+ irecv_close(recovery);
+ return -1;
+ }
+
+ irecv_close(recovery);
+ recovery = NULL;
+ 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;
char* path = NULL;
@@ -77,7 +96,7 @@ irecv_error_t recovery_open_with_timeout(irecv_client_t* client) {
return error;
}
-int recovery_send_ibec(char* ipsw, plist_t tss) {
+int recovery_send_ibec(const char* ipsw, plist_t tss) {
irecv_error_t error = 0;
irecv_client_t client = NULL;
char* component = "iBEC";
@@ -125,7 +144,7 @@ int recovery_send_ibec(char* ipsw, plist_t tss) {
return 0;
}
-int recovery_send_applelogo(char* ipsw, plist_t tss) {
+int recovery_send_applelogo(const char* ipsw, plist_t tss) {
irecv_error_t error = 0;
irecv_client_t client = NULL;
char* component = "AppleLogo";
@@ -167,7 +186,7 @@ int recovery_send_applelogo(char* ipsw, plist_t tss) {
return 0;
}
-int recovery_send_devicetree(char* ipsw, plist_t tss) {
+int recovery_send_devicetree(const char* ipsw, plist_t tss) {
irecv_error_t error = 0;
irecv_client_t client = NULL;
char *component = "RestoreDeviceTree";
@@ -199,7 +218,7 @@ int recovery_send_devicetree(char* ipsw, plist_t tss) {
return 0;
}
-int recovery_send_ramdisk(char* ipsw, plist_t tss) {
+int recovery_send_ramdisk(const char* ipsw, plist_t tss) {
irecv_error_t error = 0;
irecv_client_t client = NULL;
char *component = "RestoreRamDisk";
@@ -231,7 +250,7 @@ int recovery_send_ramdisk(char* ipsw, plist_t tss) {
return 0;
}
-int recovery_send_kernelcache(char* ipsw, plist_t tss) {
+int recovery_send_kernelcache(const char* ipsw, plist_t tss) {
irecv_error_t error = 0;
irecv_client_t client = NULL;
char *component = "RestoreKernelCache";
@@ -265,5 +284,52 @@ int recovery_send_kernelcache(char* ipsw, plist_t tss) {
int recovery_get_ecid(uint64_t* ecid) {
+ irecv_client_t recovery = NULL;
+ if(recovery_open_with_timeout(&recovery) < 0) {
+ return -1;
+ }
+
+ irecv_error_t error = irecv_get_ecid(recovery, ecid);
+ if (error != IRECV_E_SUCCESS) {
+ irecv_close(recovery);
+ return -1;
+ }
+
+ irecv_close(recovery);
+ recovery = NULL;
+ return 0;
+}
+
+int recovery_get_cpid(uint32_t* cpid) {
+ irecv_client_t recovery = NULL;
+ if(recovery_open_with_timeout(&recovery) < 0) {
+ return -1;
+ }
+
+ irecv_error_t error = irecv_get_ecid(recovery, cpid);
+ if (error != IRECV_E_SUCCESS) {
+ irecv_close(recovery);
+ return -1;
+ }
+
+ irecv_close(recovery);
+ recovery = NULL;
+ return 0;
+}
+
+int recovery_get_bdid(uint32_t* bdid) {
+ irecv_client_t recovery = NULL;
+ if(recovery_open_with_timeout(&recovery) < 0) {
+ return -1;
+ }
+
+ irecv_error_t error = irecv_get_ecid(recovery, bdid);
+ if (error != IRECV_E_SUCCESS) {
+ irecv_close(recovery);
+ return -1;
+ }
+
+ irecv_close(recovery);
+ recovery = NULL;
return 0;
}
diff --git a/src/recovery.h b/src/recovery.h
index 5495638..86e3af2 100644
--- a/src/recovery.h
+++ b/src/recovery.h
@@ -19,19 +19,22 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef RECOVERY_H
-#define RECOVERY_H
+#ifndef IDEVICERESTORE_RECOVERY_H
+#define IDEVICERESTORE_RECOVERY_H
#include <stdint.h>
#include <plist/plist.h>
-int recovery_send_signed_component(irecv_client_t client, char* ipsw, plist_t tss, char* component);
+int recovery_check_mode();
+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(char* ipsw, plist_t tss);
-int recovery_send_applelogo(char* ipsw, plist_t tss);
-int recovery_send_devicetree(char* ipsw, plist_t tss);
-int recovery_send_ramdisk(char* ipsw, plist_t tss);
-int recovery_send_kernelcache(char* ipsw, plist_t tss);
+int recovery_send_ibec(const char* ipsw, plist_t tss);
+int recovery_send_applelogo(const char* ipsw, plist_t tss);
+int recovery_send_devicetree(const char* ipsw, plist_t tss);
+int recovery_send_ramdisk(const char* ipsw, plist_t tss);
+int recovery_send_kernelcache(const char* ipsw, plist_t tss);
int recovery_get_ecid(uint64_t* ecid);
+int recovery_get_cpid(uint32_t* cpid);
+int recovery_get_bdid(uint32_t* bdid);
#endif
diff --git a/src/restore.c b/src/restore.c
index 485df9b..90d8c0e 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -44,6 +44,39 @@
#define WAIT_FOR_DEVICE 33
#define LOAD_NOR 36
+int restore_check_mode(const char* uuid) {
+ char* type = NULL;
+ uint64_t version = 0;
+ idevice_t device = NULL;
+ restored_client_t restore = NULL;
+ idevice_error_t device_error = IDEVICE_E_SUCCESS;
+ restored_error_t restore_error = RESTORE_E_SUCCESS;
+
+ device_error = idevice_new(&device, uuid);
+ if (device_error != IDEVICE_E_SUCCESS) {
+ return -1;
+ }
+
+ restore_error = restored_client_new(device, &restore, "idevicerestore");
+ if (restore_error != RESTORE_E_SUCCESS) {
+ idevice_free(device);
+ return -1;
+ }
+
+ restore_error = restored_query_type(restore, &type, &version);
+ if (restore_error != RESTORE_E_SUCCESS) {
+ restored_client_free(restore);
+ idevice_free(device);
+ return -1;
+ }
+
+ restored_client_free(restore);
+ idevice_free(device);
+ restore = NULL;
+ device = NULL;
+ return 0;
+}
+
const char* restore_progress_string(unsigned int operation) {
switch(operation) {
case CREATE_PARTITION_MAP:
@@ -98,7 +131,7 @@ int restore_handle_progress_msg(restored_client_t client, plist_t msg) {
plist_t node = NULL;
uint64_t operation = 0;
uint64_t uprogress = 0;
- uint32_t progress = 0;
+ uint64_t progress = 0;
node = plist_dict_get_item(msg, "Operation");
if (node && PLIST_UINT == plist_get_node_type(node)) {
@@ -111,14 +144,14 @@ int restore_handle_progress_msg(restored_client_t client, plist_t msg) {
node = plist_dict_get_item(msg, "Progress");
if (node && PLIST_UINT == plist_get_node_type(node)) {
plist_get_uint_val(node, &uprogress);
- progress = (uint32_t) uprogress;
+ progress = uprogress;
} else {
debug("Failed to parse progress from ProgressMsg plist \n");
return 0;
}
if ((progress > 0) && (progress < 100))
- info("%s - Progress: %ul%%\n", restore_progress_string(operation), progress);
+ info("%s - Progress: %02ull%%\n", restore_progress_string(operation), progress);
else
info("%s\n", restore_progress_string(operation));
@@ -130,7 +163,7 @@ int restore_handle_status_msg(restored_client_t client, plist_t msg) {
return 0;
}
-int asr_send_system_image_data_from_file(idevice_t device, restored_client_t client, const char *filesystem) {
+int restore_send_filesystem(idevice_t device, restored_client_t client, const char *filesystem) {
int i = 0;
char buffer[0x1000];
uint32_t recv_bytes = 0;
@@ -314,7 +347,7 @@ int restore_send_kernelcache(restored_client_t client, char *kernel_data, int le
return 0;
}
-int restore_send_nor_data(restored_client_t client, char* ipsw, plist_t tss) {
+int restore_send_nor(restored_client_t client, char* ipsw, plist_t tss) {
char* llb_path = NULL;
char* llb_blob = NULL;
if (get_tss_data_by_name(tss, "LLB", &llb_path, &llb_blob) < 0) {
diff --git a/src/restore.h b/src/restore.h
index 644658a..f344b5d 100644
--- a/src/restore.h
+++ b/src/restore.h
@@ -19,18 +19,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef RESTORED_H
-#define RESTORED_H
+#ifndef IDEVICERESTORE_RESTORE_H
+#define IDEVICERESTORE_RESTORE_H
#include <libimobiledevice/restore.h>
#include "restore.h"
+int restore_check_mode(const char* uuid);
int restore_handle_progress_msg(restored_client_t client, plist_t msg);
int restore_handle_status_msg(restored_client_t client, plist_t msg);
-int asr_send_system_image_data_from_file(idevice_t device, restored_client_t client, const char *filesystem);
+int restore_send_filesystem(idevice_t device, restored_client_t client, const char *filesystem);
int restore_send_kernelcache(restored_client_t client, char *kernel_data, int len);
-int restore_send_nor_data(restored_client_t client, char* ipsw, plist_t tss);
+int restore_send_nor(restored_client_t client, char* ipsw, plist_t tss);
const char* restore_progress_string(unsigned int operation);
#endif
diff --git a/src/tss.h b/src/tss.h
index c1ff4b4..c264ee3 100644
--- a/src/tss.h
+++ b/src/tss.h
@@ -19,8 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef TSS_H
-#define TSS_H
+#ifndef IDEVICERESTORE_TSS_H
+#define IDEVICERESTORE_TSS_H
#include <plist/plist.h>