diff options
-rw-r--r-- | src/idevicerestore.c | 57 | ||||
-rw-r--r-- | src/ipsw.c | 5 | ||||
-rw-r--r-- | src/ipsw.h | 2 | ||||
-rw-r--r-- | src/recovery.c | 64 | ||||
-rw-r--r-- | src/restore.c | 14 |
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); @@ -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; } @@ -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; |