summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/idevicerestore.c593
1 files changed, 383 insertions, 210 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index ec449d9..f9fd116 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -222,203 +222,33 @@ int main(int argc, char* argv[]) {
if (send_ibec(ipsw, tss_response) < 0) {
error("ERROR: Unable to send iBEC\n");
- return -1;
- }
-
- // Reconnect to iBEC
- info("Connecting to iBEC\n");
- recovery_error = irecv_open(&recovery);
- while (recovery_error != IRECV_E_SUCCESS) {
- sleep(1);
- info("Retrying connection...\n");
- recovery_error = irecv_open(&recovery);
- if (recovery_error == IRECV_E_SUCCESS) {
- break;
- }
- }
-
- // Sending DeviceTree
- info("Extracting DeviceTree from IPSW\n");
- plist_t devicetree_entry = plist_dict_get_item(tss_response, "RestoreDeviceTree");
- if (!devicetree_entry || plist_get_node_type(devicetree_entry) != PLIST_DICT) {
- error("ERROR: Unable to find DeviceTree entry in TSS response\n");
plist_free(tss_response);
- irecv_close(recovery);
return -1;
}
-
- char* devicetree_path = NULL;
- plist_t devicetree_path_node = plist_dict_get_item(devicetree_entry, "Path");
- if (!devicetree_path_node || plist_get_node_type(devicetree_path_node) != PLIST_STRING) {
- error("ERROR: Unable to find DeviceTree path in entry\n");
- plist_free(tss_response);
- plist_free(devicetree_entry);
- irecv_close(recovery);
- recovery = NULL;
- return -1;
- }
- plist_get_string_val(devicetree_path_node, &devicetree_path);
-
- char* devicetree_blob = NULL;
- uint64_t devicetree_blob_size = 0;
- plist_t devicetree_blob_node = plist_dict_get_item(devicetree_entry, "Blob");
- if (!devicetree_blob_node || plist_get_node_type(devicetree_blob_node) != PLIST_DATA) {
- error("ERROR: Unable to find DeviceTree blob in entry\n");
- plist_free(tss_response);
- plist_free(devicetree_entry);
- irecv_close(recovery);
- recovery = NULL;
- return -1;
- }
- plist_get_data_val(devicetree_blob_node, &devicetree_blob, &devicetree_blob_size);
- plist_free(devicetree_blob_node);
- plist_free(devicetree_entry);
-
- ipsw_file* devicetree = ipsw_extract_file(ipsw, devicetree_path);
- if (devicetree == NULL) {
- error("ERROR: Unable to extract %s from IPSW\n", devicetree_path);
- irecv_close(recovery);
- recovery = NULL;
- return -1;
- }
-
- img3_file* devicetree_img3 = img3_parse_file(devicetree->data, devicetree->size);
- if (devicetree_img3 == NULL) {
- error("ERROR: Unable to parse IMG3: %s\n", devicetree_path);
- irecv_close(recovery);
- ipsw_free_file(devicetree);
- recovery = NULL;
- return -1;
- }
- ipsw_free_file(devicetree);
-
- img3_replace_signature(devicetree_img3, devicetree_blob);
- free(devicetree_blob);
-
- int devicetree_size = 0;
- char* devicetree_data = NULL;
- img3_get_data(devicetree_img3, &devicetree_data, &devicetree_size);
- write_file("devicetree.img3", devicetree_data, devicetree_size);
- recovery_error = irecv_send_buffer(recovery, devicetree_data, devicetree_size);
- if (recovery_error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to send IMG3: %s\n", devicetree_path);
- irecv_close(recovery);
- img3_free(devicetree_img3);
- recovery = NULL;
- return -1;
- }
- img3_free(devicetree_img3);
-
- recovery_error = irecv_send_command(recovery, "devicetree");
- if (recovery_error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to execute DeviceTree\n");
- irecv_close(recovery);
- img3_free(devicetree_img3);
- recovery = NULL;
- return -1;
- }
- free(devicetree_data);
sleep(1);
- // Sending RestoreRamdisk
- info("Extracting Ramdisk from IPSW\n");
- plist_t ramdisk_entry = plist_dict_get_item(tss_response, "RestoreRamDisk");
- if (!ramdisk_entry || plist_get_node_type(ramdisk_entry) != PLIST_DICT) {
- error("ERROR: Unable to find RestoreRamDisk entry in TSS response\n");
+ if (send_devicetree(ipsw, tss_response) < 0) {
+ error("ERROR: Unable to send DeviceTree\n");
plist_free(tss_response);
- irecv_close(recovery);
return -1;
}
- char* ramdisk_path = NULL;
- plist_t ramdisk_path_node = plist_dict_get_item(ramdisk_entry, "Path");
- if (!ramdisk_path_node || plist_get_node_type(ramdisk_path_node) != PLIST_STRING) {
- error("ERROR: Unable to find RestoreRamDisk path in entry\n");
+ if (send_ramdisk(ipsw, tss_response) < 0) {
+ error("ERROR: Unable to send Ramdisk\n");
plist_free(tss_response);
- plist_free(ramdisk_entry);
- irecv_close(recovery);
- recovery = NULL;
return -1;
}
- plist_get_string_val(ramdisk_path_node, &ramdisk_path);
- char* ramdisk_blob = NULL;
- uint64_t ramdisk_blob_size = 0;
- plist_t ramdisk_blob_node = plist_dict_get_item(ramdisk_entry, "Blob");
- if (!ramdisk_blob_node || plist_get_node_type(ramdisk_blob_node) != PLIST_DATA) {
- error("ERROR: Unable to find RestoreRamdisk blob in entry\n");
- plist_free(tss_response);
- plist_free(ramdisk_entry);
- irecv_close(recovery);
- recovery = NULL;
- return -1;
- }
- plist_get_data_val(ramdisk_blob_node, &ramdisk_blob, &ramdisk_blob_size);
- plist_free(ramdisk_blob_node);
- plist_free(ramdisk_entry);
-
- ipsw_file* ramdisk = ipsw_extract_file(ipsw, ramdisk_path);
- if (ramdisk == NULL) {
- error("ERROR: Unable to extract %s from IPSW\n", ramdisk_path);
- irecv_close(recovery);
- recovery = NULL;
- return -1;
- }
-
- img3_file* ramdisk_img3 = img3_parse_file(ramdisk->data, ramdisk->size);
- if (ramdisk_img3 == NULL) {
- error("ERROR: Unable to parse IMG3: %s\n", ramdisk_path);
- irecv_close(recovery);
- ipsw_free_file(ramdisk);
- recovery = NULL;
- return -1;
- }
- ipsw_free_file(ramdisk);
-
- img3_replace_signature(ramdisk_img3, ramdisk_blob);
- free(ramdisk_blob);
-
- int ramdisk_size = 0;
- char* ramdisk_data = NULL;
- img3_get_data(ramdisk_img3, &ramdisk_data, &ramdisk_size);
- write_file("ramdisk.dmg", ramdisk_data, ramdisk_size);
- recovery_error = irecv_send_buffer(recovery, ramdisk_data, ramdisk_size);
- if (recovery_error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to send IMG3: %s\n", ramdisk_path);
- irecv_close(recovery);
- img3_free(ramdisk_img3);
- recovery = NULL;
- return -1;
- }
- img3_free(ramdisk_img3);
-
- recovery_error = irecv_send_command(recovery, "ramdisk");
- if (recovery_error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to execute DeviceTree\n");
- irecv_close(recovery);
- recovery = NULL;
- return -1;
- }
- free(ramdisk_data);
- irecv_close(recovery);
- recovery = NULL;
-
- printf("Please unplug your device, then plug it back in, hit any key to continue\n");
+ printf("Please unplug your device, then plug it back in\n");
+ printf("Hit any key to continue...");
getchar();
- // Reconnect to iBEC
- recovery_error = irecv_open(&recovery);
- while (recovery_error != IRECV_E_SUCCESS) {
- sleep(1);
- info("Retrying connection...\n");
- recovery_error = irecv_open(&recovery);
- if (recovery_error == IRECV_E_SUCCESS) {
- break;
- }
+ if (send_kernelcache(ipsw, tss_response) < 0) {
+ error("ERROR: Unable to send KernelCache\n");
+ plist_free(tss_response);
+ return -1;
}
- irecv_close(recovery);
- recovery = NULL;
plist_free(tss_response);
return 0;
}
@@ -470,25 +300,19 @@ int get_tss_data(plist_t tss, const char* entry, char** ppath, char** pblob) {
plist_t path_node = plist_dict_get_item(node, "Path");
if (!path_node || plist_get_node_type(path_node) != PLIST_STRING) {
error("ERROR: Unable to find %s path in entry\n", entry);
- plist_free(node);
return -1;
}
plist_get_string_val(path_node, &path);
- plist_free(path_node);
char* blob = NULL;
uint64_t blob_size = 0;
plist_t blob_node = plist_dict_get_item(node, "Blob");
if (!blob_node || plist_get_node_type(blob_node) != PLIST_DATA) {
error("ERROR: Unable to find %s blob in entry\n", entry);
- plist_free(node);
free(path);
return -1;
}
-
plist_get_data_val(blob_node, &blob, &blob_size);
- plist_free(blob_node);
- plist_free(node);
*ppath = path;
*pblob = blob;
@@ -497,23 +321,29 @@ int get_tss_data(plist_t tss, const char* entry, char** ppath, char** pblob) {
int send_ibec(char* ipsw, plist_t tss) {
int i = 0;
+ irecv_error_t error = 0;
irecv_client_t client = NULL;
- info("Connecting to iBoot...\n");
- irecv_error_t error = irecv_open(&client);
+ info("Sending iBEC...\n");
for (i = 10; i > 0; i--) {
+ error = irecv_open(&client);
if (error == IRECV_E_SUCCESS) {
irecv_send_command(client, "setenv auto-boot true");
irecv_send_command(client, "saveenv");
break;
}
- sleep(1);
+
+ if (i == 0) {
+ error("Unable to connect to iBoot\n");
+ return -1;
+ }
+
+ sleep(2);
info("Retrying connection...\n");
- error = irecv_open(&client);
}
char* path = NULL;
char* blob = NULL;
- info("Extracting iBEC data from TSS response\n");
+ info("Extracting data from TSS response\n");
if (get_tss_data(tss, "iBEC", &path, &blob) < 0) {
error("ERROR: Unable to get data for TSS entry\n");
irecv_close(client);
@@ -571,8 +401,16 @@ int send_ibec(char* ipsw, plist_t tss) {
return -1;
}
- path = strrchr(path, '/');
- write_file(path + 1, data, size);
+ if (idevicerestore_debug) {
+ char* out = strrchr(path, '/');
+ if (out != NULL) {
+ out++;
+ } else {
+ out = path;
+ }
+ write_file(out, data, size);
+ }
+
error = irecv_send_buffer(client, data, size);
if (error != IRECV_E_SUCCESS) {
error("ERROR: Unable to send IMG3: %s\n", path);
@@ -605,61 +443,396 @@ int send_ibec(char* ipsw, plist_t tss) {
return -1;
}
- irecv_close(client);
- client = NULL;
+ if (client) {
+ irecv_close(client);
+ client = NULL;
+ }
return 0;
}
int send_devicetree(char* ipsw, plist_t tss) {
int i = 0;
- info("Sending devicetree\n");
+ irecv_error_t error = 0;
irecv_client_t client = NULL;
- irecv_error_t error = irecv_open(&client);
+ info("Sending DeviceTree...\n");
for (i = 10; i > 0; i--) {
+ error = irecv_open(&client);
if (error == IRECV_E_SUCCESS) {
break;
}
- sleep(1);
+
+ if (i == 0) {
+ error("Unable to connect to iBEC\n");
+ return -1;
+ }
+
+ sleep(3);
info("Retrying connection...\n");
- error = irecv_open(&client);
}
- irecv_close(client);
+ char* path = NULL;
+ char* blob = NULL;
+ info("Extracting data from TSS response\n");
+ if (get_tss_data(tss, "DeviceTree", &path, &blob) < 0) {
+ error("ERROR: Unable to get data for TSS entry\n");
+ irecv_close(client);
+ client = NULL;
+ return -1;
+ }
+
+ info("Extracting %s from %s\n", path, ipsw);
+ ipsw_file* devicetree = ipsw_extract_file(ipsw, path);
+ if (devicetree == NULL) {
+ error("ERROR: Unable to extract %s from %s\n", path, ipsw);
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+
+ img3_file* img3 = img3_parse_file(devicetree->data, devicetree->size);
+ if (img3 == NULL) {
+ error("ERROR: Unable to parse IMG3: %s\n", path);
+ ipsw_free_file(devicetree);
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+ if (devicetree) {
+ ipsw_free_file(devicetree);
+ devicetree = NULL;
+ }
+
+ if (img3_replace_signature(img3, blob) < 0) {
+ error("ERROR: Unable to replace IMG3 signature\n");
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+ if (blob) {
+ free(blob);
+ blob = NULL;
+ }
+
+ int size = 0;
+ char* data = NULL;
+ if (img3_get_data(img3, &data, &size) < 0) {
+ error("ERROR: Unable to reconstruct IMG3\n");
+ irecv_close(client);
+ img3_free(img3);
+ client = NULL;
+ free(path);
+ return -1;
+ }
+
+ if (idevicerestore_debug) {
+ char* out = strrchr(path, '/');
+ if (out != NULL) {
+ out++;
+ } else {
+ out = path;
+ }
+ write_file(out, data, size);
+ }
+
+ error = irecv_send_buffer(client, data, size);
+ if (error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to send IMG3: %s\n", path);
+ irecv_close(client);
+ img3_free(img3);
+ client = NULL;
+ free(data);
+ free(path);
+ return -1;
+ }
+ if (img3) {
+ img3_free(img3);
+ img3 = NULL;
+ }
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ if (path) {
+ free(path);
+ path = NULL;
+ }
+
+ error = irecv_send_command(client, "devicetree");
+ if (error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to execute DeviceTree\n");
+ irecv_close(client);
+ client = NULL;
+ free(data);
+ return -1;
+ }
+
+ if (client) {
+ irecv_close(client);
+ client = NULL;
+ }
return 0;
}
int send_ramdisk(char* ipsw, plist_t tss) {
int i = 0;
- info("Sending ramdisk\n");
+ irecv_error_t error = 0;
irecv_client_t client = NULL;
- irecv_error_t error = irecv_open(&client);
+ info("Sending Ramdisk...\n");
for (i = 10; i > 0; i--) {
+ error = irecv_open(&client);
if (error == IRECV_E_SUCCESS) {
break;
}
- sleep(1);
+
+ if (i == 0) {
+ error("Unable to connect to iBEC\n");
+ return -1;
+ }
+
+ sleep(3);
info("Retrying connection...\n");
- error = irecv_open(&client);
}
- irecv_close(client);
+ char* path = NULL;
+ char* blob = NULL;
+ info("Extracting data from TSS response\n");
+ if (get_tss_data(tss, "RestoreRamDisk", &path, &blob) < 0) {
+ error("ERROR: Unable to get data for TSS entry\n");
+ irecv_close(client);
+ client = NULL;
+ return -1;
+ }
+
+ info("Extracting %s from %s\n", path, ipsw);
+ ipsw_file* ramdisk = ipsw_extract_file(ipsw, path);
+ if (ramdisk == NULL) {
+ error("ERROR: Unable to extract %s from %s\n", path, ipsw);
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+
+ img3_file* img3 = img3_parse_file(ramdisk->data, ramdisk->size);
+ if (img3 == NULL) {
+ error("ERROR: Unable to parse IMG3: %s\n", path);
+ ipsw_free_file(ramdisk);
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+ if (ramdisk) {
+ ipsw_free_file(ramdisk);
+ ramdisk = NULL;
+ }
+
+ if (img3_replace_signature(img3, blob) < 0) {
+ error("ERROR: Unable to replace IMG3 signature\n");
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+ if (blob) {
+ free(blob);
+ blob = NULL;
+ }
+
+ int size = 0;
+ char* data = NULL;
+ if (img3_get_data(img3, &data, &size) < 0) {
+ error("ERROR: Unable to reconstruct IMG3\n");
+ irecv_close(client);
+ img3_free(img3);
+ client = NULL;
+ free(path);
+ return -1;
+ }
+
+ if (idevicerestore_debug) {
+ char* out = strrchr(path, '/');
+ if (out != NULL) {
+ out++;
+ } else {
+ out = path;
+ }
+ write_file(out, data, size);
+ }
+
+ error = irecv_send_buffer(client, data, size);
+ if (error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to send IMG3: %s\n", path);
+ irecv_close(client);
+ img3_free(img3);
+ client = NULL;
+ free(data);
+ free(path);
+ return -1;
+ }
+ if (img3) {
+ img3_free(img3);
+ img3 = NULL;
+ }
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ if (path) {
+ free(path);
+ path = NULL;
+ }
+
+ error = irecv_send_command(client, "ramdisk");
+ if (error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to execute Ramdisk\n");
+ irecv_close(client);
+ client = NULL;
+ free(data);
+ return -1;
+ }
+
+ if (client) {
+ irecv_close(client);
+ client = NULL;
+ }
return 0;
}
int send_kernelcache(char* ipsw, plist_t tss) {
int i = 0;
- info("Sending kernelcache\n");
+ irecv_error_t error = 0;
irecv_client_t client = NULL;
- irecv_error_t error = irecv_open(&client);
+ info("Sending KernelCache...\n");
for (i = 10; i > 0; i--) {
+ error = irecv_open(&client);
if (error == IRECV_E_SUCCESS) {
break;
}
- sleep(1);
+
+ if (i == 0) {
+ error("Unable to connect to iBEC\n");
+ return -1;
+ }
+
+ sleep(3);
info("Retrying connection...\n");
- error = irecv_open(&client);
}
- irecv_close(client);
+ char* path = NULL;
+ char* blob = NULL;
+ info("Extracting data from TSS response\n");
+ if (get_tss_data(tss, "KernelCache", &path, &blob) < 0) {
+ error("ERROR: Unable to get data for TSS entry\n");
+ irecv_close(client);
+ client = NULL;
+ return -1;
+ }
+
+ info("Extracting %s from %s\n", path, ipsw);
+ ipsw_file* kernelcache = ipsw_extract_file(ipsw, path);
+ if (kernelcache == NULL) {
+ error("ERROR: Unable to extract %s from %s\n", path, ipsw);
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+
+ img3_file* img3 = img3_parse_file(kernelcache->data, kernelcache->size);
+ if (img3 == NULL) {
+ error("ERROR: Unable to parse IMG3: %s\n", path);
+ ipsw_free_file(kernelcache);
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+ if (kernelcache) {
+ ipsw_free_file(kernelcache);
+ kernelcache = NULL;
+ }
+
+ if (img3_replace_signature(img3, blob) < 0) {
+ error("ERROR: Unable to replace IMG3 signature\n");
+ irecv_close(client);
+ client = NULL;
+ free(path);
+ free(blob);
+ return -1;
+ }
+ if (blob) {
+ free(blob);
+ blob = NULL;
+ }
+
+ int size = 0;
+ char* data = NULL;
+ if (img3_get_data(img3, &data, &size) < 0) {
+ error("ERROR: Unable to reconstruct IMG3\n");
+ irecv_close(client);
+ img3_free(img3);
+ client = NULL;
+ free(path);
+ return -1;
+ }
+
+ if (idevicerestore_debug) {
+ char* out = strrchr(path, '/');
+ if (out != NULL) {
+ out++;
+ } else {
+ out = path;
+ }
+ write_file(out, data, size);
+ }
+
+ error = irecv_send_buffer(client, data, size);
+ if (error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to send IMG3: %s\n", path);
+ irecv_close(client);
+ img3_free(img3);
+ client = NULL;
+ free(data);
+ free(path);
+ return -1;
+ }
+ if (img3) {
+ img3_free(img3);
+ img3 = NULL;
+ }
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ if (path) {
+ free(path);
+ path = NULL;
+ }
+
+ error = irecv_send_command(client, "bootx");
+ if (error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to execute iBEC\n");
+ irecv_close(client);
+ client = NULL;
+ free(data);
+ return -1;
+ }
+
+ if (client) {
+ irecv_close(client);
+ client = NULL;
+ }
return 0;
}