diff options
| author | 2010-07-12 00:46:03 -0400 | |
|---|---|---|
| committer | 2010-07-12 00:46:03 -0400 | |
| commit | 021a49be23280ddf9289284e8efff2f239d96d15 (patch) | |
| tree | 0ce618f663ec2431ad335d1ea77119457ef41710 /src | |
| parent | 4bc0f4d97a767d1291ac9f09780198d5680f3e3f (diff) | |
| parent | c41bfdcfc9c8da11249422c70de6bc0884ebd32b (diff) | |
| download | idevicerestore-021a49be23280ddf9289284e8efff2f239d96d15.tar.gz idevicerestore-021a49be23280ddf9289284e8efff2f239d96d15.tar.bz2 | |
Merge branch 'martin'
Diffstat (limited to 'src')
| -rw-r--r-- | src/asr.c | 24 | ||||
| -rw-r--r-- | src/idevicerestore.c | 126 | ||||
| -rw-r--r-- | src/idevicerestore.h | 11 | ||||
| -rw-r--r-- | src/ipsw.c | 22 | ||||
| -rw-r--r-- | src/ipsw.h | 2 | ||||
| -rw-r--r-- | src/restore.c | 62 | 
6 files changed, 186 insertions, 61 deletions
| @@ -87,7 +87,9 @@ int asr_receive(idevice_connection_t asr, plist_t* data) {  	*data = request; -	debug("Received %d bytes:\n%s\n", size, buffer); +	debug("Received %d bytes:\n", size); +	if (idevicerestore_debug) +		debug_plist(request);  	free(buffer);  	return 0;  } @@ -104,7 +106,8 @@ int asr_send(idevice_connection_t asr, plist_t* data) {  	}  	debug("Sent %d bytes:\n", size); -	debug_plist(data); +	if (idevicerestore_debug) +		debug_plist(*data);  	free(buffer);  	return 0;  } @@ -119,6 +122,8 @@ int asr_send_buffer(idevice_connection_t asr, const char* data, uint32_t size) {  		return -1;  	} +	debug("Sent %d bytes buffer\n", bytes); +  	return 0;  } @@ -137,6 +142,7 @@ int asr_perform_validation(idevice_connection_t asr, const char* filesystem) {  	plist_t packet = NULL;  	plist_t packet_info = NULL;  	plist_t payload_info = NULL; +	int attempts = 0;  	file = fopen(filesystem, "rb");  	if (file == NULL) { @@ -172,6 +178,17 @@ int asr_perform_validation(idevice_connection_t asr, const char* filesystem) {  			return -1;  		} +		if (packet == NULL) { +			if (attempts < 5) { +				info("Retrying to receive validation packet... %d\n", attempts); +				attempts++; +				sleep(1); +				continue; +			} +		} + +		attempts = 0; +  		node = plist_dict_get_item(packet, "Command");  		if (!node || plist_get_node_type(node) != PLIST_STRING) {  			error("ERROR: Unable to find command node in validation request\n"); @@ -181,10 +198,7 @@ int asr_perform_validation(idevice_connection_t asr, const char* filesystem) {  		if (!strcmp(command, "OOBData")) {  			asr_handle_oob_data_request(asr, packet, file); - -  			plist_free(packet); -  		} else if(!strcmp(command, "Payload")) {  			plist_free(packet);  			break; diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 7982ed7..00c35c1 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -81,20 +81,20 @@ int main(int argc, char* argv[]) {  			return 0;  		case 'd': -			client->flags &= FLAG_DEBUG; +			client->flags |= FLAG_DEBUG;  			idevicerestore_debug = 1;  			break;  		case 'e': -			client->flags &= FLAG_ERASE; +			client->flags |= FLAG_ERASE;  			break;  		case 'c': -			client->flags &= FLAG_CUSTOM; +			client->flags |= FLAG_CUSTOM;  			break;  		case 'x': -			client->flags &= FLAG_EXCLUDE; +			client->flags |= FLAG_EXCLUDE;  			break;  		case 'u': @@ -149,15 +149,18 @@ int main(int argc, char* argv[]) {  	// extract buildmanifest  	plist_t buildmanifest = NULL;  	info("Extracting BuildManifest from IPSW\n"); -	if (extract_buildmanifest(client, ipsw, &buildmanifest) < 0) { +	if (ipsw_extract_build_manifest(ipsw, &buildmanifest) < 0) {  		error("ERROR: Unable to extract BuildManifest from %s\n", ipsw);  		return -1;  	} +	/* 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("Creating TSS request\n"); +		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"); @@ -170,7 +173,7 @@ int main(int argc, char* argv[]) {  	client->tss = NULL;  	plist_t build_identity = NULL;  	if (client->flags & FLAG_ERASE) { -		build_identity = get_build_identity(client, buildmanifest, 0); +		build_identity = build_manifest_get_build_identity(buildmanifest, 0);  		if (build_identity == NULL) {  			error("ERROR: Unable to find any build identities\n");  			plist_free(buildmanifest); @@ -181,13 +184,16 @@ int main(int argc, char* argv[]) {  		// and list the valid ones  		int i = 0;  		int valid_builds = 0; -		int build_count = get_build_count(buildmanifest); +		int build_count = build_manifest_get_identity_count(buildmanifest);  		for (i = 0; i < build_count; i++) { -			build_identity = get_build_identity(client, buildmanifest, i); +			build_identity = build_manifest_get_build_identity(buildmanifest, i);  			valid_builds++;  		}  	} +	/* 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) { @@ -206,7 +212,7 @@ int main(int argc, char* argv[]) {  	// Extract filesystem from IPSW and return its name  	char* filesystem = NULL; -	if (extract_filesystem(client, client->ipsw, build_identity, &filesystem) < 0) { +	if (ipsw_extract_filesystem(client->ipsw, build_identity, &filesystem) < 0) {  		error("ERROR: Unable to extract filesystem from IPSW\n");  		if (client->tss)  			plist_free(client->tss); @@ -455,32 +461,9 @@ int get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid) {  	return 0;  } -int extract_buildmanifest(struct idevicerestore_client_t* client, const char* ipsw, plist_t* buildmanifest) { -	int size = 0; -	char* data = NULL; -	int device = client->device->index; - -	/* 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); -		return 0; -	} - -	data = NULL; -	size = 0; - -	/* whereas newer devices do not require personalized firmwares and use a BuildManifest.plist */ -	if (ipsw_extract_to_memory(ipsw, "BuildManifest.plist", &data, &size) == 0) { -		plist_from_xml(data, size, buildmanifest); -		return 0; -	} - -	return -1; -} - -plist_t get_build_identity(struct idevicerestore_client_t* client, plist_t buildmanifest, uint32_t identity) { +plist_t build_manifest_get_build_identity(plist_t build_manifest, uint32_t identity) {  	// fetch build identities array from BuildManifest -	plist_t build_identities_array = plist_dict_get_item(buildmanifest, "BuildIdentities"); +	plist_t build_identities_array = plist_dict_get_item(build_manifest, "BuildIdentities");  	if (!build_identities_array || plist_get_node_type(build_identities_array) != PLIST_ARRAY) {  		error("ERROR: Unable to find build identities node\n");  		return NULL; @@ -523,9 +506,9 @@ int get_shsh_blobs(struct idevicerestore_client_t* client, uint64_t ecid, plist_  	return 0;  } -int get_build_count(plist_t buildmanifest) { +int build_manifest_get_identity_count(plist_t build_manifest) {  	// fetch build identities array from BuildManifest -	plist_t build_identities_array = plist_dict_get_item(buildmanifest, "BuildIdentities"); +	plist_t build_identities_array = plist_dict_get_item(build_manifest, "BuildIdentities");  	if (!build_identities_array || plist_get_node_type(build_identities_array) != PLIST_ARRAY) {  		error("ERROR: Unable to find build identities node\n");  		return -1; @@ -535,7 +518,7 @@ int get_build_count(plist_t buildmanifest) {  	return plist_array_get_size(build_identities_array);  } -int extract_filesystem(struct idevicerestore_client_t* client, const char* ipsw, plist_t build_identity, char** filesystem) { +int ipsw_extract_filesystem(const char* ipsw, plist_t build_identity, char** filesystem) {  	char* filename = NULL;  	if (build_identity_get_component_path(build_identity, "OS", &filename) < 0) { @@ -616,6 +599,73 @@ int ipsw_get_component_by_path(const char* ipsw, plist_t tss, const char* path,  	return 0;  } +void build_manifest_print_information(plist_t build_manifest) { +	char* value = NULL; +	plist_t node = NULL; + +	node = plist_dict_get_item(build_manifest, "ProductVersion"); +	if (!node || plist_get_node_type(node) != PLIST_STRING) { +		error("ERROR: Unable to find ProductVersion node\n"); +		return; +	} +	plist_get_string_val(node, &value); + +	info("Product Version: %s\n", value); +	free(value); + +	node = plist_dict_get_item(build_manifest, "ProductBuildVersion"); +	if (!node || plist_get_node_type(node) != PLIST_STRING) { +		error("ERROR: Unable to find ProductBuildVersion node\n"); +		return; +	} +	plist_get_string_val(node, &value); + +	info("Product Build: %s\n", value); +	free(value); + +	node = NULL; +} + +void build_identity_print_information(plist_t build_identity) { +	char* value = NULL; +	plist_t info_node = NULL; +	plist_t node = NULL; + +	info_node = plist_dict_get_item(build_identity, "Info"); +	if (!info_node || plist_get_node_type(info_node) != PLIST_DICT) { +		error("ERROR: Unable to find Info node\n"); +		return; +	} + +	node = plist_dict_get_item(info_node, "Variant"); +	if (!node || plist_get_node_type(node) != PLIST_STRING) { +		error("ERROR: Unable to find Variant node\n"); +		return; +	} +	plist_get_string_val(node, &value); + +	info("Variant: %s\n", value); +	free(value); + +	node = plist_dict_get_item(info_node, "RestoreBehavior"); +	if (!node || plist_get_node_type(node) != PLIST_STRING) { +		error("ERROR: Unable to find RestoreBehavior node\n"); +		return; +	} +	plist_get_string_val(node, &value); + +	if (!strcmp(value, "Erase")) +		info("This restore will erase your device data.\n"); + +	if (!strcmp(value, "Update")) +		info("This restore will update your device without loosing data.\n"); + +	free(value); + +	info_node = NULL; +	node = NULL; +} +  int build_identity_get_component_path(plist_t build_identity, const char* component, char** path) {  	char* filename = NULL; diff --git a/src/idevicerestore.h b/src/idevicerestore.h index f529b5b..4f59a02 100644 --- a/src/idevicerestore.h +++ b/src/idevicerestore.h @@ -34,16 +34,17 @@ extern "C" {  void usage(int argc, char* argv[]);  int check_mode(struct idevicerestore_client_t* client);  int check_device(struct idevicerestore_client_t* client); -int get_build_count(plist_t buildmanifest);  int get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid);  int get_bdid(struct idevicerestore_client_t* client, uint32_t* bdid);  int get_cpid(struct idevicerestore_client_t* client, uint32_t* cpid); -int extract_buildmanifest(struct idevicerestore_client_t* client, const char* ipsw, plist_t* buildmanifest); -plist_t get_build_identity(struct idevicerestore_client_t* client, plist_t buildmanifest, uint32_t identity);  int get_shsh_blobs(struct idevicerestore_client_t* client, uint64_t ecid, plist_t build_identity, plist_t* tss); -int extract_filesystem(struct idevicerestore_client_t* client, const char* ipsw, plist_t buildmanifest, char** filesystem); -int ipsw_get_component_by_path(const char* ipsw, plist_t tss, const char* path, char** data, uint32_t* size); +void build_manifest_print_information(plist_t build_manifest); +plist_t build_manifest_get_build_identity(plist_t build_manifest, uint32_t identity); +int build_manifest_get_build_count(plist_t build_manifest); +void build_identity_print_information(plist_t build_identity);  int build_identity_get_component_path(plist_t build_identity, const char* component, char** path); +int ipsw_extract_filesystem(const char* ipsw, plist_t build_identity, char** filesystem); +int ipsw_get_component_by_path(const char* ipsw, plist_t tss, const char* path, char** data, uint32_t* size);  #ifdef __cplusplus  } @@ -173,6 +173,28 @@ 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 size = 0; +	char* data = NULL; + +	/* 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); +		return 0; +	} + +	data = NULL; +	size = 0; + +	/* whereas newer devices do not require personalized firmwares and use a BuildManifest.plist */ +	if (ipsw_extract_to_memory(ipsw, "BuildManifest.plist", &data, &size) == 0) { +		plist_from_xml(data, size, buildmanifest); +		return 0; +	} + +	return -1; +} +  void ipsw_close(ipsw_archive* archive) {  	if (archive != NULL) {  		zip_unchange_all(archive->zip); @@ -28,6 +28,7 @@ extern "C" {  #include <zip.h>  #include <stdint.h> +#include <plist/plist.h>  typedef struct {  	int index; @@ -37,6 +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);  void ipsw_free_file(ipsw_file* file);  #ifdef __cplusplus diff --git a/src/restore.c b/src/restore.c index 5d45296..bb3ed96 100644 --- a/src/restore.c +++ b/src/restore.c @@ -29,6 +29,7 @@  #include "common.h"  #include "restore.h" +#define WAIT_FOR_STORAGE       11  #define CREATE_PARTITION_MAP   12  #define CREATE_FILESYSTEM      13  #define RESTORE_IMAGE          14 @@ -39,6 +40,8 @@  #define UPDATE_BASEBAND        20  #define FINIALIZE_NAND         21  #define MODIFY_BOOTARGS        26 +#define LOAD_KERNEL_CACHE      27 +#define PARTITION_NAND_DEVICE  28  #define WAIT_FOR_NAND          29  #define UNMOUNT_FILESYSTEM     30  #define WAIT_FOR_DEVICE        33 @@ -178,7 +181,7 @@ void restore_device_callback(const idevice_event_t* event, void* userdata) {  	} else if (event->event == IDEVICE_DEVICE_REMOVE) {  		restore_device_connected = 0; -		client->flags &= FLAG_QUIT; +		client->flags |= FLAG_QUIT;  	}  } @@ -225,7 +228,7 @@ int restore_open_with_timeout(struct idevicerestore_client_t* client) {  		}  	} -	device_error = idevice_event_subscribe(&restore_device_callback, NULL); +	device_error = idevice_event_subscribe(&restore_device_callback, client);  	if (device_error != IDEVICE_E_SUCCESS) {  		error("ERROR: Unable to subscribe to device events\n");  		return -1; @@ -271,6 +274,9 @@ 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..."; +  	case CREATE_PARTITION_MAP:  		return "Creating partition map"; @@ -304,12 +310,18 @@ const char* restore_progress_string(unsigned int operation) {  	case UNMOUNT_FILESYSTEM:  		return "Unmounting filesystems"; +	case PARTITION_NAND_DEVICE: +		return "Partition NAND device"; +  	case WAIT_FOR_NAND:  		return "Waiting for NAND...";  	case WAIT_FOR_DEVICE:  		return "Waiting for Device..."; +	case LOAD_KERNEL_CACHE: +		return "Loading kernelcache..."; +  	case LOAD_NOR:  		return "Loading NOR data to flash"; @@ -339,7 +351,6 @@ int restore_handle_progress_msg(restored_client_t client, plist_t msg) {  	if ((progress > 0) && (progress < 100)) {  		print_progress_bar((double) progress); -  	} else {  		info("%s\n", restore_progress_string(operation));  	} @@ -348,8 +359,27 @@ int restore_handle_progress_msg(restored_client_t client, plist_t msg) {  }  int restore_handle_status_msg(restored_client_t client, plist_t msg) { +	uint64_t value = 0;  	info("Got status message\n");  	debug_plist(msg); + +	plist_t node = plist_dict_get_item(msg, "Status"); +	plist_get_uint_val(node, &value); + +	switch(value) { +		case 0: +			info("Status: Restore Finished\n"); +			break; +		case 6: +			info("Status: Disk Failure\n"); +			break; +		case 14: +			info("Status: Fail\n"); +			break; +		default: +			info("Unknown status message.\n"); +	} +  	return 0;  } @@ -366,8 +396,7 @@ int restore_send_filesystem(idevice_t device, const char* filesystem) {  	}  	info("Connected to ASR\n"); -	// we don't really need to do anything with this, -	// we're just clearing the output buffer +	/* receive Initiate command message */  	if (asr_receive(asr, &data) < 0) {  		error("ERROR: Unable to receive data from ASR\n");  		asr_close(asr); @@ -530,11 +559,12 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*  	}  	plist_dict_insert_item(dict, "NorImageData", norimage_array); -	debug_plist(dict); +	if (idevicerestore_debug) +		debug_plist(dict);  	ret = restored_send(restore, dict);  	if (ret != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send kernelcache data\n"); +		error("ERROR: Unable to send NOR image data data\n");  		plist_free(dict);  		return -1;  	} @@ -569,19 +599,22 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev  		}  		else if (!strcmp(type, "NORData")) { -			if(client->flags & FLAG_EXCLUDE > 0) { +			if((client->flags & FLAG_EXCLUDE) == 0) { +				info("Sending NORData\n");  				if(restore_send_nor(restore, client, build_identity) < 0) {  					error("ERROR: Unable to send NOR data\n");  					return -1;  				}  			} else { -				client->flags &= 1; +				info("Not sending NORData... Quitting...\n"); +				client->flags |= FLAG_QUIT;  			}  		} else {  			// Unknown DataType!!  			debug("Unknown data request received\n"); -			debug_plist(message); +			if (idevicerestore_debug) +				debug_plist(message);  		}  	}  	return 0; @@ -606,6 +639,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  	info("Device has successfully entered restore mode\n");  	restore = client->restore->client; +	device = client->restore->device;  	// start the restore process  	restore_error = restored_start_restore(restore); @@ -629,7 +663,8 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		node = plist_dict_get_item(message, "MsgType");  		if (!node || plist_get_node_type(node) != PLIST_STRING) {  			debug("Unknown message received\n"); -			debug_plist(message); +			if (idevicerestore_debug) +				debug_plist(message);  			plist_free(message);  			message = NULL;  			continue; @@ -659,14 +694,15 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		// at least the "previous error logs" messages usually end up here  		else {  			debug("Unknown message type received\n"); -			debug_plist(message); +			if (idevicerestore_debug) +				debug_plist(message);  		}  		// finally, if any of these message handlers returned -1 then we encountered  		// an unrecoverable error, so we need to bail.  		if (error < 0) {  			error("ERROR: Unable to successfully restore device\n"); -			client->flags &= FLAG_QUIT; +			client->flags |= FLAG_QUIT;  		}  		plist_free(message); | 
