summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/restore.c108
-rw-r--r--src/tss.c167
-rw-r--r--src/tss.h1
3 files changed, 269 insertions, 7 deletions
diff --git a/src/restore.c b/src/restore.c
index ab7e50d..85e34f4 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -83,6 +83,8 @@
#define UPDATE_SWDHID 56
#define UPDATE_S3E_FIRMWARE 58
#define UPDATE_SE_FIRMWARE 59
+#define UPDATE_SAVAGE 60
+#define CERTIFY_SAVAGE 61
static int restore_finished = 0;
@@ -552,6 +554,10 @@ const char* restore_progress_string(unsigned int operation)
return "Updating S3E Firmware";
case UPDATE_SE_FIRMWARE:
return "Updating SE Firmware";
+ case UPDATE_SAVAGE:
+ return "Updating Savage";
+ case CERTIFY_SAVAGE:
+ return "Certifying Savage";
default:
return "Unknown operation";
}
@@ -1853,6 +1859,88 @@ plist_t restore_get_se_firmware_data(restored_client_t restore, struct idevicere
return response;
}
+plist_t restore_get_savage_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info)
+{
+ const char *comp_name = NULL;
+ char *comp_path = NULL;
+ unsigned char* component_data = NULL;
+ unsigned int component_size = 0;
+ plist_t fwdict = NULL;
+ plist_t parameters = NULL;
+ plist_t request = NULL;
+ plist_t response = NULL;
+ plist_t node = NULL;
+ uint8_t isprod = 0;
+ int ret;
+
+ node = plist_dict_get_item(p_info, "Savage,ProductionMode");
+ if (node && (plist_get_node_type(node) == PLIST_BOOLEAN)) {
+ plist_get_bool_val(node, &isprod);
+ }
+ node = NULL;
+ if (isprod) {
+ comp_name = "Savage,B2-Prod-Patch";
+ } else {
+ comp_name = "Savage,B2-Dev-Patch";
+ }
+
+ if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ error("ERROR: Unable get path for '%s' component\n", 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);
+ return NULL;
+ }
+
+ /* create Savage request */
+ request = tss_request_new(NULL);
+ if (request == NULL) {
+ error("ERROR: Unable to create Savage TSS request\n");
+ free(component_data);
+ return NULL;
+ }
+
+ parameters = plist_new_dict();
+
+ /* add manifest for current build_identity to parameters */
+ tss_parameters_add_from_manifest(parameters, build_identity);
+
+ /* add Savage,* tags from info dictionary to parameters */
+ plist_dict_merge(&parameters, p_info);
+
+ /* add required tags for Savage TSS request */
+ tss_request_add_savage_tags(request, parameters, NULL);
+
+ plist_free(parameters);
+
+ info("Sending Savage TSS request...\n");
+ response = tss_request_send(request, client->tss_url);
+ plist_free(request);
+ if (response == NULL) {
+ error("ERROR: Unable to fetch Savage ticket\n");
+ free(component_data);
+ return NULL;
+ }
+
+ if (plist_dict_get_item(response, "Savage,Ticket")) {
+ info("Received Savage ticket\n");
+ } else {
+ error("ERROR: No 'Savage,Ticket' in TSS response, this might not work\n");
+ }
+
+ plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, (uint64_t) component_size));
+ 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;
@@ -1909,19 +1997,25 @@ int restore_send_firmware_updater_data(restored_client_t restore, struct idevice
plist_get_string_val(p_updater_name, &s_updater_name);
- if (strcmp(s_updater_name, "SE")) {
+ if (strcmp(s_updater_name, "SE") == 0) {
+ fwdict = restore_get_se_firmware_data(restore, client, build_identity, p_info);
+ if (fwdict == NULL) {
+ error("ERROR: %s: Couldn't get SE firmware data\n", __func__);
+ goto error_out;
+ }
+ } else if (strcmp(s_updater_name, "Savage") == 0) {
+ 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;
+ }
+ } else {
error("ERROR: %s: Got unknown updater name '%s'.", __func__, s_updater_name);
goto error_out;
}
free(s_updater_name);
s_updater_name = NULL;
- fwdict = restore_get_se_firmware_data(restore, client, build_identity, p_info);
- if (fwdict == NULL) {
- error("ERROR: %s: Couldn't get SE firmware data\n", __func__);
- goto error_out;
- }
-
dict = plist_new_dict();
plist_dict_set_item(dict, "FirmwareResponseData", fwdict);
diff --git a/src/tss.c b/src/tss.c
index ed45c24..5a6af44 100644
--- a/src/tss.c
+++ b/src/tss.c
@@ -202,6 +202,51 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity)
}
node = NULL;
+ /* SE,ChipID - Used for SE firmware request */
+ node = plist_dict_get_item(build_identity, "SE,ChipID");
+ if (node) {
+ if (plist_get_node_type(node) == PLIST_STRING) {
+ char *strval = NULL;
+ int intval = 0;
+ plist_get_string_val(node, &strval);
+ sscanf(strval, "%x", &intval);
+ plist_dict_set_item(parameters, "SE,ChipID", plist_new_uint(intval));
+ } else {
+ plist_dict_set_item(parameters, "SE,ChipID", plist_copy(node));
+ }
+ }
+ node = NULL;
+
+ /* Savage,ChipID - Used for Savage firmware request */
+ node = plist_dict_get_item(build_identity, "Savage,ChipID");
+ if (node) {
+ if (plist_get_node_type(node) == PLIST_STRING) {
+ char *strval = NULL;
+ int intval = 0;
+ plist_get_string_val(node, &strval);
+ sscanf(strval, "%x", &intval);
+ plist_dict_set_item(parameters, "Savage,ChipID", plist_new_uint(intval));
+ } else {
+ plist_dict_set_item(parameters, "Savage,ChipID", plist_copy(node));
+ }
+ }
+ node = NULL;
+
+ /* add Savage,PatchEpoch - Used for Savage firmware request */
+ node = plist_dict_get_item(build_identity, "Savage,PatchEpoch");
+ if (node) {
+ if (plist_get_node_type(node) == PLIST_STRING) {
+ char *strval = NULL;
+ int intval = 0;
+ plist_get_string_val(node, &strval);
+ sscanf(strval, "%x", &intval);
+ plist_dict_set_item(parameters, "Savage,PatchEpoch", plist_new_uint(intval));
+ } else {
+ plist_dict_set_item(parameters, "Savage,PatchEpoch", plist_copy(node));
+ }
+ }
+ node = NULL;
+
/* add build identity manifest dictionary */
node = plist_dict_get_item(build_identity, "Manifest");
if (!node || plist_get_node_type(node) != PLIST_DICT) {
@@ -735,6 +780,128 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid
return 0;
}
+int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t overrides)
+{
+ plist_t node = NULL;
+
+ plist_t manifest_node = plist_dict_get_item(parameters, "Manifest");
+ if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
+ error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__);
+ return -1;
+ }
+
+ /* add tags indicating we want to get the Savage,Ticket */
+ plist_dict_set_item(request, "@BBTicket", plist_new_bool(1));
+ plist_dict_set_item(request, "@Savage,Ticket", plist_new_bool(1));
+
+ /* add Savage,UID */
+ node = plist_dict_get_item(parameters, "Savage,UID");
+ if (!node) {
+ error("ERROR: %s: Unable to find required Savage,UID in parameters\n", __func__);
+ return -1;
+ }
+ plist_dict_set_item(request, "Savage,UID", plist_copy(node));
+ node = NULL;
+
+ /* add SEP */
+ node = plist_access_path(manifest_node, 2, "SEP", "Digest");
+ if (!node) {
+ error("ERROR: Unable to get SEP digest from manifest\n");
+ return -1;
+ }
+ plist_t dict = plist_new_dict();
+ plist_dict_set_item(dict, "Digest", plist_copy(node));
+ plist_dict_set_item(request, "SEP", dict);
+
+ /* add Savage,PatchEpoch */
+ node = plist_dict_get_item(parameters, "Savage,PatchEpoch");
+ if (!node) {
+ error("ERROR: %s: Unable to find required Savage,PatchEpoch in parameters\n", __func__);
+ return -1;
+ }
+ plist_dict_set_item(request, "Savage,PatchEpoch", plist_copy(node));
+ node = NULL;
+
+ /* add Savage,ChipID */
+ node = plist_dict_get_item(parameters, "Savage,ChipID");
+ if (!node) {
+ error("ERROR: %s: Unable to find required Savage,ChipID in parameters\n", __func__);
+ return -1;
+ }
+ plist_dict_set_item(request, "Savage,ChipID", plist_copy(node));
+ node = NULL;
+
+ /* add Savage,AllowOfflineBoot */
+ node = plist_dict_get_item(parameters, "Savage,AllowOfflineBoot");
+ if (!node) {
+ error("ERROR: %s: Unable to find required Savage,AllowOfflineBoot in parameters\n", __func__);
+ return -1;
+ }
+ plist_dict_set_item(request, "Savage,AllowOfflineBoot", plist_copy(node));
+ node = NULL;
+
+ /* add Savage,ReadFWKey */
+ node = plist_dict_get_item(parameters, "Savage,ReadFWKey");
+ if (!node) {
+ error("ERROR: %s: Unable to find required Savage,ReadFWKey in parameters\n", __func__);
+ return -1;
+ }
+ plist_dict_set_item(request, "Savage,ReadFWKey", plist_copy(node));
+ node = NULL;
+
+ /* add Savage,ProductionMode */
+ node = plist_dict_get_item(parameters, "Savage,ProductionMode");
+ if (!node) {
+ error("ERROR: %s: Unable to find required Savage,ProductionMode in parameters\n", __func__);
+ return -1;
+ }
+ plist_dict_set_item(request, "Savage,ProductionMode", plist_copy(node));
+ const char *comp_name = NULL;
+ uint8_t isprod = 0;
+ plist_get_bool_val(node, &isprod);
+ node = NULL;
+
+ /* add Savage,B2-*-Patch */
+ if (isprod) {
+ comp_name = "Savage,B2-Prod-Patch";
+ } else {
+ comp_name = "Savage,B2-Dev-Patch";
+ }
+ node = plist_access_path(manifest_node, 2, comp_name, "Digest");
+ if (!node) {
+ error("ERROR: Unable to get %s digest from manifest\n", comp_name);
+ return -1;
+ }
+ dict = plist_new_dict();
+ plist_dict_set_item(dict, "Digest", plist_copy(node));
+ plist_dict_set_item(request, comp_name, dict);
+
+ /* add Savage,Nonce */
+ node = plist_dict_get_item(parameters, "Savage,Nonce");
+ if (!node) {
+ error("ERROR: %s: Unable to find required Savage,Nonce in parameters\n", __func__);
+ return -1;
+ }
+ plist_dict_set_item(request, "Savage,Nonce", plist_copy(node));
+ node = NULL;
+
+ /* add Savage,ReadECKey */
+ node = plist_dict_get_item(parameters, "Savage,ReadECKey");
+ if (!node) {
+ error("ERROR: %s: Unable to find required Savage,ReadECKey in parameters\n", __func__);
+ return -1;
+ }
+ plist_dict_set_item(request, "Savage,ReadECKey", plist_copy(node));
+ node = NULL;
+
+ /* apply overrides */
+ if (overrides) {
+ plist_dict_merge(&request, overrides);
+ }
+
+ return 0;
+}
+
static size_t tss_write_callback(char* data, size_t size, size_t nmemb, tss_response* response) {
size_t total = size * nmemb;
if (total != 0) {
diff --git a/src/tss.h b/src/tss.h
index 8eb7083..0c62d26 100644
--- a/src/tss.h
+++ b/src/tss.h
@@ -40,6 +40,7 @@ int tss_request_add_common_tags(plist_t request, plist_t parameters, plist_t ove
int tss_request_add_ap_tags(plist_t request, plist_t parameters, plist_t overrides);
int tss_request_add_baseband_tags(plist_t request, plist_t parameters, plist_t overrides);
int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrides);
+int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t overrides);
int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters);
int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters);