From afb36f37770e1b429fcd227904cff6235ee90b5f Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Mon, 12 Jul 2010 14:56:47 +0200 Subject: Be more verbose when reporting about each step of the restore process --- src/restore.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/restore.c b/src/restore.c index bb3ed96..7eed0ae 100644 --- a/src/restore.c +++ b/src/restore.c @@ -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; -- cgit v1.1-32-gdbae From 61831ded8b7775244ddd32683181aebf60ab6807 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:06:44 +0200 Subject: Allow getting the ecid for any device model --- src/idevicerestore.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 00c35c1..93623bc 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -432,11 +432,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) { -- cgit v1.1-32-gdbae From 88e1348858aa8157930066e634b66f3f717be9b6 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:08:54 +0200 Subject: Extend sleep timeouts to allow the device to load --- src/recovery.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/recovery.c b/src/recovery.c index 6a38343..3eec1a3 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"); } @@ -132,7 +132,10 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build 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); if (recovery_send_applelogo(client, build_identity) < 0) { error("ERROR: Unable to send AppleLogo\n"); -- cgit v1.1-32-gdbae From 64f2c23140d23d409989f148a57366e37df468b2 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:11:06 +0200 Subject: Take setup for autoboot out of the ibec sending code --- src/recovery.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/recovery.c b/src/recovery.c index 3eec1a3..cf38b16 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -123,11 +123,34 @@ 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; + } + if (recovery_send_ibec(client, build_identity) < 0) { error("ERROR: Unable to send iBEC\n"); return -1; @@ -221,32 +244,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; -- cgit v1.1-32-gdbae From 38b8439c0b9b4b64aae1c812da322146d0843446 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:13:01 +0200 Subject: Add and improve some comments for restore process --- src/idevicerestore.c | 2 +- src/recovery.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 93623bc..50e2783 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -166,7 +166,7 @@ int main(int argc, char* argv[]) { error("ERROR: Unable to find device ECID\n"); return -1; } - debug("Found ECID %llu\n", client->ecid); + info("Found ECID %llu\n", client->ecid); } // choose whether this is an upgrade or a restore (default to upgrade) diff --git a/src/recovery.c b/src/recovery.c index cf38b16..015e9ac 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -151,6 +151,7 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build return -1; } + /* send iBEC and run it */ if (recovery_send_ibec(client, build_identity) < 0) { error("ERROR: Unable to send iBEC\n"); return -1; @@ -160,16 +161,19 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build /* 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; -- cgit v1.1-32-gdbae From 50c1616ff66ccb4e674405659cb2e6f8207bc915 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:13:37 +0200 Subject: Refactor tss request requirements to work with iPhone 3G and iOS 4 This gets rid of the device model checking code and allows devices like the iPhone 3G to get shsh blobs as required by iOS 4. The requirement if the components need to be signed is determined by which kind of manifest filename is within the IPSW. --- src/idevicerestore.c | 34 +++++++++++++++++++--------------- src/ipsw.c | 5 ++++- src/ipsw.h | 2 +- src/recovery.c | 3 +++ 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 50e2783..32dd736 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,9 +157,15 @@ int main(int argc, char* argv[]) { /* print iOS information from the manifest */ build_manifest_print_information(buildmanifest); + if (client->flags & FLAG_CUSTOM) { + /* prevent signing custom firmware */ + tss_enabled = 0; + info("Custom firmware requested. Disabled TSS request.\n"); + } + // devices are listed in order from oldest to newest // so we'll need their ECID - if (client->device->index > DEVICE_IPOD2G) { + 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) { @@ -194,22 +200,20 @@ 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; - } - } - - /* 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 (tss_enabled) { + 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) { 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 015e9ac..28256b5 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -228,6 +228,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); -- cgit v1.1-32-gdbae From 803d4af2ef109f39a512c23b74e3b99cc3bde61b Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:47:51 +0200 Subject: Name restore progress strings cosistently --- src/restore.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/restore.c b/src/restore.c index 7eed0ae..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"; -- cgit v1.1-32-gdbae From 18e9411aac155ff4aa35ac1c50e752102b1ed531 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:50:29 +0200 Subject: Move ecid retrieval code right before shsh blob retrieval --- src/idevicerestore.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 32dd736..90fe4bc 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -163,18 +163,6 @@ int main(int argc, char* argv[]) { info("Custom firmware requested. Disabled TSS request.\n"); } - // devices are listed in order from oldest to newest - // so we'll need their ECID - 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); - } - // choose whether this is an upgrade or a restore (default to upgrade) client->tss = NULL; plist_t build_identity = NULL; @@ -200,7 +188,16 @@ int main(int argc, char* argv[]) { /* print information about current build identity */ build_identity_print_information(build_identity); + /* 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); + 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; -- cgit v1.1-32-gdbae From 4aac570d9bb265a81de4b9c601d1fd9c38fcddc4 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:51:25 +0200 Subject: Do not reset the usb connection twice after uploading the ramdisk --- src/recovery.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/recovery.c b/src/recovery.c index 28256b5..40b207e 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -185,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; -- cgit v1.1-32-gdbae From db6dc7b5310138eb6eb3eb099f22ccde65e3e765 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 14 Jul 2010 04:52:15 +0200 Subject: Further improve some output to better guide the user --- src/idevicerestore.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 90fe4bc..f3fdbdc 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -206,7 +206,7 @@ int main(int argc, char* argv[]) { /* verify if we have tss records if required */ if ((tss_enabled) && (client->tss == NULL)) { - error("ERROR: Unable to proceed without a tss record.\n"); + error("ERROR: Unable to proceed without a TSS record.\n"); plist_free(buildmanifest); return -1; } @@ -490,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; @@ -552,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); @@ -568,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); -- cgit v1.1-32-gdbae