summaryrefslogtreecommitdiffstats
path: root/src/idevicerestore.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2019-08-29 10:01:13 +0200
committerGravatar Nikias Bassen2019-08-29 10:01:13 +0200
commit182b08380564a4c9c7d5dd35d49cd0f3f5dd3f34 (patch)
treec3ee9e1a475fc83575216b9171f978bd9eb63392 /src/idevicerestore.c
parentc09c07b33038cc333daf1e15f3abbbe522b1de62 (diff)
downloadidevicerestore-182b08380564a4c9c7d5dd35d49cd0f3f5dd3f34.tar.gz
idevicerestore-182b08380564a4c9c7d5dd35d49cd0f3f5dd3f34.tar.bz2
Add support to "preboard" a device on update restore to prevent 'Attempting data recovery'
Diffstat (limited to 'src/idevicerestore.c')
-rw-r--r--src/idevicerestore.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 1918987..10f8e25 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -813,6 +813,7 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
/* retrieve shsh blobs if required */
if (tss_enabled) {
+ int stashbag_commit_required = 0;
debug("Getting device's ECID for TSS request\n");
/* fetch the device's ECID for the TSS request */
if (get_ecid(client, &client->ecid) < 0) {
@@ -821,6 +822,35 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
info("Found ECID " FMT_qu "\n", (long long unsigned int)client->ecid);
+ if (client->mode->index == MODE_NORMAL && !(client->flags & FLAG_ERASE) && !(client->flags & FLAG_SHSHONLY)) {
+ plist_t node = normal_get_lockdown_value(client, NULL, "HasSiDP");
+ uint8_t needs_preboard = 0;
+ if (node && plist_get_node_type(node) == PLIST_BOOLEAN) {
+ plist_get_bool_val(node, &needs_preboard);
+ }
+ if (needs_preboard) {
+ info("Checking if device requires stashbag...\n");
+ plist_t manifest;
+ if (get_preboard_manifest(client, build_identity, &manifest) < 0) {
+ error("ERROR: Unable to create preboard manifest.\n");
+ return -1;
+ }
+ debug("DEBUG: creating stashbag...\n");
+ int err = normal_handle_create_stashbag(client, manifest);
+ if (err < 0) {
+ if (err == -2) {
+ error("ERROR: Could not create stashbag (timeout).\n");
+ } else {
+ error("ERROR: An error occurred while creating the stashbag.\n");
+ }
+ return -1;
+ } else if (err == 1) {
+ stashbag_commit_required = 1;
+ }
+ plist_free(manifest);
+ }
+ }
+
if (client->build_major > 8) {
unsigned char* nonce = NULL;
int nonce_size = 0;
@@ -844,6 +874,19 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
error("ERROR: Unable to get SHSH blobs for this device\n");
return -1;
}
+ if (stashbag_commit_required) {
+ plist_t ticket = plist_dict_get_item(client->tss, "ApImg4Ticket");
+ if (!ticket || plist_get_node_type(ticket) != PLIST_DATA) {
+ error("ERROR: Missing ApImg4Ticket in TSS response for stashbag commit\n");
+ return -1;
+ }
+ info("Committing stashbag...\n");
+ int err = normal_handle_commit_stashbag(client, ticket);
+ if (err < 0) {
+ error("ERROR: Could not commit stashbag (%d). Aborting.\n", err);
+ return -1;
+ }
+ }
}
if (client->flags & FLAG_SHSHONLY) {
@@ -1601,6 +1644,66 @@ plist_t build_manifest_get_build_identity_for_model(plist_t build_manifest, cons
return build_manifest_get_build_identity_for_model_with_restore_behavior(build_manifest, hardware_model, NULL);
}
+int get_preboard_manifest(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* manifest)
+{
+ plist_t request = NULL;
+ *manifest = NULL;
+
+ if (!client->image4supported) {
+ return -1;
+ }
+
+ /* populate parameters */
+ plist_t parameters = plist_new_dict();
+
+ plist_t overrides = plist_new_dict();
+ plist_dict_set_item(overrides, "@APTicket", plist_new_bool(1));
+ plist_dict_set_item(overrides, "ApProductionMode", plist_new_uint(0));
+ plist_dict_set_item(overrides, "ApSecurityDomain", plist_new_uint(0));
+
+ plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(0));
+ plist_dict_set_item(parameters, "ApSecurityMode", plist_new_bool(0));
+
+ tss_parameters_add_from_manifest(parameters, build_identity);
+
+ /* create basic request */
+ request = tss_request_new(NULL);
+ if (request == NULL) {
+ error("ERROR: Unable to create TSS request\n");
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* add common tags from manifest */
+ if (tss_request_add_common_tags(request, parameters, overrides) < 0) {
+ error("ERROR: Unable to add common tags\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ plist_dict_set_item(parameters, "_OnlyFWComponents", plist_new_bool(1));
+
+ /* add tags from manifest */
+ if (tss_request_add_ap_tags(request, parameters, NULL) < 0) {
+ error("ERROR: Unable to add ap tags\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ plist_t local_manifest = NULL;
+ int res = img4_create_local_manifest(request, &local_manifest);
+
+ *manifest = local_manifest;
+
+ plist_free(request);
+ plist_free(parameters);
+ plist_free(overrides);
+
+ return res;
+}
+
int get_tss_response(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss) {
plist_t request = NULL;
plist_t response = NULL;