diff options
author | Nikias Bassen | 2017-02-21 18:30:28 +0100 |
---|---|---|
committer | Nikias Bassen | 2017-02-21 18:30:28 +0100 |
commit | aaec66651aba5f617c5c2c22b019d115e2db8e8f (patch) | |
tree | 0632c50b687c44d088c4e36930b1072cd669b46a | |
parent | 1728254f3a51b8b4d7de902dd53f12141085109c (diff) | |
download | idevicerestore-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.c | 87 |
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; |