summaryrefslogtreecommitdiffstats
path: root/src/recovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/recovery.c')
-rw-r--r--src/recovery.c197
1 files changed, 77 insertions, 120 deletions
diff --git a/src/recovery.c b/src/recovery.c
index bacfac7..290f368 100644
--- a/src/recovery.c
+++ b/src/recovery.c
@@ -21,7 +21,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
#include <libirecovery.h>
#include <libimobiledevice/restore.h>
#include <libimobiledevice/libimobiledevice.h>
@@ -29,6 +28,7 @@
#include "tss.h"
#include "img3.h"
#include "common.h"
+#include "restore.h"
#include "recovery.h"
#include "idevicerestore.h"
@@ -46,13 +46,8 @@ int recovery_client_new(struct idevicerestore_client_t* client) {
return -1;
}
- if (recovery_open_with_timeout(recovery) < 0) {
- recovery_client_free(recovery);
- return -1;
- }
-
- if(recovery_check_mode(recovery) < 0) {
- recovery_client_free(recovery);
+ if (recovery_open_with_timeout(client) < 0) {
+ recovery_client_free(client);
return -1;
}
@@ -61,16 +56,42 @@ int recovery_client_new(struct idevicerestore_client_t* client) {
}
void recovery_client_free(struct idevicerestore_client_t* client) {
- struct recovery_client_t* recovery = client->recovery;
- if (recovery) {
- if(recovery->client) {
- irecv_close(recovery);
- recovery = NULL;
+ if(client) {
+ if (client->recovery) {
+ if(client->recovery->client) {
+ irecv_close(client->recovery->client);
+ client->recovery->client = NULL;
+ }
+ free(client->recovery);
+ client->recovery = NULL;
+ }
+ }
+}
+
+int recovery_open_with_timeout(struct idevicerestore_client_t* client) {
+ int i = 0;
+ int attempts = 10;
+ irecv_client_t recovery = NULL;
+ irecv_error_t recovery_error = IRECV_E_UNKNOWN_ERROR;
+
+ for (i = 1; i <= attempts; i++) {
+ recovery_error = irecv_open(&recovery);
+ if (recovery_error == IRECV_E_SUCCESS) {
+ break;
}
- free(recovery);
- client->recovery = NULL;
+ if (i >= attempts) {
+ error("ERROR: Unable to connect to device in recovery mode\n");
+ return -1;
+ }
+
+ sleep(2);
+ debug("Retrying connection...\n");
}
+
+ irecv_event_subscribe(recovery, IRECV_PROGRESS, &recovery_progress_callback, NULL);
+ client->recovery->client = recovery;
+ return 0;
}
int recovery_check_mode() {
@@ -92,28 +113,28 @@ int recovery_check_mode() {
return 0;
}
-int recovery_enter_restore(const char* uuid, const char* ipsw, plist_t tss) {
+int recovery_enter_restore(struct idevicerestore_client_t* client) {
idevice_t device = NULL;
restored_client_t restore = NULL;
// upload data to make device boot restore mode
- if (recovery_send_ibec(ipsw, tss) < 0) {
+ if (recovery_send_ibec(client) < 0) {
error("ERROR: Unable to send iBEC\n");
return -1;
}
sleep(1);
- if (recovery_send_applelogo(ipsw, tss) < 0) {
+ if (recovery_send_applelogo(client) < 0) {
error("ERROR: Unable to send AppleLogo\n");
return -1;
}
- if (recovery_send_devicetree(ipsw, tss) < 0) {
+ if (recovery_send_devicetree(client) < 0) {
error("ERROR: Unable to send DeviceTree\n");
return -1;
}
- if (recovery_send_ramdisk(ipsw, tss) < 0) {
+ if (recovery_send_ramdisk(client) < 0) {
error("ERROR: Unable to send Ramdisk\n");
return -1;
}
@@ -124,35 +145,35 @@ int recovery_enter_restore(const char* uuid, const char* ipsw, plist_t tss) {
printf("Hit any key to continue...");
getchar();
- if (recovery_send_kernelcache(ipsw, tss) < 0) {
+ if (recovery_send_kernelcache(client) < 0) {
error("ERROR: Unable to send KernelCache\n");
return -1;
}
info("Waiting for device to enter restore mode\n");
- if (restore_open_with_timeout(uuid, &device, &restore) < 0) {
+ if (restore_open_with_timeout(client) < 0) {
error("ERROR: Unable to connect to device in restore mode\n");
return -1;
}
- restore_close(device, restore);
+ restore_client_free(client);
client->mode = &idevicerestore_modes[MODE_RESTORE];
return 0;
}
-int recovery_send_signed_component(struct idevicerestore_client_t client, const char* ipsw, plist_t tss, char* component) {
+int recovery_send_signed_component(struct idevicerestore_client_t* client, const char* component) {
int size = 0;
char* data = NULL;
char* path = NULL;
char* blob = NULL;
irecv_error_t error = 0;
- if (tss_get_entry_path(tss, component, &path) < 0) {
+ if (tss_get_entry_path(client->tss, component, &path) < 0) {
error("ERROR: Unable to get component path\n");
return -1;
}
- if (get_signed_component(client, ipsw, tss, path, &data, &size) < 0) {
+ if (get_signed_component(client, client->ipsw, client->tss, path, &data, &size) < 0) {
error("ERROR: Unable to get signed component: %s\n", component);
free(path);
return -1;
@@ -160,7 +181,7 @@ int recovery_send_signed_component(struct idevicerestore_client_t client, const
free(path);
info("Sending %s...\n", component);
- error = irecv_send_buffer(client, data, size);
+ error = irecv_send_buffer(client->recovery->client, data, size);
if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to send component: %s\n", component);
free(data);
@@ -171,84 +192,47 @@ int recovery_send_signed_component(struct idevicerestore_client_t client, const
return 0;
}
-int recovery_open_with_timeout(irecv_client_t* client) {
- int i = 0;
- int attempts = 10;
- irecv_client_t recovery = NULL;
- irecv_error_t recovery_error = IRECV_E_UNKNOWN_ERROR;
-
- for (i = 1; i <= attempts; i++) {
- recovery_error = irecv_open(&recovery);
- if (recovery_error == IRECV_E_SUCCESS) {
- break;
- }
-
- if (i >= attempts) {
- error("ERROR: Unable to connect to device in recovery mode\n");
- return -1;
- }
-
- sleep(2);
- debug("Retrying connection...\n");
- }
-
- irecv_event_subscribe(recovery, IRECV_PROGRESS, &recovery_progress_callback, NULL);
- *client = recovery;
- return 0;
-}
-
-int recovery_send_ibec(const char* ipsw, plist_t tss) {
- irecv_client_t recovery = NULL;
+int recovery_send_ibec(struct idevicerestore_client_t* client) {
const char* component = "iBEC";
irecv_error_t recovery_error = IRECV_E_SUCCESS;
- if (recovery_open_with_timeout(&recovery) < 0) {
- return -1;
- }
-
- recovery_error = irecv_send_command(recovery, "setenv auto-boot true");
+ recovery_error = irecv_send_command(client->recovery->client, "setenv auto-boot true");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to set auto-boot environmental variable\n");
- irecv_close(recovery);
return -1;
}
- recovery_error = irecv_send_command(recovery, "saveenv");
+ recovery_error = irecv_send_command(client->recovery->client, "saveenv");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to save environmental variable\n");
- irecv_close(recovery);
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "iBEC") < 0) {
+ if (recovery_send_signed_component(client, "iBEC") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
return -1;
}
- recovery_error = irecv_send_command(recovery, "go");
+ recovery_error = irecv_send_command(client->recovery->client, "go");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(recovery);
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
return 0;
}
-int recovery_send_applelogo(const char* ipsw, plist_t tss) {
+int recovery_send_applelogo(struct idevicerestore_client_t* client) {
irecv_client_t recovery = NULL;
const char* component = "applelogo";
irecv_error_t recovery_error = IRECV_E_SUCCESS;
info("Sending %s...\n", component);
- if (recovery_open_with_timeout(&recovery) < 0) {
+ if (recovery_open_with_timeout(client) < 0) {
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "AppleLogo") < 0) {
+ if (recovery_send_signed_component(client, "AppleLogo") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
irecv_close(recovery);
return -1;
@@ -273,141 +257,114 @@ int recovery_send_applelogo(const char* ipsw, plist_t tss) {
return 0;
}
-int recovery_send_devicetree(const char* ipsw, plist_t tss) {
- irecv_client_t recovery = NULL;
+int recovery_send_devicetree(struct idevicerestore_client_t* client) {
const char* component = "devicetree";
irecv_error_t recovery_error = IRECV_E_SUCCESS;
- if (recovery_open_with_timeout(&recovery) < 0) {
+ if (recovery_open_with_timeout(client) < 0) {
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreDeviceTree") < 0) {
+ if (recovery_send_signed_component(client, "RestoreDeviceTree") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
return -1;
}
- recovery_error = irecv_send_command(recovery, "devicetree");
+ recovery_error = irecv_send_command(client->recovery->client, "devicetree");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(recovery);
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
return 0;
}
-int recovery_send_ramdisk(const char* ipsw, plist_t tss) {
+int recovery_send_ramdisk(struct idevicerestore_client_t* client) {
irecv_error_t recovery_error = IRECV_E_SUCCESS;
- irecv_client_t recovery = NULL;
const char *component = "ramdisk";
- recovery_error = recovery_open_with_timeout(&recovery);
+ recovery_error = recovery_open_with_timeout(client);
if (recovery_error != IRECV_E_SUCCESS) {
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreRamDisk") < 0) {
+ if (recovery_send_signed_component(client, "RestoreRamDisk") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
return -1;
}
- recovery_error = irecv_send_command(recovery, "ramdisk");
+ recovery_error = irecv_send_command(client->recovery->client, "ramdisk");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(recovery);
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
return 0;
}
-int recovery_send_kernelcache(const char* ipsw, plist_t tss) {
- irecv_client_t recovery = NULL;
+int recovery_send_kernelcache(struct idevicerestore_client_t* client) {
const char* component = "kernelcache";
irecv_error_t recovery_error = IRECV_E_SUCCESS;
- if (recovery_open_with_timeout(&recovery) < 0) {
+ if (recovery_open_with_timeout(client) < 0) {
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreKernelCache") < 0) {
+ if (recovery_send_signed_component(client, "RestoreKernelCache") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
return -1;
}
- recovery_error = irecv_send_command(recovery, "bootx");
+ recovery_error = irecv_send_command(client->recovery->client, "bootx");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(recovery);
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
return 0;
}
-int recovery_get_ecid(uint64_t* ecid) {
- irecv_client_t recovery = NULL;
+int recovery_get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid) {
irecv_error_t recovery_error = IRECV_E_SUCCESS;
- if (recovery_open_with_timeout(&recovery) < 0) {
+ if (recovery_open_with_timeout(client) < 0) {
return -1;
}
- recovery_error = irecv_get_ecid(recovery, ecid);
+ recovery_error = irecv_get_ecid(client->recovery->client, ecid);
if (recovery_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;
+int recovery_get_cpid(struct idevicerestore_client_t* client, uint32_t* cpid) {
irecv_error_t recovery_error = IRECV_E_SUCCESS;
- if (recovery_open_with_timeout(&recovery) < 0) {
+ if (recovery_open_with_timeout(client) < 0) {
return -1;
}
- recovery_error = irecv_get_cpid(recovery, cpid);
+ recovery_error = irecv_get_cpid(client->recovery->client, cpid);
if (recovery_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;
+int recovery_get_bdid(struct idevicerestore_client_t* client, uint32_t* bdid) {
irecv_error_t recovery_error = IRECV_E_SUCCESS;
- if (recovery_open_with_timeout(&recovery) < 0) {
+ if (recovery_open_with_timeout(client) < 0) {
return -1;
}
- recovery_error = irecv_get_bdid(recovery, bdid);
+ recovery_error = irecv_get_bdid(client->recovery->client, bdid);
if (recovery_error != IRECV_E_SUCCESS) {
- irecv_close(recovery);
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
return 0;
}