summaryrefslogtreecommitdiffstats
path: root/src/restore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/restore.c')
-rw-r--r--src/restore.c147
1 files changed, 146 insertions, 1 deletions
diff --git a/src/restore.c b/src/restore.c
index 9248d7f..5e5bcec 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -1973,6 +1973,146 @@ plist_t restore_get_savage_firmware_data(restored_client_t restore, struct idevi
return response;
}
+plist_t restore_get_yonkers_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info)
+{
+ char *comp_name = NULL;
+ char *comp_path = NULL;
+ plist_t comp_node = NULL;
+ unsigned char* component_data = NULL;
+ unsigned int component_size = 0;
+ plist_t parameters = NULL;
+ plist_t request = NULL;
+ plist_t response = NULL;
+ plist_t node = NULL;
+ uint8_t isprod = 1;
+ uint64_t fabrevision = (uint64_t)-1;
+ int ret;
+
+ node = plist_dict_get_item(p_info, "Yonkers,ProductionMode");
+ if (node && (plist_get_node_type(node) == PLIST_BOOLEAN)) {
+ plist_get_bool_val(node, &isprod);
+ }
+
+ node = plist_dict_get_item(p_info, "Yonkers,FabRevision");
+ if (node && (plist_get_node_type(node) == PLIST_UINT)) {
+ plist_get_uint_val(node, &fabrevision);
+ }
+
+ plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest");
+ if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
+ error("ERROR: Unable to find manifest node\n");
+ return NULL;
+ }
+ plist_dict_iter iter = NULL;
+ plist_dict_new_iter(manifest_node, &iter);
+ while (1) {
+ plist_dict_next_item(manifest_node, iter, &comp_name, &node);
+ if (comp_name == NULL) {
+ node = NULL;
+ break;
+ }
+ if (strncmp(comp_name, "Yonkers,", 8) == 0) {
+ int target_node = 1;
+ plist_t sub_node;
+ if ((sub_node = plist_dict_get_item(node, "EPRO")) != NULL && plist_get_node_type(sub_node) == PLIST_BOOLEAN) {
+ uint8_t b = 0;
+ plist_get_bool_val(sub_node, &b);
+ target_node &= ((isprod) ? b : !b);
+ }
+ if ((sub_node = plist_dict_get_item(node, "FabRevision")) != NULL && plist_get_node_type(sub_node) == PLIST_UINT) {
+ uint64_t v = 0;
+ plist_get_uint_val(sub_node, &v);
+ target_node &= (v == fabrevision);
+ }
+ if (target_node) {
+ comp_node = node;
+ break;
+ }
+ }
+ free(comp_name);
+ comp_name = NULL;
+ }
+ free(iter);
+ node = NULL;
+
+ if (comp_name == NULL) {
+ error("ERROR: No Yonkers node for %s/%lu\n", (isprod) ? "Production" : "Development", (unsigned long)fabrevision);
+ return NULL;
+ }
+ debug("DEBUG: %s: using %s\n", __func__, comp_name);
+
+ if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ error("ERROR: Unable get path for '%s' component\n", comp_name);
+ free(comp_name);
+ return NULL;
+ }
+
+ ret = extract_component(client->ipsw, comp_path, &component_data, &component_size);
+ free(comp_path);
+ comp_path = NULL;
+ if (ret < 0) {
+ error("ERROR: Unable to extract '%s' component\n", comp_name);
+ free(comp_name);
+ return NULL;
+ }
+
+ /* create Yonkers request */
+ request = tss_request_new(NULL);
+ if (request == NULL) {
+ error("ERROR: Unable to create Yonkers TSS request\n");
+ free(component_data);
+ free(comp_name);
+ return NULL;
+ }
+
+ parameters = plist_new_dict();
+
+ /* add manifest for current build_identity to parameters */
+ tss_parameters_add_from_manifest(parameters, build_identity);
+
+ /* add Yonkers,* tags from info dictionary to parameters */
+ plist_dict_merge(&parameters, p_info);
+
+ /* add required tags for Yonkers TSS request */
+ tss_request_add_yonkers_tags(request, parameters, NULL);
+
+ plist_free(parameters);
+
+ if (comp_node != NULL) {
+ plist_t comp_dict = plist_copy(comp_node);
+ plist_dict_remove_item(comp_dict, "Info");
+ plist_dict_set_item(request, comp_name, comp_dict);
+ }
+
+ free(comp_name);
+ comp_name = NULL;
+
+ info("Sending Yonkers TSS request...\n");
+ response = tss_request_send(request, client->tss_url);
+ plist_free(request);
+ if (response == NULL) {
+ error("ERROR: Unable to fetch Yonkers ticket\n");
+ free(component_data);
+ return NULL;
+ }
+
+ if (plist_dict_get_item(response, "Yonkers,Ticket")) {
+ info("Received Yonkers ticket\n");
+ } else {
+ error("ERROR: No 'Yonkers,Ticket' in TSS response, this might not work\n");
+ }
+
+ plist_t firmware_data = plist_new_dict();
+ plist_dict_set_item(firmware_data, "YonkersFirmware", plist_new_data((char *)component_data, (uint64_t)component_size));
+ plist_dict_set_item(response, "FirmwareData", firmware_data);
+
+ free(component_data);
+ component_data = NULL;
+ component_size = 0;
+
+ return response;
+}
+
int restore_send_firmware_updater_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message)
{
plist_t arguments;
@@ -2036,7 +2176,12 @@ int restore_send_firmware_updater_data(restored_client_t restore, struct idevice
goto error_out;
}
} else if (strcmp(s_updater_name, "Savage") == 0) {
- fwdict = restore_get_savage_firmware_data(restore, client, build_identity, p_info);
+ plist_t p_info2 = plist_dict_get_item(p_info, "YonkersDeviceInfo");
+ if (p_info2 && plist_get_node_type(p_info2) == PLIST_DICT) {
+ fwdict = restore_get_yonkers_firmware_data(restore, client, build_identity, p_info2);
+ } else {
+ fwdict = restore_get_savage_firmware_data(restore, client, build_identity, p_info);
+ }
if (fwdict == NULL) {
error("ERROR: %s: Couldn't get Savage firmware data\n", __func__);
goto error_out;