summaryrefslogtreecommitdiffstats
path: root/src/recovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/recovery.c')
-rw-r--r--src/recovery.c247
1 files changed, 122 insertions, 125 deletions
diff --git a/src/recovery.c b/src/recovery.c
index 3bfb97e..a0a1151 100644
--- a/src/recovery.c
+++ b/src/recovery.c
@@ -23,6 +23,8 @@
#include <stdlib.h>
#include <stdint.h>
#include <libirecovery.h>
+#include <libimobiledevice/restore.h>
+#include <libimobiledevice/libimobiledevice.h>
#include "tss.h"
#include "img3.h"
@@ -38,7 +40,7 @@ int recovery_check_mode() {
return -1;
}
- if(recovery->mode == kDfuMode) {
+ if (recovery->mode == kDfuMode) {
irecv_close(recovery);
return -1;
}
@@ -48,7 +50,10 @@ int recovery_check_mode() {
return 0;
}
-int recovery_enter_restore(const char* ipsw, plist_t tss) {
+int recovery_enter_restore(const char* uuid, const char* ipsw, plist_t tss) {
+ idevice_t device = NULL;
+ restored_client_t restore = NULL;
+
// upload data to make device boot restore mode
if (recovery_send_ibec(ipsw, tss) < 0) {
error("ERROR: Unable to send iBEC\n");
@@ -72,7 +77,7 @@ int recovery_enter_restore(const char* ipsw, plist_t tss) {
}
// for some reason iboot requires a hard reset after ramdisk
- // or things start getting wacky
+ // or things start getting wacky
printf("Please unplug your device, then plug it back in\n");
printf("Hit any key to continue...");
getchar();
@@ -82,6 +87,13 @@ int recovery_enter_restore(const char* ipsw, plist_t tss) {
return -1;
}
+ info("Waiting for device to enter restore mode\n");
+ if (restore_open_with_timeout(uuid, &device, &restore) < 0) {
+ error("ERROR: Unable to connect to device in restore mode\n");
+ return -1;
+ }
+ restore_close(device, restore);
+
return 0;
}
@@ -90,244 +102,225 @@ int recovery_send_signed_component(irecv_client_t client, const char* ipsw, plis
char* data = NULL;
char* path = NULL;
char* blob = NULL;
- img3_file* img3 = NULL;
irecv_error_t error = 0;
- if (get_signed_component_by_name(ipsw, tss, component, &data, &size) < 0) {
+ if (tss_get_entry_path(tss, component, &path) < 0) {
+ error("ERROR: Unable to get component path\n");
+ return -1;
+ }
+
+ if (get_signed_component(ipsw, tss, path, &data, &size) < 0) {
error("ERROR: Unable to get signed component: %s\n", component);
+ free(path);
return -1;
}
+ free(path);
info("Sending %s...\n", component);
error = irecv_send_buffer(client, data, size);
if (error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to send IMG3: %s\n", path);
- img3_free(img3);
+ error("ERROR: Unable to send component: %s\n", component);
free(data);
- free(path);
return -1;
}
-
- if (data) {
- free(data);
- data = NULL;
- }
+ free(data);
return 0;
}
-irecv_error_t recovery_open_with_timeout(irecv_client_t* client) {
+int recovery_open_with_timeout(irecv_client_t* client) {
int i = 0;
- irecv_error_t error = 0;
- for (i = 10; i > 0; i--) {
- error = irecv_open(client);
- if (error == IRECV_E_SUCCESS) {
- return error;
+ int attempts = 10;
+ irecv_client_t recovery = NULL;
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
+
+ for (i = 1; i <= attempts; i++) {
+ recovery_error = irecv_open(client);
+ 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);
- info("Retrying connection...\n");
+ debug("Retrying connection...\n");
}
- error("ERROR: Unable to connect to recovery device.\n");
- return error;
+ *client = recovery;
+ return 0;
}
int recovery_send_ibec(const char* ipsw, plist_t tss) {
- irecv_error_t error = 0;
- irecv_client_t client = NULL;
- char* component = "iBEC";
+ irecv_client_t recovery = NULL;
+ const char* component = "iBEC";
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
- error = recovery_open_with_timeout(&client);
- if (error != IRECV_E_SUCCESS) {
+ if (recovery_open_with_timeout(&recovery) < 0) {
return -1;
}
- error = irecv_send_command(client, "setenv auto-boot true");
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_send_command(recovery, "setenv auto-boot true");
+ if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to set auto-boot environmental variable\n");
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- error = irecv_send_command(client, "saveenv");
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_send_command(recovery, "saveenv");
+ if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to save environmental variable\n");
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
+ if (recovery_send_signed_component(recovery, ipsw, tss, "iBEC") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- error = irecv_send_command(client, "go");
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_send_command(recovery, "go");
+ if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- if (client) {
- irecv_close(client);
- client = NULL;
- }
+ irecv_close(recovery);
+ recovery = NULL;
return 0;
}
int recovery_send_applelogo(const char* ipsw, plist_t tss) {
- irecv_error_t error = 0;
- irecv_client_t client = NULL;
- char* component = "AppleLogo";
+ irecv_client_t recovery = NULL;
+ const char* component = "applelogo";
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
info("Sending %s...\n", component);
-
- error = recovery_open_with_timeout(&client);
- if (error != IRECV_E_SUCCESS) {
+ if (recovery_open_with_timeout(&recovery) < 0) {
return -1;
}
- if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
+ if (recovery_send_signed_component(recovery, ipsw, tss, "AppleLogo") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- error = irecv_send_command(client, "setpicture 1");
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_send_command(recovery, "setpicture 1");
+ if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to set %s\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- error = irecv_send_command(client, "bgcolor 0 0 0");
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_send_command(recovery, "bgcolor 0 0 0");
+ if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to display %s\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- if (client) {
- irecv_close(client);
- client = NULL;
- }
+ irecv_close(recovery);
+ recovery = NULL;
return 0;
}
int recovery_send_devicetree(const char* ipsw, plist_t tss) {
- irecv_error_t error = 0;
- irecv_client_t client = NULL;
- char *component = "RestoreDeviceTree";
+ irecv_client_t recovery = NULL;
+ const char* component = "devicetree";
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
- error = recovery_open_with_timeout(&client);
- if (error != IRECV_E_SUCCESS) {
+ if (recovery_open_with_timeout(&recovery) < 0) {
return -1;
}
- if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
+ if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreDeviceTree") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- error = irecv_send_command(client, "devicetree");
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_send_command(recovery, "devicetree");
+ if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- if (client) {
- irecv_close(client);
- client = NULL;
- }
+ irecv_close(recovery);
+ recovery = NULL;
return 0;
}
int recovery_send_ramdisk(const char* ipsw, plist_t tss) {
- irecv_error_t error = 0;
- irecv_client_t client = NULL;
- char *component = "RestoreRamDisk";
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
+ irecv_client_t recovery = NULL;
+ const char *component = "ramdisk";
- error = recovery_open_with_timeout(&client);
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = recovery_open_with_timeout(&recovery);
+ if (recovery_error != IRECV_E_SUCCESS) {
return -1;
}
- if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
+ if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreRamDisk") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- error = irecv_send_command(client, "ramdisk");
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_send_command(recovery, "ramdisk");
+ if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- if (client) {
- irecv_close(client);
- client = NULL;
- }
+ irecv_close(recovery);
+ recovery = NULL;
return 0;
}
int recovery_send_kernelcache(const char* ipsw, plist_t tss) {
- irecv_error_t error = 0;
- irecv_client_t client = NULL;
- char *component = "RestoreKernelCache";
+ irecv_client_t recovery = NULL;
+ const char* component = "kernelcache";
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
- error = recovery_open_with_timeout(&client);
- if (error != IRECV_E_SUCCESS) {
+ if (recovery_open_with_timeout(&recovery) < 0) {
return -1;
}
- if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
+ if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreKernelCache") < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- error = irecv_send_command(client, "bootx");
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_send_command(recovery, "bootx");
+ if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(client);
- client = NULL;
+ irecv_close(recovery);
return -1;
}
- if (client) {
- irecv_close(client);
- client = NULL;
- }
+ irecv_close(recovery);
+ recovery = NULL;
return 0;
}
-
int recovery_get_ecid(uint64_t* ecid) {
irecv_client_t recovery = NULL;
- if(recovery_open_with_timeout(&recovery) < 0) {
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
+
+ if (recovery_open_with_timeout(&recovery) < 0) {
return -1;
}
- irecv_error_t error = irecv_get_ecid(recovery, ecid);
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_get_ecid(recovery, ecid);
+ if (recovery_error != IRECV_E_SUCCESS) {
irecv_close(recovery);
return -1;
}
@@ -339,12 +332,14 @@ int recovery_get_ecid(uint64_t* ecid) {
int recovery_get_cpid(uint32_t* cpid) {
irecv_client_t recovery = NULL;
- if(recovery_open_with_timeout(&recovery) < 0) {
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
+
+ if (recovery_open_with_timeout(&recovery) < 0) {
return -1;
}
- irecv_error_t error = irecv_get_cpid(recovery, cpid);
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_get_cpid(recovery, cpid);
+ if (recovery_error != IRECV_E_SUCCESS) {
irecv_close(recovery);
return -1;
}
@@ -356,12 +351,14 @@ int recovery_get_cpid(uint32_t* cpid) {
int recovery_get_bdid(uint32_t* bdid) {
irecv_client_t recovery = NULL;
- if(recovery_open_with_timeout(&recovery) < 0) {
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
+
+ if (recovery_open_with_timeout(&recovery) < 0) {
return -1;
}
- irecv_error_t error = irecv_get_bdid(recovery, bdid);
- if (error != IRECV_E_SUCCESS) {
+ recovery_error = irecv_get_bdid(recovery, bdid);
+ if (recovery_error != IRECV_E_SUCCESS) {
irecv_close(recovery);
return -1;
}