diff options
| author | 2010-05-25 17:57:51 +0200 | |
|---|---|---|
| committer | 2010-05-25 17:57:51 +0200 | |
| commit | 81ffbe21a73cc2c356e20bba8bdcfd99cbe4e230 (patch) | |
| tree | 0e2052b67304543f6184dd25b35a7db4d427c6d7 | |
| parent | cbf65ca13b37eb156a6d755824a4ff6bc298e063 (diff) | |
| download | idevicerestore-81ffbe21a73cc2c356e20bba8bdcfd99cbe4e230.tar.gz idevicerestore-81ffbe21a73cc2c356e20bba8bdcfd99cbe4e230.tar.bz2 | |
Refactor sending and signing of images to reduce redundant code
| -rw-r--r-- | src/idevicerestore.c | 567 | 
1 files changed, 107 insertions, 460 deletions
| diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 5f3e95e..1422c8c 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -46,11 +46,11 @@ static int idevicerestore_mode = 0;  void usage(int argc, char* argv[]);  int write_file(const char* filename, char* data, int size); -int send_ibec(char* ipsw, plist_t tss); -int send_applelogo(char* ipsw, plist_t tss); -int send_devicetree(char* ipsw, plist_t tss); -int send_ramdisk(char* ipsw, plist_t tss); -int send_kernelcache(char* ipsw, plist_t tss); +int irecv_send_ibec(char* ipsw, plist_t tss); +int irecv_send_applelogo(char* ipsw, plist_t tss); +int irecv_send_devicetree(char* ipsw, plist_t tss); +int irecv_send_ramdisk(char* ipsw, plist_t tss); +int irecv_send_kernelcache(char* ipsw, plist_t tss);  int get_tss_data(plist_t tss, const char* entry, char** path, char** blob);  void device_callback(const idevice_event_t* event, void *user_data); @@ -101,6 +101,7 @@ int main(int argc, char* argv[]) {  	idevice_error_t device_error = IDEVICE_E_SUCCESS;  	lockdownd_error_t lockdown_error = LOCKDOWN_E_SUCCESS; +	/* determine recovery or normal mode */  	info("Checking for device in normal mode...\n");  	device_error = 1;//idevice_new(&device, uuid);  	if (device_error != IDEVICE_E_SUCCESS) { @@ -118,6 +119,7 @@ int main(int argc, char* argv[]) {  		idevicerestore_mode = NORMAL_MODE;  	} +	/* retrieve ECID */  	if (idevicerestore_mode == NORMAL_MODE) {  		lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");  		if (lockdown_error != LOCKDOWN_E_SUCCESS) { @@ -166,6 +168,7 @@ int main(int argc, char* argv[]) {  		return -1;  	} +	/* parse buildmanifest */  	int  buildmanifest_size = 0;  	char* buildmanifest_data = NULL;  	info("Extracting BuildManifest.plist from IPSW\n"); @@ -226,8 +229,8 @@ int main(int argc, char* argv[]) {  		return -1;  	} +	/* place device into recovery mode if required */  	if (idevicerestore_mode == NORMAL_MODE) { -		// Place the device in recovery mode  		info("Entering recovery mode...\n");  		device_error = idevice_new(&device, uuid);  		if (device_error != IDEVICE_E_SUCCESS) { @@ -259,26 +262,27 @@ int main(int argc, char* argv[]) {  		device = NULL;  	} -	if (send_ibec(ipsw, tss_response) < 0) { +	/* upload data to make device boot restore mode */ +	if (irecv_send_ibec(ipsw, tss_response) < 0) {  		error("ERROR: Unable to send iBEC\n");  		plist_free(tss_response);  		return -1;  	}  	sleep(1); -	if (send_applelogo(ipsw, tss_response) < 0) { +	if (irecv_send_applelogo(ipsw, tss_response) < 0) {  		error("ERROR: Unable to send AppleLogo\n");  		plist_free(tss_response);  		return -1;  	} -	if (send_devicetree(ipsw, tss_response) < 0) { +	if (irecv_send_devicetree(ipsw, tss_response) < 0) {  		error("ERROR: Unable to send DeviceTree\n");  		plist_free(tss_response);  		return -1;  	} -	if (send_ramdisk(ipsw, tss_response) < 0) { +	if (irecv_send_ramdisk(ipsw, tss_response) < 0) {  		error("ERROR: Unable to send Ramdisk\n");  		plist_free(tss_response);  		return -1; @@ -288,7 +292,7 @@ int main(int argc, char* argv[]) {  	printf("Hit any key to continue...");  	getchar(); -	if (send_kernelcache(ipsw, tss_response) < 0) { +	if (irecv_send_kernelcache(ipsw, tss_response) < 0) {  		error("ERROR: Unable to send KernelCache\n");  		plist_free(tss_response);  		return -1; @@ -309,6 +313,7 @@ int main(int argc, char* argv[]) {  		//return -1;  	}  	idevice_set_debug_level(5); +  	restored_client_t restore = NULL;  	restored_error_t restore_error = restored_client_new(device, &restore, "idevicerestore");  	if (restore_error != RESTORE_E_SUCCESS) { @@ -329,7 +334,7 @@ int main(int argc, char* argv[]) {  	}  	info("Device has successfully entered restore mode\n"); -	/* start restored service and retrieve port */ +	/* start restore process */  	int quit_flag = 0;  	char* kernelcache = NULL;  	printf("Restore protocol version is %llu.\n", version); @@ -343,18 +348,18 @@ int main(int argc, char* argv[]) {  				char *msgtype = NULL;  				plist_get_string_val(msgtype_node, &msgtype);  				if (!strcmp(msgtype, "ProgressMsg")) { -					restore_error = progress_msg(restore, message); +					restore_error = restored_handle_progress_msg(restore, message);  				} else if (!strcmp(msgtype, "DataRequestMsg")) { -					//restore_error = data_request_msg(device, restore, message, filesystem); +					//restore_error = restored_handle_data_request_msg(device, restore, message, filesystem);  					plist_t datatype_node = plist_dict_get_item(message, "DataType");  					if (datatype_node && PLIST_STRING == plist_get_node_type(datatype_node)) {  						char *datatype = NULL;  						plist_get_string_val(datatype_node, &datatype);  						if (!strcmp(datatype, "SystemImageData")) { -							send_system_data(device, restore, filesystem); +							asr_send_system_image_data_from_file(device, restore, filesystem);  						} else if (!strcmp(datatype, "KernelCache")) { -							send_kernel_data(device, restore, kernelcache); +							restored_send_kernel_cache_from_file(restore, kernelcache);  						} else if (!strcmp(datatype, "NORData")) {  							send_nor_data(device, restore);  						} else { @@ -365,7 +370,7 @@ int main(int argc, char* argv[]) {  					}  				} else if (!strcmp(msgtype, "StatusMsg")) { -					restore_error = status_msg(restore, message); +					restore_error = restored_handle_status_msg(restore, message);  				} else {  					printf("Received unknown message type: %s\n", msgtype); @@ -406,20 +411,20 @@ void usage(int argc, char* argv[]) {  	exit(1);  } -int progress_msg(restored_client_t client, plist_t msg) { +int restored_handle_progress_msg(restored_client_t client, plist_t msg) {  	info("Got progress message\n");  	return 0;  } -int data_request_msg(idevice_t device, restored_client_t client, plist_t msg, const char *filesystem, const char *kernel) { +int restored_handle_data_request_msg(idevice_t device, restored_client_t client, plist_t msg, const char *filesystem, const char *kernel) {  	plist_t datatype_node = plist_dict_get_item(msg, "DataType");  	if (datatype_node && PLIST_STRING == plist_get_node_type(datatype_node)) {  		char *datatype = NULL;  		plist_get_string_val(datatype_node, &datatype);  		if (!strcmp(datatype, "SystemImageData")) { -			send_system_data(device, client, filesystem); +			asr_send_system_image_data_from_file(device, client, filesystem);  		} else if (!strcmp(datatype, "KernelCache")) { -			send_kernel_data(device, client, kernel); +			restored_send_kernel_cache_from_file(client, kernel);  		} else if (!strcmp(datatype, "NORData")) {  			send_nor_data(device, client);  		} else { @@ -431,12 +436,12 @@ int data_request_msg(idevice_t device, restored_client_t client, plist_t msg, co  	return 0;  } -int status_msg(restored_client_t client, plist_t msg) { +int restored_handle_status_msg(restored_client_t client, plist_t msg) {  	info("Got status message\n");  	return 0;  } -int send_system_data(idevice_t device, restored_client_t client, const char *filesystem) { +int asr_send_system_image_data_from_file(idevice_t device, restored_client_t client, const char *filesystem) {  	int i = 0;  	char buffer[0x1000];  	uint32_t recv_bytes = 0; @@ -600,7 +605,7 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil  	return ret;  } -int send_kernel_data(idevice_t device, restored_client_t client, const char *kernel) { +int restored_send_kernel_cache_from_file(restored_client_t client, const char *kernel) {  	printf("Sending kernelcache\n");  	FILE* fd = fopen(kernel, "rb");  	if (fd == NULL) { @@ -703,69 +708,42 @@ int get_tss_data(plist_t tss, const char* entry, char** ppath, char** pblob) {  	return 0;  } -int send_ibec(char* ipsw, plist_t tss) { -	int i = 0; -	irecv_error_t error = 0; -	irecv_client_t client = NULL; -	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; -		} - -		if (i == 0) { -			error("Unable to connect to iBoot\n"); -			return -1; -		} - -		sleep(2); -		info("Retrying connection...\n"); -	} - +static int irecv_send_signed_component(irecv_client_t client, char* ipsw, plist_t tss, char* component) {  	char* path = NULL;  	char* blob = NULL; -	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); -		client = NULL; +	irecv_error_t error = 0; + +	info("Extracting %s from TSS response\n", component); +	if (get_tss_data(tss, component, &path, &blob) < 0) { +		error("ERROR: Unable to get data for TSS %s entry\n", component);  		return -1;  	} -	int ibec_size = 0; -	char* ibec_data = NULL; +	int component_size = 0; +	char* component_data = NULL;  	info("Extracting %s from %s\n", path, ipsw); -	if (ipsw_extract_to_memory(ipsw, path, &ibec_data, &ibec_size)) { +	if (ipsw_extract_to_memory(ipsw, path, &component_data, &component_size) < 0) {  		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(ibec_data, ibec_size); +	img3_file* img3 = img3_parse_file(component_data, component_size);  	if (img3 == NULL) {  		error("ERROR: Unable to parse IMG3: %s\n", path); -		irecv_close(client); -		client = NULL; -		free(ibec_data); +		free(component_data);  		free(path);  		free(blob);  		return -1;  	} -	if (ibec_data) { -		free(ibec_data); -		ibec_data = NULL; +	if (component_data) { +		free(component_data); +		component_data = 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; @@ -779,9 +757,7 @@ int send_ibec(char* ipsw, plist_t tss) {  	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;  	} @@ -799,13 +775,13 @@ int send_ibec(char* ipsw, plist_t tss) {  	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;  	} + +leave:  	if (img3) {  		img3_free(img3);  		img3 = NULL; @@ -819,35 +795,21 @@ int send_ibec(char* ipsw, plist_t tss) {  		path = NULL;  	} -	error = irecv_send_command(client, "go"); -	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;  } -int send_applelogo(char* ipsw, plist_t tss) { -	int i = 0; +static irecv_error_t irecv_open_with_timeout(irecv_client_t *client) {  	irecv_error_t error = 0; -	irecv_client_t client = NULL; -	info("Sending AppleLogo...\n"); +	int i = 0; +  	for (i = 10; i > 0; i--) { -		error = irecv_open(&client); +		error = irecv_open(client);  		if (error == IRECV_E_SUCCESS) {  			break;  		}  		if (i == 0) { -			error("Unable to connect to iBEC\n"); +			error("Unable to connect to recovery device.\n");  			return -1;  		} @@ -855,107 +817,37 @@ int send_applelogo(char* ipsw, plist_t tss) {  		info("Retrying connection...\n");  	} -	char* path = NULL; -	char* blob = NULL; -	info("Extracting data from TSS response\n"); -	if (get_tss_data(tss, "RestoreLogo", &path, &blob) < 0) { -		error("ERROR: Unable to get data for TSS entry\n"); -		irecv_close(client); -		client = NULL; -		return -1; -	} - -	int applelogo_size = 0; -	char* applelogo_data = NULL; -	info("Extracting %s from %s\n", path, ipsw); -	if (ipsw_extract_to_memory(ipsw, path, &applelogo_data, &applelogo_size) < 0) { -		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(applelogo_data, applelogo_size); -	if (img3 == NULL) { -		error("ERROR: Unable to parse IMG3: %s\n", path); -		irecv_close(client); -		client = NULL; -		free(applelogo_data); -		free(path); -		free(blob); -		return -1; -	} -	if (applelogo_data) { -		free(applelogo_data); -		applelogo_data = NULL; -	} +	return error; +} -	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 irecv_send_ibec(char* ipsw, plist_t tss) { +	irecv_error_t error = 0; +	irecv_client_t client = NULL; +	char *component = "iBEC"; +	info("Sending %s...\n", component); -	int size = 0; -	char* data = NULL; -	if (img3_get_data(img3, &data, &size) < 0) { -		error("ERROR: Unable to reconstruct IMG3\n"); +	error = irecv_open_with_timeout(&client); +	if (error != IRECV_E_SUCCESS) {  		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); -	} +	irecv_send_command(client, "setenv auto-boot true"); +	irecv_send_command(client, "saveenv");	 -	error = irecv_send_buffer(client, data, size); -	if (error != IRECV_E_SUCCESS) { -		error("ERROR: Unable to send IMG3: %s\n", path); +	if (irecv_send_signed_component(client, ipsw, tss, component) < 0) { +		error("ERROR: Unable to send %s to device.\n", component);  		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, "setpicture 1"); -	error = irecv_send_command(client, "bgcolor 0 0 0"); +	error = irecv_send_command(client, "go");  	if (error != IRECV_E_SUCCESS) { -		error("ERROR: Unable to set AppleLogo\n"); +		error("ERROR: Unable to execute %s\n", component);  		irecv_close(client);  		client = NULL; -		free(data);  		return -1;  	} @@ -966,126 +858,69 @@ int send_applelogo(char* ipsw, plist_t tss) {  	return 0;  } -int send_devicetree(char* ipsw, plist_t tss) { -	int i = 0; +int irecv_send_applelogo(char* ipsw, plist_t tss) {  	irecv_error_t error = 0;  	irecv_client_t client = NULL; -	info("Sending DeviceTree...\n"); -	for (i = 10; i > 0; i--) { -		error = irecv_open(&client); -		if (error == IRECV_E_SUCCESS) { -			break; -		} +	char *component = "AppleLogo"; -		if (i == 0) { -			error("Unable to connect to iBEC\n"); -			return -1; -		} - -		sleep(3); -		info("Retrying connection...\n"); -	} +	info("Sending %s...\n", component); -	char* path = NULL; -	char* blob = NULL; -	info("Extracting data from TSS response\n"); -	if (get_tss_data(tss, "RestoreDeviceTree", &path, &blob) < 0) { -		error("ERROR: Unable to get data for TSS entry\n"); +	error = irecv_open_with_timeout(&client); +	if (error != IRECV_E_SUCCESS) {  		irecv_close(client);  		client = NULL;  		return -1;  	} -	int devicetree_size = 0; -	char* devicetree_data = NULL; -	info("Extracting %s from %s\n", path, ipsw); -	if (ipsw_extract_to_memory(ipsw, path, &devicetree_data, &devicetree_size) < 0) { -		error("ERROR: Unable to extract %s from %s\n", path, ipsw); +	if (irecv_send_signed_component(client, ipsw, tss, component) < 0) { +		error("ERROR: Unable to send %s to device.\n", component);  		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); -		free(devicetree_data); +	error = irecv_send_command(client, "setpicture 1"); +	error = irecv_send_command(client, "bgcolor 0 0 0"); +	if (error != IRECV_E_SUCCESS) { +		error("ERROR: Unable to set %s\n", component);  		irecv_close(client);  		client = NULL; -		free(path); -		free(blob);  		return -1;  	} -	if (devicetree_data) { -		free(devicetree_data); -		devicetree_data = NULL; -	} -	if (img3_replace_signature(img3, blob) < 0) { -		error("ERROR: Unable to replace IMG3 signature\n"); +	if (client) {  		irecv_close(client);  		client = NULL; -		free(path); -		free(blob); -		return -1; -	} -	if (blob) { -		free(blob); -		blob = NULL;  	} +	return 0; +} -	int size = 0; -	char* data = NULL; -	if (img3_get_data(img3, &data, &size) < 0) { -		error("ERROR: Unable to reconstruct IMG3\n"); +int irecv_send_devicetree(char* ipsw, plist_t tss) { +	irecv_error_t error = 0; +	irecv_client_t client = NULL; +	char *component = "RestoreDeviceTree"; + +	info("Sending %s...\n", component); + +	error = irecv_open_with_timeout(&client); +	if (error != IRECV_E_SUCCESS) {  		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); +	if (irecv_send_signed_component(client, ipsw, tss, component) < 0) { +		error("ERROR: Unable to send %s to device.\n", component);  		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"); +		error("ERROR: Unable to execute %s\n", component);  		irecv_close(client);  		client = NULL; -		free(data);  		return -1;  	} @@ -1096,126 +931,32 @@ int send_devicetree(char* ipsw, plist_t tss) {  	return 0;  } -int send_ramdisk(char* ipsw, plist_t tss) { -	int i = 0; +int irecv_send_ramdisk(char* ipsw, plist_t tss) {  	irecv_error_t error = 0;  	irecv_client_t client = NULL; -	info("Sending Ramdisk...\n"); -	for (i = 10; i > 0; i--) { -		error = irecv_open(&client); -		if (error == IRECV_E_SUCCESS) { -			break; -		} - -		if (i == 0) { -			error("Unable to connect to iBEC\n"); -			return -1; -		} +	char *component = "RestoreRamDisk"; -		sleep(3); -		info("Retrying connection...\n"); -	} - -	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; -	} - -	int ramdisk_size = 0; -	char* ramdisk_data = NULL; -	info("Extracting %s from %s\n", path, ipsw); -	if (ipsw_extract_to_memory(ipsw, path, &ramdisk_data, &ramdisk_size) < 0) { -		error("ERROR: Unable to extract %s from %s\n", path, ipsw); -		irecv_close(client); -		client = NULL; -		free(path); -		free(blob); -		return -1; -	} +	info("Sending %s...\n", component); -	img3_file* img3 = img3_parse_file(ramdisk_data, ramdisk_size); -	if (img3 == NULL) { -		error("ERROR: Unable to parse IMG3: %s\n", path); -		free(ramdisk_data); -		irecv_close(client); -		client = NULL; -		free(path); -		free(blob); -		return -1; -	} -	if (ramdisk_data) { -		free(ramdisk_data); -		ramdisk_data = NULL; -	} - -	if (img3_replace_signature(img3, blob) < 0) { -		error("ERROR: Unable to replace IMG3 signature\n"); +	error = irecv_open_with_timeout(&client); +	if (error != IRECV_E_SUCCESS) {  		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"); +	if (irecv_send_signed_component(client, ipsw, tss, component) < 0) { +		error("ERROR: Unable to send %s to device.\n", component);  		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"); +		error("ERROR: Unable to execute %s\n", component);  		irecv_close(client);  		client = NULL; -		free(data);  		return -1;  	} @@ -1226,126 +967,32 @@ int send_ramdisk(char* ipsw, plist_t tss) {  	return 0;  } -int send_kernelcache(char* ipsw, plist_t tss) { -	int i = 0; +int irecv_send_kernelcache(char* ipsw, plist_t tss) {  	irecv_error_t error = 0;  	irecv_client_t client = NULL; -	info("Sending KernelCache...\n"); -	for (i = 10; i > 0; i--) { -		error = irecv_open(&client); -		if (error == IRECV_E_SUCCESS) { -			break; -		} +	char *component = "RestoreKernelCache"; -		if (i == 0) { -			error("Unable to connect to iBEC\n"); -			return -1; -		} - -		sleep(3); -		info("Retrying connection...\n"); -	} - -	char* path = NULL; -	char* blob = NULL; -	info("Extracting data from TSS response\n"); -	if (get_tss_data(tss, "RestoreKernelCache", &path, &blob) < 0) { -		error("ERROR: Unable to get data for TSS entry\n"); -		irecv_close(client); -		client = NULL; -		return -1; -	} - -	int kernelcache_size = 0; -	char* kernelcache_data = NULL; -	info("Extracting %s from %s\n", path, ipsw); -	if (ipsw_extract_to_memory(ipsw, path, &kernelcache_data, &kernelcache_size) < 0) { -		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); -		free(kernelcache_data); -		irecv_close(client); -		client = NULL; -		free(path); -		free(blob); -		return -1; -	} -	if (kernelcache_data) { -		free(kernelcache_data); -		kernelcache_data = 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; -	} +	info("Sending %s...\n", component); -	int size = 0; -	char* data = NULL; -	if (img3_get_data(img3, &data, &size) < 0) { -		error("ERROR: Unable to reconstruct IMG3\n"); +	error = irecv_open_with_timeout(&client); +	if (error != IRECV_E_SUCCESS) {  		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); +	if (irecv_send_signed_component(client, ipsw, tss, component) < 0) { +		error("ERROR: Unable to send %s to device.\n", component);  		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"); +		error("ERROR: Unable to execute %s\n", component);  		irecv_close(client);  		client = NULL; -		free(data);  		return -1;  	} | 
