summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2017-02-21 18:30:28 +0100
committerGravatar Nikias Bassen2017-02-21 18:30:28 +0100
commitaaec66651aba5f617c5c2c22b019d115e2db8e8f (patch)
tree0632c50b687c44d088c4e36930b1072cd669b46a
parent1728254f3a51b8b4d7de902dd53f12141085109c (diff)
downloadidevicerestore-aaec66651aba5f617c5c2c22b019d115e2db8e8f.tar.gz
idevicerestore-aaec66651aba5f617c5c2c22b019d115e2db8e8f.tar.bz2
restore: Add support for 10.3+ firmware images (ipsw)
Starting with iOS 10.3 the ipsw files don't contain any 'manifest' file anymore which we used to determine the files required for the reply to the 'NorData' request. Since this info is also included in the BuildManifest we us that instead, unless a 'manifest' file is present.
-rw-r--r--src/restore.c87
1 files changed, 73 insertions, 14 deletions
diff --git a/src/restore.c b/src/restore.c
index 6fe1049..d06eba9 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -901,6 +901,8 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
unsigned int nor_size = 0;
unsigned char* nor_data = NULL;
plist_t norimage_array = NULL;
+ plist_t firmware_files = NULL;
+ uint32_t i;
info("About to send NORData...\n");
@@ -929,11 +931,53 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
memset(manifest_file, '\0', sizeof(manifest_file));
snprintf(manifest_file, sizeof(manifest_file), "%s/manifest", firmware_path);
- info("Getting firmware manifest %s\n", manifest_file);
- if (ipsw_extract_to_memory(client->ipsw, manifest_file, &manifest_data, &manifest_size) < 0) {
- error("ERROR: Unable to extract firmware manifest from ipsw\n");
- free(llb_path);
+ firmware_files = plist_new_array();
+ ipsw_extract_to_memory(client->ipsw, manifest_file, &manifest_data, &manifest_size);
+ if (manifest_data && manifest_size > 0) {
+ info("Getting firmware manifest from %s\n", manifest_file);
+ char *manifest_p = (char*)manifest_data;
+ while ((filename = strsep(&manifest_p, "\r\n")) != NULL) {
+ if (*filename == '\0') continue;
+ memset(firmware_filename, '\0', sizeof(firmware_filename));
+ snprintf(firmware_filename, sizeof(firmware_filename), "%s/%s", firmware_path, filename);
+ plist_array_append_item(firmware_files, plist_new_string(firmware_filename));
+ }
+ free(manifest_data);
+ } else {
+ info("Getting firmware manifest from build identity\n");
+ plist_dict_iter iter = NULL;
+ plist_t build_id_manifest = plist_dict_get_item(build_identity, "Manifest");
+ if (build_id_manifest) {
+ plist_dict_new_iter(build_id_manifest, &iter);
+ }
+ if (iter) {
+ char *component;
+ plist_t manifest_entry;
+ do {
+ component = NULL;
+ manifest_entry = NULL;
+ plist_dict_next_item(build_id_manifest, iter, &component, &manifest_entry);
+ if (component && manifest_entry && plist_get_node_type(manifest_entry) == PLIST_DICT) {
+ uint8_t is_fw = 0;
+ plist_t is_fw_node = plist_access_path(manifest_entry, 2, "Info", "IsFirmwarePayload");
+ if (is_fw_node && plist_get_node_type(is_fw_node) == PLIST_BOOLEAN) {
+ plist_get_bool_val(is_fw_node, &is_fw);
+ }
+ if (is_fw) {
+ plist_t comp_path = plist_access_path(manifest_entry, 2, "Info", "Path");
+ if (comp_path) {
+ plist_array_append_item(firmware_files, plist_copy(comp_path));
+ }
+ }
+ }
+ } while (manifest_entry);
+ free(iter);
+ }
+ }
+
+ if (plist_array_get_size(firmware_files) == 0) {
+ error("ERROR: Unable to get list of firmware files.\n");
return -1;
}
@@ -962,28 +1006,43 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
norimage_array = plist_new_array();
- filename = strtok((char*)manifest_data, "\r\n");
- while (filename != NULL) {
- if ((!strncmp("LLB", filename, 3)) || (!strncmp("sep", filename, 3))) {
- // skip LLB, it's already passed in LlbImageData
- filename = strtok(NULL, "\r\n");
+ for (i = 0; i < plist_array_get_size(firmware_files); i++) {
+ plist_t pcomp = plist_array_get_item(firmware_files, i);
+ char *comppath = NULL;
+
+ plist_get_string_val(pcomp, &comppath);
+ if (!comppath) continue;
+
+ filename = strrchr(comppath, '/');
+ if (!filename) {
+ free(comppath);
continue;
}
- memset(firmware_filename, '\0', sizeof(firmware_filename));
- snprintf(firmware_filename, sizeof(firmware_filename), "%s/%s", firmware_path, filename);
+ filename++;
component = get_component_name(filename);
+ if (!strcmp(component, "LLB") || !strcmp(component, "RestoreSEP")) {
+ // skip LLB, it's already passed in LlbImageData
+ // skip RestoreSEP, it's passed in RestoreSEPImageData
+ free(comppath);
+ continue;
+ }
+
component_data = NULL;
unsigned int component_size = 0;
- if (extract_component(client->ipsw, firmware_filename, &component_data, &component_size) < 0) {
+ if (extract_component(client->ipsw, comppath, &component_data, &component_size) < 0) {
+ free(comppath);
+ plist_free(firmware_files);
error("ERROR: Unable to extract component: %s\n", component);
return -1;
}
+ free(comppath);
if (personalize_component(component, component_data, component_size, client->tss, &nor_data, &nor_size) < 0) {
- error("ERROR: Unable to get personalized component: %s\n", component);
free(component_data);
+ plist_free(firmware_files);
+ error("ERROR: Unable to get personalized component: %s\n", component);
return -1;
}
free(component_data);
@@ -1000,8 +1059,8 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
free(nor_data);
nor_data = NULL;
nor_size = 0;
- filename = strtok(NULL, "\r\n");
}
+ plist_free(firmware_files);
plist_dict_set_item(dict, "NorImageData", norimage_array);
unsigned char* personalized_data = NULL;