diff options
| author | 2010-05-24 16:49:15 -0400 | |
|---|---|---|
| committer | 2010-05-24 16:49:15 -0400 | |
| commit | 4775f164dd40812226c169d3e1921af977013dd1 (patch) | |
| tree | 38afe406281f921daff6e1f9d787d1a086e98912 /src/idevicerestore.c | |
| parent | 92c2879d16148f47ff38f3490f24768bb8eb61f6 (diff) | |
| download | idevicerestore-4775f164dd40812226c169d3e1921af977013dd1.tar.gz idevicerestore-4775f164dd40812226c169d3e1921af977013dd1.tar.bz2 | |
Device now successfully enters restore mode. Now all that's left is copying code over from the other idevicerestore
Diffstat (limited to 'src/idevicerestore.c')
| -rw-r--r-- | src/idevicerestore.c | 593 | 
1 files changed, 383 insertions, 210 deletions
| diff --git a/src/idevicerestore.c b/src/idevicerestore.c index ec449d9..f9fd116 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -222,203 +222,33 @@ int main(int argc, char* argv[]) {  	if (send_ibec(ipsw, tss_response) < 0) {  		error("ERROR: Unable to send iBEC\n"); -		return -1; -	} - -	// Reconnect to iBEC -	info("Connecting to iBEC\n"); -	recovery_error = irecv_open(&recovery); -	while (recovery_error != IRECV_E_SUCCESS) { -		sleep(1); -		info("Retrying connection...\n"); -		recovery_error = irecv_open(&recovery); -		if (recovery_error == IRECV_E_SUCCESS) { -			break; -		} -	} - -	// Sending DeviceTree -	info("Extracting DeviceTree from IPSW\n"); -	plist_t devicetree_entry = plist_dict_get_item(tss_response, "RestoreDeviceTree"); -	if (!devicetree_entry || plist_get_node_type(devicetree_entry) != PLIST_DICT) { -		error("ERROR: Unable to find DeviceTree entry in TSS response\n");  		plist_free(tss_response); -		irecv_close(recovery);  		return -1;  	} - -	char* devicetree_path = NULL; -	plist_t devicetree_path_node = plist_dict_get_item(devicetree_entry, "Path"); -	if (!devicetree_path_node || plist_get_node_type(devicetree_path_node) != PLIST_STRING) { -		error("ERROR: Unable to find DeviceTree path in entry\n"); -		plist_free(tss_response); -		plist_free(devicetree_entry); -		irecv_close(recovery); -		recovery = NULL; -		return -1; -	} -	plist_get_string_val(devicetree_path_node, &devicetree_path); - -	char* devicetree_blob = NULL; -	uint64_t devicetree_blob_size = 0; -	plist_t devicetree_blob_node = plist_dict_get_item(devicetree_entry, "Blob"); -	if (!devicetree_blob_node || plist_get_node_type(devicetree_blob_node) != PLIST_DATA) { -		error("ERROR: Unable to find DeviceTree blob in entry\n"); -		plist_free(tss_response); -		plist_free(devicetree_entry); -		irecv_close(recovery); -		recovery = NULL; -		return -1; -	} -	plist_get_data_val(devicetree_blob_node, &devicetree_blob, &devicetree_blob_size); -	plist_free(devicetree_blob_node); -	plist_free(devicetree_entry); - -	ipsw_file* devicetree = ipsw_extract_file(ipsw, devicetree_path); -	if (devicetree == NULL) { -		error("ERROR: Unable to extract %s from IPSW\n", devicetree_path); -		irecv_close(recovery); -		recovery = NULL; -		return -1; -	} - -	img3_file* devicetree_img3 = img3_parse_file(devicetree->data, devicetree->size); -	if (devicetree_img3 == NULL) { -		error("ERROR: Unable to parse IMG3: %s\n", devicetree_path); -		irecv_close(recovery); -		ipsw_free_file(devicetree); -		recovery = NULL; -		return -1; -	} -	ipsw_free_file(devicetree); - -	img3_replace_signature(devicetree_img3, devicetree_blob); -	free(devicetree_blob); - -	int devicetree_size = 0; -	char* devicetree_data = NULL; -	img3_get_data(devicetree_img3, &devicetree_data, &devicetree_size); -	write_file("devicetree.img3", devicetree_data, devicetree_size); -	recovery_error = irecv_send_buffer(recovery, devicetree_data, devicetree_size); -	if (recovery_error != IRECV_E_SUCCESS) { -		error("ERROR: Unable to send IMG3: %s\n", devicetree_path); -		irecv_close(recovery); -		img3_free(devicetree_img3); -		recovery = NULL; -		return -1; -	} -	img3_free(devicetree_img3); - -	recovery_error = irecv_send_command(recovery, "devicetree"); -	if (recovery_error != IRECV_E_SUCCESS) { -		error("ERROR: Unable to execute DeviceTree\n"); -		irecv_close(recovery); -		img3_free(devicetree_img3); -		recovery = NULL; -		return -1; -	} -	free(devicetree_data);  	sleep(1); -	// Sending RestoreRamdisk -	info("Extracting Ramdisk from IPSW\n"); -	plist_t ramdisk_entry = plist_dict_get_item(tss_response, "RestoreRamDisk"); -	if (!ramdisk_entry || plist_get_node_type(ramdisk_entry) != PLIST_DICT) { -		error("ERROR: Unable to find RestoreRamDisk entry in TSS response\n"); +	if (send_devicetree(ipsw, tss_response) < 0) { +		error("ERROR: Unable to send DeviceTree\n");  		plist_free(tss_response); -		irecv_close(recovery);  		return -1;  	} -	char* ramdisk_path = NULL; -	plist_t ramdisk_path_node = plist_dict_get_item(ramdisk_entry, "Path"); -	if (!ramdisk_path_node || plist_get_node_type(ramdisk_path_node) != PLIST_STRING) { -		error("ERROR: Unable to find RestoreRamDisk path in entry\n"); +	if (send_ramdisk(ipsw, tss_response) < 0) { +		error("ERROR: Unable to send Ramdisk\n");  		plist_free(tss_response); -		plist_free(ramdisk_entry); -		irecv_close(recovery); -		recovery = NULL;  		return -1;  	} -	plist_get_string_val(ramdisk_path_node, &ramdisk_path); -	char* ramdisk_blob = NULL; -	uint64_t ramdisk_blob_size = 0; -	plist_t ramdisk_blob_node = plist_dict_get_item(ramdisk_entry, "Blob"); -	if (!ramdisk_blob_node || plist_get_node_type(ramdisk_blob_node) != PLIST_DATA) { -		error("ERROR: Unable to find RestoreRamdisk blob in entry\n"); -		plist_free(tss_response); -		plist_free(ramdisk_entry); -		irecv_close(recovery); -		recovery = NULL; -		return -1; -	} -	plist_get_data_val(ramdisk_blob_node, &ramdisk_blob, &ramdisk_blob_size); -	plist_free(ramdisk_blob_node); -	plist_free(ramdisk_entry); - -	ipsw_file* ramdisk = ipsw_extract_file(ipsw, ramdisk_path); -	if (ramdisk == NULL) { -		error("ERROR: Unable to extract %s from IPSW\n", ramdisk_path); -		irecv_close(recovery); -		recovery = NULL; -		return -1; -	} - -	img3_file* ramdisk_img3 = img3_parse_file(ramdisk->data, ramdisk->size); -	if (ramdisk_img3 == NULL) { -		error("ERROR: Unable to parse IMG3: %s\n", ramdisk_path); -		irecv_close(recovery); -		ipsw_free_file(ramdisk); -		recovery = NULL; -		return -1; -	} -	ipsw_free_file(ramdisk); - -	img3_replace_signature(ramdisk_img3, ramdisk_blob); -	free(ramdisk_blob); - -	int ramdisk_size = 0; -	char* ramdisk_data = NULL; -	img3_get_data(ramdisk_img3, &ramdisk_data, &ramdisk_size); -	write_file("ramdisk.dmg", ramdisk_data, ramdisk_size); -	recovery_error = irecv_send_buffer(recovery, ramdisk_data, ramdisk_size); -	if (recovery_error != IRECV_E_SUCCESS) { -		error("ERROR: Unable to send IMG3: %s\n", ramdisk_path); -		irecv_close(recovery); -		img3_free(ramdisk_img3); -		recovery = NULL; -		return -1; -	} -	img3_free(ramdisk_img3); - -	recovery_error = irecv_send_command(recovery, "ramdisk"); -	if (recovery_error != IRECV_E_SUCCESS) { -		error("ERROR: Unable to execute DeviceTree\n"); -		irecv_close(recovery); -		recovery = NULL; -		return -1; -	} -	free(ramdisk_data); -	irecv_close(recovery); -	recovery = NULL; - -	printf("Please unplug your device, then plug it back in, hit any key to continue\n"); +	printf("Please unplug your device, then plug it back in\n"); +	printf("Hit any key to continue...");  	getchar(); -	// Reconnect to iBEC -	recovery_error = irecv_open(&recovery); -	while (recovery_error != IRECV_E_SUCCESS) { -		sleep(1); -		info("Retrying connection...\n"); -		recovery_error = irecv_open(&recovery); -		if (recovery_error == IRECV_E_SUCCESS) { -			break; -		} +	if (send_kernelcache(ipsw, tss_response) < 0) { +		error("ERROR: Unable to send KernelCache\n"); +		plist_free(tss_response); +		return -1;  	} -	irecv_close(recovery); -	recovery = NULL;  	plist_free(tss_response);  	return 0;  } @@ -470,25 +300,19 @@ int get_tss_data(plist_t tss, const char* entry, char** ppath, char** pblob) {  	plist_t path_node = plist_dict_get_item(node, "Path");  	if (!path_node || plist_get_node_type(path_node) != PLIST_STRING) {  		error("ERROR: Unable to find %s path in entry\n", entry); -		plist_free(node);  		return -1;  	}  	plist_get_string_val(path_node, &path); -	plist_free(path_node);  	char* blob = NULL;  	uint64_t blob_size = 0;  	plist_t blob_node = plist_dict_get_item(node, "Blob");  	if (!blob_node || plist_get_node_type(blob_node) != PLIST_DATA) {  		error("ERROR: Unable to find %s blob in entry\n", entry); -		plist_free(node);  		free(path);  		return -1;  	} -  	plist_get_data_val(blob_node, &blob, &blob_size); -	plist_free(blob_node); -	plist_free(node);  	*ppath = path;  	*pblob = blob; @@ -497,23 +321,29 @@ int get_tss_data(plist_t tss, const char* entry, char** ppath, char** pblob) {  int send_ibec(char* ipsw, plist_t tss) {  	int i = 0; +	irecv_error_t error = 0;  	irecv_client_t client = NULL; -	info("Connecting to iBoot...\n"); -	irecv_error_t error = irecv_open(&client); +	info("Sending iBEC...\n");  	for (i = 10; i > 0; i--) { +		error = irecv_open(&client);  		if (error == IRECV_E_SUCCESS) {  			irecv_send_command(client, "setenv auto-boot true");  			irecv_send_command(client, "saveenv");  			break;  		} -		sleep(1); + +		if (i == 0) { +			error("Unable to connect to iBoot\n"); +			return -1; +		} + +		sleep(2);  		info("Retrying connection...\n"); -		error = irecv_open(&client);  	}  	char* path = NULL;  	char* blob = NULL; -	info("Extracting iBEC data from TSS response\n"); +	info("Extracting data from TSS response\n");  	if (get_tss_data(tss, "iBEC", &path, &blob) < 0) {  		error("ERROR: Unable to get data for TSS entry\n");  		irecv_close(client); @@ -571,8 +401,16 @@ int send_ibec(char* ipsw, plist_t tss) {  		return -1;  	} -	path = strrchr(path, '/'); -	write_file(path + 1, data, size); +	if (idevicerestore_debug) { +		char* out = strrchr(path, '/'); +		if (out != NULL) { +			out++; +		} else { +			out = path; +		} +		write_file(out, data, size); +	} +  	error = irecv_send_buffer(client, data, size);  	if (error != IRECV_E_SUCCESS) {  		error("ERROR: Unable to send IMG3: %s\n", path); @@ -605,61 +443,396 @@ int send_ibec(char* ipsw, plist_t tss) {  		return -1;  	} -	irecv_close(client); -	client = NULL; +	if (client) { +		irecv_close(client); +		client = NULL; +	}  	return 0;  }  int send_devicetree(char* ipsw, plist_t tss) {  	int i = 0; -	info("Sending devicetree\n"); +	irecv_error_t error = 0;  	irecv_client_t client = NULL; -	irecv_error_t error = irecv_open(&client); +	info("Sending DeviceTree...\n");  	for (i = 10; i > 0; i--) { +		error = irecv_open(&client);  		if (error == IRECV_E_SUCCESS) {  			break;  		} -		sleep(1); + +		if (i == 0) { +			error("Unable to connect to iBEC\n"); +			return -1; +		} + +		sleep(3);  		info("Retrying connection...\n"); -		error = irecv_open(&client);  	} -	irecv_close(client); +	char* path = NULL; +	char* blob = NULL; +	info("Extracting data from TSS response\n"); +	if (get_tss_data(tss, "DeviceTree", &path, &blob) < 0) { +		error("ERROR: Unable to get data for TSS entry\n"); +		irecv_close(client); +		client = NULL; +		return -1; +	} + +	info("Extracting %s from %s\n", path, ipsw); +	ipsw_file* devicetree = ipsw_extract_file(ipsw, path); +	if (devicetree == NULL) { +		error("ERROR: Unable to extract %s from %s\n", path, ipsw); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} + +	img3_file* img3 = img3_parse_file(devicetree->data, devicetree->size); +	if (img3 == NULL) { +		error("ERROR: Unable to parse IMG3: %s\n", path); +		ipsw_free_file(devicetree); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} +	if (devicetree) { +		ipsw_free_file(devicetree); +		devicetree = NULL; +	} + +	if (img3_replace_signature(img3, blob) < 0) { +		error("ERROR: Unable to replace IMG3 signature\n"); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} +	if (blob) { +		free(blob); +		blob = NULL; +	} + +	int size = 0; +	char* data = NULL; +	if (img3_get_data(img3, &data, &size) < 0) { +		error("ERROR: Unable to reconstruct IMG3\n"); +		irecv_close(client); +		img3_free(img3); +		client = NULL; +		free(path); +		return -1; +	} + +	if (idevicerestore_debug) { +		char* out = strrchr(path, '/'); +		if (out != NULL) { +			out++; +		} else { +			out = path; +		} +		write_file(out, data, size); +	} + +	error = irecv_send_buffer(client, data, size); +	if (error != IRECV_E_SUCCESS) { +		error("ERROR: Unable to send IMG3: %s\n", path); +		irecv_close(client); +		img3_free(img3); +		client = NULL; +		free(data); +		free(path); +		return -1; +	} +	if (img3) { +		img3_free(img3); +		img3 = NULL; +	} +	if (data) { +		free(data); +		data = NULL; +	} +	if (path) { +		free(path); +		path = NULL; +	} + +	error = irecv_send_command(client, "devicetree"); +	if (error != IRECV_E_SUCCESS) { +		error("ERROR: Unable to execute DeviceTree\n"); +		irecv_close(client); +		client = NULL; +		free(data); +		return -1; +	} + +	if (client) { +		irecv_close(client); +		client = NULL; +	}  	return 0;  }  int send_ramdisk(char* ipsw, plist_t tss) {  	int i = 0; -	info("Sending ramdisk\n"); +	irecv_error_t error = 0;  	irecv_client_t client = NULL; -	irecv_error_t error = irecv_open(&client); +	info("Sending Ramdisk...\n");  	for (i = 10; i > 0; i--) { +		error = irecv_open(&client);  		if (error == IRECV_E_SUCCESS) {  			break;  		} -		sleep(1); + +		if (i == 0) { +			error("Unable to connect to iBEC\n"); +			return -1; +		} + +		sleep(3);  		info("Retrying connection...\n"); -		error = irecv_open(&client);  	} -	irecv_close(client); +	char* path = NULL; +	char* blob = NULL; +	info("Extracting data from TSS response\n"); +	if (get_tss_data(tss, "RestoreRamDisk", &path, &blob) < 0) { +		error("ERROR: Unable to get data for TSS entry\n"); +		irecv_close(client); +		client = NULL; +		return -1; +	} + +	info("Extracting %s from %s\n", path, ipsw); +	ipsw_file* ramdisk = ipsw_extract_file(ipsw, path); +	if (ramdisk == NULL) { +		error("ERROR: Unable to extract %s from %s\n", path, ipsw); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} + +	img3_file* img3 = img3_parse_file(ramdisk->data, ramdisk->size); +	if (img3 == NULL) { +		error("ERROR: Unable to parse IMG3: %s\n", path); +		ipsw_free_file(ramdisk); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} +	if (ramdisk) { +		ipsw_free_file(ramdisk); +		ramdisk = NULL; +	} + +	if (img3_replace_signature(img3, blob) < 0) { +		error("ERROR: Unable to replace IMG3 signature\n"); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} +	if (blob) { +		free(blob); +		blob = NULL; +	} + +	int size = 0; +	char* data = NULL; +	if (img3_get_data(img3, &data, &size) < 0) { +		error("ERROR: Unable to reconstruct IMG3\n"); +		irecv_close(client); +		img3_free(img3); +		client = NULL; +		free(path); +		return -1; +	} + +	if (idevicerestore_debug) { +		char* out = strrchr(path, '/'); +		if (out != NULL) { +			out++; +		} else { +			out = path; +		} +		write_file(out, data, size); +	} + +	error = irecv_send_buffer(client, data, size); +	if (error != IRECV_E_SUCCESS) { +		error("ERROR: Unable to send IMG3: %s\n", path); +		irecv_close(client); +		img3_free(img3); +		client = NULL; +		free(data); +		free(path); +		return -1; +	} +	if (img3) { +		img3_free(img3); +		img3 = NULL; +	} +	if (data) { +		free(data); +		data = NULL; +	} +	if (path) { +		free(path); +		path = NULL; +	} + +	error = irecv_send_command(client, "ramdisk"); +	if (error != IRECV_E_SUCCESS) { +		error("ERROR: Unable to execute Ramdisk\n"); +		irecv_close(client); +		client = NULL; +		free(data); +		return -1; +	} + +	if (client) { +		irecv_close(client); +		client = NULL; +	}  	return 0;  }  int send_kernelcache(char* ipsw, plist_t tss) {  	int i = 0; -	info("Sending kernelcache\n"); +	irecv_error_t error = 0;  	irecv_client_t client = NULL; -	irecv_error_t error = irecv_open(&client); +	info("Sending KernelCache...\n");  	for (i = 10; i > 0; i--) { +		error = irecv_open(&client);  		if (error == IRECV_E_SUCCESS) {  			break;  		} -		sleep(1); + +		if (i == 0) { +			error("Unable to connect to iBEC\n"); +			return -1; +		} + +		sleep(3);  		info("Retrying connection...\n"); -		error = irecv_open(&client);  	} -	irecv_close(client); +	char* path = NULL; +	char* blob = NULL; +	info("Extracting data from TSS response\n"); +	if (get_tss_data(tss, "KernelCache", &path, &blob) < 0) { +		error("ERROR: Unable to get data for TSS entry\n"); +		irecv_close(client); +		client = NULL; +		return -1; +	} + +	info("Extracting %s from %s\n", path, ipsw); +	ipsw_file* kernelcache = ipsw_extract_file(ipsw, path); +	if (kernelcache == NULL) { +		error("ERROR: Unable to extract %s from %s\n", path, ipsw); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} + +	img3_file* img3 = img3_parse_file(kernelcache->data, kernelcache->size); +	if (img3 == NULL) { +		error("ERROR: Unable to parse IMG3: %s\n", path); +		ipsw_free_file(kernelcache); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} +	if (kernelcache) { +		ipsw_free_file(kernelcache); +		kernelcache = NULL; +	} + +	if (img3_replace_signature(img3, blob) < 0) { +		error("ERROR: Unable to replace IMG3 signature\n"); +		irecv_close(client); +		client = NULL; +		free(path); +		free(blob); +		return -1; +	} +	if (blob) { +		free(blob); +		blob = NULL; +	} + +	int size = 0; +	char* data = NULL; +	if (img3_get_data(img3, &data, &size) < 0) { +		error("ERROR: Unable to reconstruct IMG3\n"); +		irecv_close(client); +		img3_free(img3); +		client = NULL; +		free(path); +		return -1; +	} + +	if (idevicerestore_debug) { +		char* out = strrchr(path, '/'); +		if (out != NULL) { +			out++; +		} else { +			out = path; +		} +		write_file(out, data, size); +	} + +	error = irecv_send_buffer(client, data, size); +	if (error != IRECV_E_SUCCESS) { +		error("ERROR: Unable to send IMG3: %s\n", path); +		irecv_close(client); +		img3_free(img3); +		client = NULL; +		free(data); +		free(path); +		return -1; +	} +	if (img3) { +		img3_free(img3); +		img3 = NULL; +	} +	if (data) { +		free(data); +		data = NULL; +	} +	if (path) { +		free(path); +		path = NULL; +	} + +	error = irecv_send_command(client, "bootx"); +	if (error != IRECV_E_SUCCESS) { +		error("ERROR: Unable to execute iBEC\n"); +		irecv_close(client); +		client = NULL; +		free(data); +		return -1; +	} + +	if (client) { +		irecv_close(client); +		client = NULL; +	}  	return 0;  } | 
