summaryrefslogtreecommitdiffstats
path: root/src/idevicerestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/idevicerestore.c')
-rw-r--r--src/idevicerestore.c79
1 files changed, 57 insertions, 22 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 0ee2bde..5601082 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -73,6 +73,8 @@ static struct option longopts[] = {
{ "no-action", no_argument, NULL, 'n' },
{ "cache-path", required_argument, NULL, 'C' },
{ "no-input", no_argument, NULL, 'y' },
+ { "restore-mode", no_argument, NULL, 'R' },
+ { "ticket", required_argument, NULL, 'T' },
{ NULL, 0, NULL, 0 }
};
@@ -117,6 +119,8 @@ static void usage(int argc, char* argv[], int err)
" -t, --shsh Fetch TSS record and save to .shsh file, then exit\n" \
" -k, --keep-pers Write personalized components to files for debugging\n" \
" -p, --pwn Put device in pwned DFU mode and exit (limera1n devices only)\n" \
+ " -R, --restore-mode Allow restoring from Restore mode\n" \
+ " -T, --ticket PATH Use file at PATH to send as AP ticket\n" \
"\n" \
"Homepage: <" PACKAGE_URL ">\n",
(name ? name + 1 : argv[0]));
@@ -557,21 +561,29 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
if (client->mode->index == MODE_RESTORE) {
- if (restore_reboot(client) < 0) {
- error("ERROR: Unable to exit restore mode\n");
- return -2;
- }
+ if (client->flags & FLAG_ALLOW_RESTORE_MODE) {
+ tss_enabled = 0;
+ if (!client->root_ticket) {
+ client->root_ticket = (void*)strdup("");
+ client->root_ticket_len = 0;
+ }
+ } else {
+ if (restore_reboot(client) < 0) {
+ error("ERROR: Unable to exit restore mode\n");
+ return -2;
+ }
- // we need to refresh the current mode again
- mutex_lock(&client->device_event_mutex);
- cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 60000);
- if (client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (client->flags & FLAG_QUIT)) {
+ // we need to refresh the current mode again
+ mutex_lock(&client->device_event_mutex);
+ cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 60000);
+ if (client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (client->flags & FLAG_QUIT)) {
+ mutex_unlock(&client->device_event_mutex);
+ error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n");
+ return -1;
+ }
+ info("Found device in %s mode\n", client->mode->string);
mutex_unlock(&client->device_event_mutex);
- error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n");
- return -1;
}
- info("Found device in %s mode\n", client->mode->string);
- mutex_unlock(&client->device_event_mutex);
}
// verify if ipsw file exists
@@ -1302,17 +1314,19 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.9);
- mutex_lock(&client->device_event_mutex);
- info("Waiting for device to enter restore mode...\n");
- cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 180000);
- if (client->mode != &idevicerestore_modes[MODE_RESTORE] || (client->flags & FLAG_QUIT)) {
+ if (client->mode->index != MODE_RESTORE) {
+ mutex_lock(&client->device_event_mutex);
+ info("Waiting for device to enter restore mode...\n");
+ cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 180000);
+ if (client->mode != &idevicerestore_modes[MODE_RESTORE] || (client->flags & FLAG_QUIT)) {
+ mutex_unlock(&client->device_event_mutex);
+ error("ERROR: Device failed to enter restore mode.\n");
+ if (delete_fs && filesystem)
+ unlink(filesystem);
+ return -1;
+ }
mutex_unlock(&client->device_event_mutex);
- error("ERROR: Device failed to enter restore mode.\n");
- if (delete_fs && filesystem)
- unlink(filesystem);
- return -1;
}
- mutex_unlock(&client->device_event_mutex);
// device is finally in restore mode, let's do this
if (client->mode->index == MODE_RESTORE) {
@@ -1418,6 +1432,9 @@ void idevicerestore_client_free(struct idevicerestore_client_t* client)
if (client->cache_dir) {
free(client->cache_dir);
}
+ if (client->root_ticket) {
+ free(client->root_ticket);
+ }
free(client);
}
@@ -1528,7 +1545,7 @@ int main(int argc, char* argv[]) {
client->flags |= FLAG_INTERACTIVE;
}
- while ((opt = getopt_long(argc, argv, "dhcesxtpli:u:nC:ky", longopts, &optindex)) > 0) {
+ while ((opt = getopt_long(argc, argv, "dhcesxtpli:u:nC:kyRT:", longopts, &optindex)) > 0) {
switch (opt) {
case 'h':
usage(argc, argv, 0);
@@ -1605,6 +1622,21 @@ int main(int argc, char* argv[]) {
client->flags &= ~FLAG_INTERACTIVE;
break;
+ case 'R':
+ client->flags |= FLAG_ALLOW_RESTORE_MODE;
+ break;
+
+ case 'T': {
+ size_t root_ticket_len = 0;
+ unsigned char* root_ticket = NULL;
+ if (read_file(optarg, (void**)&root_ticket, &root_ticket_len) != 0) {
+ return -1;
+ }
+ client->root_ticket = root_ticket;
+ client->root_ticket_len = (int)root_ticket_len;
+ info("Using ApTicket found at %s length %u\n", optarg, client->root_ticket_len);
+ break;
+ }
default:
usage(argc, argv, 1);
return -1;
@@ -1706,6 +1738,9 @@ int is_image4_supported(struct idevicerestore_client_t* client)
case MODE_NORMAL:
res = normal_is_image4_supported(client);
break;
+ case MODE_RESTORE:
+ res = restore_is_image4_supported(client);
+ break;
case MODE_DFU:
res = dfu_is_image4_supported(client);
break;