summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/idevicerestore.c57
-rw-r--r--src/ipsw.c5
-rw-r--r--src/ipsw.h2
-rw-r--r--src/recovery.c64
-rw-r--r--src/restore.c14
5 files changed, 76 insertions, 66 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 00c35c1..f3fdbdc 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -64,7 +64,7 @@ int main(int argc, char* argv[]) {
int optindex = 0;
char* ipsw = NULL;
char* uuid = NULL;
- uint64_t ecid = 0;
+ int tss_enabled = 0;
// create an instance of our context
struct idevicerestore_client_t* client = (struct idevicerestore_client_t*) malloc(sizeof(struct idevicerestore_client_t));
@@ -149,7 +149,7 @@ int main(int argc, char* argv[]) {
// extract buildmanifest
plist_t buildmanifest = NULL;
info("Extracting BuildManifest from IPSW\n");
- if (ipsw_extract_build_manifest(ipsw, &buildmanifest) < 0) {
+ if (ipsw_extract_build_manifest(ipsw, &buildmanifest, &tss_enabled) < 0) {
error("ERROR: Unable to extract BuildManifest from %s\n", ipsw);
return -1;
}
@@ -157,16 +157,10 @@ int main(int argc, char* argv[]) {
/* print iOS information from the manifest */
build_manifest_print_information(buildmanifest);
- // devices are listed in order from oldest to newest
- // so we'll need their ECID
- if (client->device->index > DEVICE_IPOD2G) {
- 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) {
- error("ERROR: Unable to find device ECID\n");
- return -1;
- }
- debug("Found ECID %llu\n", client->ecid);
+ if (client->flags & FLAG_CUSTOM) {
+ /* prevent signing custom firmware */
+ tss_enabled = 0;
+ info("Custom firmware requested. Disabled TSS request.\n");
}
// choose whether this is an upgrade or a restore (default to upgrade)
@@ -194,22 +188,29 @@ int main(int argc, char* argv[]) {
/* print information about current build identity */
build_identity_print_information(build_identity);
- if (client->flags & FLAG_CUSTOM > 0) {
- if (client->device->index > DEVICE_IPOD2G) {
- if (get_shsh_blobs(client, ecid, build_identity, &client->tss) < 0) {
- error("ERROR: Unable to get SHSH blobs for this device\n");
- return -1;
- }
+ /* retrieve shsh blobs if required */
+ if (tss_enabled) {
+ 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) {
+ error("ERROR: Unable to find device ECID\n");
+ return -1;
}
+ info("Found ECID %llu\n", client->ecid);
- /* verify if we have tss records if required */
- if ((client->device->index > DEVICE_IPOD2G) && (client->tss == NULL)) {
- error("ERROR: Unable to proceed without a tss record.\n");
- plist_free(buildmanifest);
+ if (get_shsh_blobs(client, client->ecid, build_identity, &client->tss) < 0) {
+ error("ERROR: Unable to get SHSH blobs for this device\n");
return -1;
}
}
+ /* verify if we have tss records if required */
+ if ((tss_enabled) && (client->tss == NULL)) {
+ error("ERROR: Unable to proceed without a TSS record.\n");
+ plist_free(buildmanifest);
+ return -1;
+ }
+
// Extract filesystem from IPSW and return its name
char* filesystem = NULL;
if (ipsw_extract_filesystem(client->ipsw, build_identity, &filesystem) < 0) {
@@ -432,11 +433,6 @@ int get_cpid(struct idevicerestore_client_t* client, uint32_t* cpid) {
}
int get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid) {
- if(client->device->index <= DEVICE_IPOD2G) {
- *ecid = 0;
- return 0;
- }
-
switch (client->mode->index) {
case MODE_NORMAL:
if (normal_get_ecid(client->uuid, ecid) < 0) {
@@ -494,13 +490,16 @@ int get_shsh_blobs(struct idevicerestore_client_t* client, uint64_t ecid, plist_
return -1;
}
- info("Sending TSS request\n");
+ info("Sending TSS request... ");
response = tss_send_request(request);
if (response == NULL) {
+ info("ERROR: Unable to send TSS request\n");
plist_free(request);
return -1;
}
+ info("received SHSH blobs\n");
+
plist_free(request);
*tss = response;
return 0;
@@ -556,7 +555,6 @@ int ipsw_get_component_by_path(const char* ipsw, plist_t tss, const char* path,
}
if (tss) {
- info("Signing img3...\n");
img3 = img3_parse_file(component_data, component_size);
if (img3 == NULL) {
error("ERROR: Unable to parse IMG3: %s\n", component_name);
@@ -572,6 +570,7 @@ int ipsw_get_component_by_path(const char* ipsw, plist_t tss, const char* path,
return -1;
}
+ info("Signing %s\n", component_name);
if (img3_replace_signature(img3, component_blob) < 0) {
error("ERROR: Unable to replace IMG3 signature\n");
free(component_blob);
diff --git a/src/ipsw.c b/src/ipsw.c
index 9cd7290..d3f8839 100644
--- a/src/ipsw.c
+++ b/src/ipsw.c
@@ -173,10 +173,12 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, char** pbuffer,
return 0;
}
-int ipsw_extract_build_manifest(const char* ipsw, plist_t* buildmanifest) {
+int ipsw_extract_build_manifest(const char* ipsw, plist_t* buildmanifest, int *tss_enabled) {
int size = 0;
char* data = NULL;
+ *tss_enabled = 0;
+
/* older devices don't require personalized firmwares and use a BuildManifesto.plist */
if (ipsw_extract_to_memory(ipsw, "BuildManifesto.plist", &data, &size) == 0) {
plist_from_xml(data, size, buildmanifest);
@@ -188,6 +190,7 @@ int ipsw_extract_build_manifest(const char* ipsw, plist_t* buildmanifest) {
/* whereas newer devices do not require personalized firmwares and use a BuildManifest.plist */
if (ipsw_extract_to_memory(ipsw, "BuildManifest.plist", &data, &size) == 0) {
+ *tss_enabled = 1;
plist_from_xml(data, size, buildmanifest);
return 0;
}
diff --git a/src/ipsw.h b/src/ipsw.h
index f1694ef..bd8ffc4 100644
--- a/src/ipsw.h
+++ b/src/ipsw.h
@@ -38,7 +38,7 @@ typedef struct {
} ipsw_file;
int ipsw_extract_to_memory(const char* ipsw, const char* infile, char** pbuffer, uint32_t* psize);
-int ipsw_extract_build_manifest(const char* ipsw, plist_t* buildmanifest);
+int ipsw_extract_build_manifest(const char* ipsw, plist_t* buildmanifest, int *tss_enabled);
void ipsw_free_file(ipsw_file* file);
#ifdef __cplusplus
diff --git a/src/recovery.c b/src/recovery.c
index 6a38343..40b207e 100644
--- a/src/recovery.c
+++ b/src/recovery.c
@@ -95,7 +95,7 @@ int recovery_open_with_timeout(struct idevicerestore_client_t* client) {
return -1;
}
- sleep(2);
+ sleep(4);
debug("Retrying connection...\n");
}
@@ -123,27 +123,57 @@ int recovery_check_mode() {
return 0;
}
+static int recovery_enable_autoboot(struct idevicerestore_client_t* client) {
+ irecv_error_t recovery_error = IRECV_E_SUCCESS;
+
+ recovery_error = irecv_setenv(client->recovery->client, "auto-boot", "true");
+ if (recovery_error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to set auto-boot environmental variable\n");
+ return -1;
+ }
+
+ recovery_error = irecv_send_command(client->recovery->client, "saveenv");
+ if (recovery_error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to save environmental variable\n");
+ return -1;
+ }
+
+ return 0;
+}
+
int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build_identity) {
idevice_t device = NULL;
restored_client_t restore = NULL;
- // upload data to make device boot restore mode
+ /* upload data to make device boot restore mode */
+
+ if (recovery_enable_autoboot(client) < 0) {
+ return -1;
+ }
+
+ /* send iBEC and run it */
if (recovery_send_ibec(client, build_identity) < 0) {
error("ERROR: Unable to send iBEC\n");
return -1;
}
- sleep(2);
+ /* this must be long enough to allow the device to run the iBEC */
+ /* FIXME: Probably better to detect if the device is back then */
+ sleep(4);
+
+ /* send logo and show it */
if (recovery_send_applelogo(client, build_identity) < 0) {
error("ERROR: Unable to send AppleLogo\n");
return -1;
}
+ /* send devicetree and load it */
if (recovery_send_devicetree(client, build_identity) < 0) {
error("ERROR: Unable to send DeviceTree\n");
return -1;
}
+ /* send ramdisk and run it */
if (recovery_send_ramdisk(client, build_identity) < 0) {
error("ERROR: Unable to send Ramdisk\n");
return -1;
@@ -155,9 +185,6 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
printf("Hit any key to continue...");
getchar();
- info("Resetting recovery mode connection...\n");
- irecv_reset(client->recovery->client);
-
if (recovery_send_kernelcache(client, build_identity) < 0) {
error("ERROR: Unable to send KernelCache\n");
return -1;
@@ -198,6 +225,9 @@ int recovery_send_component(struct idevicerestore_client_t* client, plist_t buil
info("Resetting recovery mode connection...\n");
irecv_reset(client->recovery->client);
+ if (client->tss)
+ info("%s will be signed\n", component);
+
if (ipsw_get_component_by_path(client->ipsw, client->tss, path, &data, &size) < 0) {
error("ERROR: Unable to get component: %s\n", component);
free(path);
@@ -218,32 +248,10 @@ int recovery_send_component(struct idevicerestore_client_t* client, plist_t buil
return 0;
}
-static int recovery_enable_autoboot(struct idevicerestore_client_t* client) {
- irecv_error_t recovery_error = IRECV_E_SUCCESS;
- //recovery_error = irecv_send_command(client->recovery->client, "setenv auto-boot true");
- recovery_error = irecv_setenv(client->recovery->client, "auto-boot", "true");
- if (recovery_error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to set auto-boot environmental variable\n");
- return -1;
- }
-
- recovery_error = irecv_send_command(client->recovery->client, "saveenv");
- if (recovery_error != IRECV_E_SUCCESS) {
- error("ERROR: Unable to save environmental variable\n");
- return -1;
- }
-
- return 0;
-}
-
int recovery_send_ibec(struct idevicerestore_client_t* client, plist_t build_identity) {
const char* component = "iBEC";
irecv_error_t recovery_error = IRECV_E_SUCCESS;
- if (recovery_enable_autoboot(client) < 0) {
- return -1;
- }
-
if (recovery_send_component(client, build_identity, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
return -1;
diff --git a/src/restore.c b/src/restore.c
index bb3ed96..5e42b97 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -275,7 +275,7 @@ int restore_open_with_timeout(struct idevicerestore_client_t* client) {
const char* restore_progress_string(unsigned int operation) {
switch (operation) {
case WAIT_FOR_STORAGE:
- return "Waiting for Storage Device...";
+ return "Waiting for storage device";
case CREATE_PARTITION_MAP:
return "Creating partition map";
@@ -314,13 +314,13 @@ const char* restore_progress_string(unsigned int operation) {
return "Partition NAND device";
case WAIT_FOR_NAND:
- return "Waiting for NAND...";
+ return "Waiting for NAND";
case WAIT_FOR_DEVICE:
- return "Waiting for Device...";
+ return "Waiting for device";
case LOAD_KERNEL_CACHE:
- return "Loading kernelcache...";
+ return "Loading kernelcache";
case LOAD_NOR:
return "Loading NOR data to flash";
@@ -406,7 +406,7 @@ int restore_send_filesystem(idevice_t device, const char* filesystem) {
// this step sends requested chunks of data from various offsets to asr so
// it can validate the filesystem before installing it
- debug("Preparing to validate the filesystem\n");
+ info("Validating the filesystem\n");
if (asr_perform_validation(asr, filesystem) < 0) {
error("ERROR: ASR was unable to validate the filesystem\n");
asr_close(asr);
@@ -416,13 +416,13 @@ int restore_send_filesystem(idevice_t device, const char* filesystem) {
// once the target filesystem has been validated, ASR then requests the
// entire filesystem to be sent.
- debug("Preparing to send filesystem\n");
+ info("Sending filesystem now...\n");
if (asr_send_payload(asr, filesystem) < 0) {
error("ERROR: Unable to send payload to ASR\n");
asr_close(asr);
return -1;
}
- info("Filesystem finished\n");
+ info("Filesystem sent\n");
asr_close(asr);
return 0;