summaryrefslogtreecommitdiffstats
path: root/src/recovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/recovery.c')
-rw-r--r--src/recovery.c345
1 files changed, 118 insertions, 227 deletions
diff --git a/src/recovery.c b/src/recovery.c
index 52f4802..4e2e7ad 100644
--- a/src/recovery.c
+++ b/src/recovery.c
@@ -23,356 +23,247 @@
#include <stdlib.h>
#include <stdint.h>
#include <libirecovery.h>
-#include <libimobiledevice/restore.h>
-#include <libimobiledevice/libimobiledevice.h>
#include "tss.h"
#include "img3.h"
#include "recovery.h"
#include "idevicerestore.h"
-int recovery_progress_callback(irecv_client_t client, const irecv_event_t* event) {
- if (event->type == IRECV_PROGRESS) {
- print_progress_bar(event->data, event->progress);
- }
- return 0;
-}
-
-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_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");
- 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;
- }
-
- 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);
- idevicerestore_mode = MODE_RESTORE;
- return 0;
-}
-
-int recovery_send_signed_component(irecv_client_t client, const char* ipsw, plist_t tss, char* component) {
+int recovery_send_signed_component(irecv_client_t client, char* ipsw, plist_t tss, char* component) {
int size = 0;
char* data = NULL;
char* path = NULL;
char* blob = NULL;
+ img3_file* img3 = NULL;
irecv_error_t error = 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) {
+ if (get_signed_component_by_name(ipsw, tss, component, &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 component: %s\n", component);
+ error("ERROR: Unable to send IMG3: %s\n", path);
+ img3_free(img3);
free(data);
+ free(path);
return -1;
}
- free(data);
+
+ if (data) {
+ free(data);
+ data = NULL;
+ }
return 0;
}
-int recovery_open_with_timeout(irecv_client_t* client) {
+irecv_error_t 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;
+ irecv_error_t error = 0;
+ for (i = 10; i > 0; i--) {
+ error = irecv_open(client);
+ if (error == IRECV_E_SUCCESS) {
+ return error;
}
sleep(2);
- debug("Retrying connection...\n");
+ info("Retrying connection...\n");
}
- irecv_event_subscribe(recovery, IRECV_PROGRESS, &recovery_progress_callback, NULL);
- *client = recovery;
- return 0;
+ error("ERROR: Unable to connect to recovery device.\n");
+ return error;
}
-int recovery_send_ibec(const char* ipsw, plist_t tss) {
- irecv_client_t recovery = NULL;
- const char* component = "iBEC";
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
+int recovery_send_ibec(char* ipsw, plist_t tss) {
+ irecv_error_t error = 0;
+ irecv_client_t client = NULL;
+ char* component = "iBEC";
- if (recovery_open_with_timeout(&recovery) < 0) {
+ error = recovery_open_with_timeout(&client);
+ if (error != IRECV_E_SUCCESS) {
return -1;
}
- recovery_error = irecv_send_command(recovery, "setenv auto-boot true");
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = irecv_send_command(client, "setenv auto-boot true");
+ if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to set auto-boot environmental variable\n");
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- recovery_error = irecv_send_command(recovery, "saveenv");
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = irecv_send_command(client, "saveenv");
+ if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to save environmental variable\n");
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "iBEC") < 0) {
+ if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- recovery_error = irecv_send_command(recovery, "go");
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = irecv_send_command(client, "go");
+ if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
+ if (client) {
+ irecv_close(client);
+ client = NULL;
+ }
return 0;
}
-int recovery_send_applelogo(const char* ipsw, plist_t tss) {
- irecv_client_t recovery = NULL;
- const char* component = "applelogo";
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
+int recovery_send_applelogo(char* ipsw, plist_t tss) {
+ irecv_error_t error = 0;
+ irecv_client_t client = NULL;
+ char* component = "AppleLogo";
info("Sending %s...\n", component);
- if (recovery_open_with_timeout(&recovery) < 0) {
+
+ error = recovery_open_with_timeout(&client);
+ if (error != IRECV_E_SUCCESS) {
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "AppleLogo") < 0) {
+ if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- recovery_error = irecv_send_command(recovery, "setpicture 1");
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = irecv_send_command(client, "setpicture 1");
+ if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to set %s\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- recovery_error = irecv_send_command(recovery, "bgcolor 0 0 0");
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = irecv_send_command(client, "bgcolor 0 0 0");
+ if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to display %s\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
+ if (client) {
+ irecv_close(client);
+ client = NULL;
+ }
return 0;
}
-int recovery_send_devicetree(const char* ipsw, plist_t tss) {
- irecv_client_t recovery = NULL;
- const char* component = "devicetree";
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
+int recovery_send_devicetree(char* ipsw, plist_t tss) {
+ irecv_error_t error = 0;
+ irecv_client_t client = NULL;
+ char *component = "RestoreDeviceTree";
- if (recovery_open_with_timeout(&recovery) < 0) {
+ error = recovery_open_with_timeout(&client);
+ if (error != IRECV_E_SUCCESS) {
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreDeviceTree") < 0) {
+ if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- recovery_error = irecv_send_command(recovery, "devicetree");
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = irecv_send_command(client, "devicetree");
+ if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
+ if (client) {
+ irecv_close(client);
+ client = NULL;
+ }
return 0;
}
-int recovery_send_ramdisk(const char* ipsw, plist_t tss) {
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
- irecv_client_t recovery = NULL;
- const char *component = "ramdisk";
+int recovery_send_ramdisk(char* ipsw, plist_t tss) {
+ irecv_error_t error = 0;
+ irecv_client_t client = NULL;
+ char *component = "RestoreRamDisk";
- recovery_error = recovery_open_with_timeout(&recovery);
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = recovery_open_with_timeout(&client);
+ if (error != IRECV_E_SUCCESS) {
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreRamDisk") < 0) {
+ if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- recovery_error = irecv_send_command(recovery, "ramdisk");
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = irecv_send_command(client, "ramdisk");
+ if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
+ if (client) {
+ irecv_close(client);
+ client = NULL;
+ }
return 0;
}
-int recovery_send_kernelcache(const char* ipsw, plist_t tss) {
- irecv_client_t recovery = NULL;
- const char* component = "kernelcache";
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
+int recovery_send_kernelcache(char* ipsw, plist_t tss) {
+ irecv_error_t error = 0;
+ irecv_client_t client = NULL;
+ char *component = "RestoreKernelCache";
- if (recovery_open_with_timeout(&recovery) < 0) {
+ error = recovery_open_with_timeout(&client);
+ if (error != IRECV_E_SUCCESS) {
return -1;
}
- if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreKernelCache") < 0) {
+ if (recovery_send_signed_component(client, ipsw, tss, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- recovery_error = irecv_send_command(recovery, "bootx");
- if (recovery_error != IRECV_E_SUCCESS) {
+ error = irecv_send_command(client, "bootx");
+ if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
- irecv_close(recovery);
+ irecv_close(client);
+ client = NULL;
return -1;
}
- irecv_close(recovery);
- recovery = NULL;
- return 0;
-}
-
-int recovery_get_ecid(uint64_t* ecid) {
- irecv_client_t recovery = NULL;
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
-
- if (recovery_open_with_timeout(&recovery) < 0) {
- return -1;
- }
-
- recovery_error = irecv_get_ecid(recovery, 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;
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
-
- if (recovery_open_with_timeout(&recovery) < 0) {
- return -1;
- }
-
- recovery_error = irecv_get_cpid(recovery, cpid);
- if (recovery_error != IRECV_E_SUCCESS) {
- irecv_close(recovery);
- return -1;
+ if (client) {
+ irecv_close(client);
+ client = NULL;
}
-
- irecv_close(recovery);
- recovery = NULL;
return 0;
}
-int recovery_get_bdid(uint32_t* bdid) {
- irecv_client_t recovery = NULL;
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
-
- if (recovery_open_with_timeout(&recovery) < 0) {
- return -1;
- }
-
- recovery_error = irecv_get_bdid(recovery, bdid);
- if (recovery_error != IRECV_E_SUCCESS) {
- irecv_close(recovery);
- return -1;
- }
- irecv_close(recovery);
- recovery = NULL;
+int recovery_get_ecid(uint64_t* ecid) {
return 0;
}