diff options
Diffstat (limited to 'src/restore.c')
| -rw-r--r-- | src/restore.c | 1835 | 
1 files changed, 1159 insertions, 676 deletions
| diff --git a/src/restore.c b/src/restore.c index d3828f9..12f837c 100644 --- a/src/restore.c +++ b/src/restore.c @@ -30,6 +30,7 @@  #include <string.h>  #include <unistd.h>  #include <libgen.h> +#include <math.h>  #include <libimobiledevice/restore.h>  #include <libimobiledevice/property_list_service.h>  #include <libimobiledevice-glue/thread.h> @@ -126,7 +127,7 @@ int restore_client_new(struct idevicerestore_client_t* client)  {  	struct restore_client_t* restore = (struct restore_client_t*) malloc(sizeof(struct restore_client_t));  	if (restore == NULL) { -		error("ERROR: Out of memory\n"); +		logger(LL_ERROR, "Out of memory\n");  		return -1;  	} @@ -183,12 +184,12 @@ static int restore_idevice_new(struct idevicerestore_client_t* client, idevice_t  		}  		device_error = idevice_new(&dev, devices[j]);  		if (device_error != IDEVICE_E_SUCCESS) { -			debug("%s: can't open device with UDID %s\n", __func__, devices[j]); +			logger(LL_DEBUG, "%s: can't open device with UDID %s\n", __func__, devices[j]);  			continue;  		}  		if (restored_client_new(dev, &restore, "idevicerestore") != RESTORE_E_SUCCESS) { -			debug("%s: can't connect to restored on device with UDID %s\n", __func__, devices[j]); +			logger(LL_DEBUG, "%s: can't connect to restored on device with UDID %s\n", __func__, devices[j]);  			continue;  		} @@ -284,7 +285,7 @@ irecv_device_t restore_get_irecv_device(struct idevicerestore_client_t* client)  	if (client->srnm == NULL) {  		if (restored_get_value(restore, "SerialNumber", &node) == RESTORE_E_SUCCESS) {  			plist_get_string_val(node, &client->srnm); -			info("INFO: device serial number is %s\n", client->srnm); +			logger(LL_INFO, "INFO: device serial number is %s\n", client->srnm);  			plist_free(node);  			node = NULL;  		} @@ -294,7 +295,7 @@ irecv_device_t restore_get_irecv_device(struct idevicerestore_client_t* client)  	restored_client_free(restore);  	idevice_free(device);  	if (restore_error != RESTORE_E_SUCCESS || !node || plist_get_node_type(node) != PLIST_STRING) { -		error("ERROR: Unable to get HardwareModel from restored\n"); +		logger(LL_ERROR, "Unable to get HardwareModel from restored\n");  		plist_free(node);  		return NULL;  	} @@ -315,7 +316,7 @@ int restore_is_image4_supported(struct idevicerestore_client_t* client)  	restored_error_t restore_error = RESTORE_E_SUCCESS;  	if (idevice_new(&device, client->udid) != IDEVICE_E_SUCCESS) { -		error("ERROR: Could not connect to device %s\n", client->udid); +		logger(LL_ERROR, "Could not connect to device %s\n", client->udid);  		return -1;  	} @@ -350,14 +351,14 @@ int restore_reboot(struct idevicerestore_client_t* client)  {  	if(client->restore == NULL) {  		if (restore_open_with_timeout(client) < 0) { -			error("ERROR: Unable to open device in restore mode\n"); +			logger(LL_ERROR, "Unable to open device in restore mode\n");  			return -1;  		}  	}  	mutex_lock(&client->device_event_mutex); -	info("Rebooting restore mode device...\n"); +	logger(LL_INFO, "Rebooting restore mode device...\n");  	restored_reboot(client->restore->client);  	restored_client_free(client->restore->client); @@ -378,7 +379,7 @@ static int restore_is_current_device(struct idevicerestore_client_t* client, con  		return 0;  	}  	if (!client->ecid) { -		error("ERROR: %s: no ECID given in client data\n", __func__); +		logger(LL_ERROR, "%s: no ECID given in client data\n", __func__);  		return 0;  	} @@ -391,21 +392,21 @@ static int restore_is_current_device(struct idevicerestore_client_t* client, con  	device_error = idevice_new(&device, udid);  	if (device_error != IDEVICE_E_SUCCESS) { -		debug("%s: can't open device with UDID %s\n", __func__, udid); +		logger(LL_DEBUG, "%s: can't open device with UDID %s\n", __func__, udid);  		return 0;  	}  	restore_error = restored_client_new(device, &restored, "idevicerestore");  	if (restore_error != RESTORE_E_SUCCESS) { -		debug("%s: can't connect to restored\n", __func__); +		logger(LL_DEBUG, "%s: can't connect to restored\n", __func__);  		idevice_free(device);  		return 0;  	}  	restore_error = restored_query_type(restored, &type, &version);  	if ((restore_error == RESTORE_E_SUCCESS) && type && (strcmp(type, "com.apple.mobile.restored") == 0)) { -		debug("%s: Connected to %s, version %d\n", __func__, type, (int)version); +		logger(LL_DEBUG, "%s: Connected to %s, version %d\n", __func__, type, (int)version);  	} else { -		debug("%s: device %s is not in restore mode\n", __func__, udid); +		logger(LL_DEBUG, "%s: device %s is not in restore mode\n", __func__, udid);  		restored_client_free(restored);  		idevice_free(device);  		return 0; @@ -414,7 +415,7 @@ static int restore_is_current_device(struct idevicerestore_client_t* client, con  	plist_t hwinfo = NULL;  	restore_error = restored_query_value(restored, "HardwareInfo", &hwinfo);  	if ((restore_error != RESTORE_E_SUCCESS) || !hwinfo) { -		error("ERROR: %s: Unable to get HardwareInfo from restored\n", __func__); +		logger(LL_ERROR, "%s: Unable to get HardwareInfo from restored\n", __func__);  		restored_client_free(restored);  		idevice_free(device);  		plist_free(hwinfo); @@ -431,7 +432,7 @@ static int restore_is_current_device(struct idevicerestore_client_t* client, con  	plist_free(hwinfo);  	if (this_ecid == 0) { -		error("ERROR: %s: Unable to get ECID from restored\n", __func__); +		logger(LL_ERROR, "%s: Unable to get ECID from restored\n", __func__);  		return 0;  	} @@ -453,7 +454,7 @@ int restore_open_with_timeout(struct idevicerestore_client_t* client)  	}  	if (client->ecid == 0) { -		error("ERROR: no ECID in client data!\n"); +		logger(LL_ERROR, "no ECID in client data!\n");  		return -1;  	} @@ -461,7 +462,7 @@ int restore_open_with_timeout(struct idevicerestore_client_t* client)  	if (client->restore == NULL) {  		client->restore = (struct restore_client_t*) malloc(sizeof(struct restore_client_t));  		if(client->restore == NULL) { -			error("ERROR: Out of memory\n"); +			logger(LL_ERROR, "Out of memory\n");  			return -1;  		}  		memset(client->restore, '\0', sizeof(struct restore_client_t)); @@ -470,11 +471,11 @@ int restore_open_with_timeout(struct idevicerestore_client_t* client)  	restore_device_connected = 0;  	if (!restore_is_current_device(client, client->udid)) { -		error("ERROR: Unable to connect to device in restore mode\n"); +		logger(LL_ERROR, "Unable to connect to device in restore mode\n");  		return -1;  	} -	info("Connecting now...\n"); +	logger(LL_INFO, "Connecting now...\n");  	device_error = idevice_new(&device, client->udid);  	if (device_error != IDEVICE_E_SUCCESS) {  		return -1; @@ -489,9 +490,9 @@ int restore_open_with_timeout(struct idevicerestore_client_t* client)  	restore_error = restored_query_type(restored, &type, &version);  	if ((restore_error == RESTORE_E_SUCCESS) && type && (strcmp(type, "com.apple.mobile.restored") == 0)) {  		client->restore->protocol_version = version; -		info("Connected to %s, version %d\n", type, (int)version); +		logger(LL_INFO, "Connected to %s, version %d\n", type, (int)version);  	} else { -		error("ERROR: Unable to connect to restored, error=%d\n", restore_error); +		logger(LL_ERROR, "Unable to connect to restored, error=%d\n", restore_error);  		restored_client_free(restored);  		idevice_free(device);  		return -1; @@ -650,9 +651,9 @@ typedef struct restore_service_client {  static void* _restore_get_service_client_for_data_request(struct idevicerestore_client_t *client, plist_t message)  { -	if (!client || !client->restore || !client->restore->client || !PLIST_IS_DICT(message)) return NULL; +	if (!client || !client->restore || !client->restore->client) return NULL;  	restore_service_client_t service = (restore_service_client_t)malloc(sizeof(struct restore_service_client)); -	if (!plist_dict_get_item(message, "DataPort")) { +	if (!PLIST_IS_DICT(message) || !plist_dict_get_item(message, "DataPort")) {  		service->client = client->restore->client;  		service->type = SERVICE_TYPE_RESTORED;  		return service; @@ -667,9 +668,9 @@ static void* _restore_get_service_client_for_data_request(struct idevicerestore_  		(char*)data_type_str  	};  	property_list_service_client_t plclient = NULL; -	info("Connecting to %s data port %u\n", data_type_str, data_port); +	logger(LL_INFO, "Connecting to %s data port %u\n", data_type_str, data_port);  	if (property_list_service_client_new(client->restore->device, &svcdesc, &plclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { -		error("ERROR: Failed to start service connection for %s on port %u\n", data_type_str, data_port); +		logger(LL_ERROR, "Failed to start service connection for %s on port %u\n", data_type_str, data_port);  		free(service);  		return NULL;  	} @@ -698,16 +699,22 @@ static int _restore_service_send(restore_service_client_t service, plist_t plist  	return -1;  } -static int _restore_service_recv(restore_service_client_t service, plist_t *plist) +static int _restore_service_recv_timeout(restore_service_client_t service, plist_t *plist, unsigned int timeout)  { +	struct restored_client_private { +		property_list_service_client_t parent; +		char *udid; +		char *label; +		plist_t info; +	};  	if (!service) {  		return -1;  	}  	switch (service->type) {  		case SERVICE_TYPE_RESTORED: -			return restored_receive((restored_client_t)service->client, plist); +			return property_list_service_receive_plist_with_timeout(((struct restored_client_private*)service->client)->parent, plist, timeout);  		case SERVICE_TYPE_PLIST: -			return property_list_service_receive_plist((property_list_service_client_t)service->client, plist); +			return property_list_service_receive_plist_with_timeout((property_list_service_client_t)service->client, plist, timeout);  		default:  			break;  	} @@ -740,12 +747,12 @@ static int restore_handle_previous_restore_log_msg(restored_client_t client, pli  	node = plist_dict_get_item(msg, "PreviousRestoreLog");  	if (!node || plist_get_node_type(node) != PLIST_STRING) { -		debug("Failed to parse restore log from PreviousRestoreLog plist\n"); +		logger(LL_DEBUG, "Failed to parse restore log from PreviousRestoreLog plist\n");  		return -1;  	}  	plist_get_string_val(node, &restorelog); -	info("Previous Restore Log Received:\n%s\n", restorelog); +	logger(LL_VERBOSE, "Previous Restore Log Received:\n%s\n", restorelog);  	free(restorelog);  	return 0; @@ -759,14 +766,14 @@ int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t  	node = plist_dict_get_item(msg, "Operation");  	if (!node || plist_get_node_type(node) != PLIST_UINT) { -		debug("Failed to parse operation from ProgressMsg plist\n"); +		logger(LL_DEBUG, "Failed to parse operation from ProgressMsg plist\n");  		return -1;  	}  	plist_get_uint_val(node, &operation);  	node = plist_dict_get_item(msg, "Progress");  	if (!node || plist_get_node_type(node) != PLIST_UINT) { -		debug("Failed to parse progress from ProgressMsg plist \n"); +		logger(LL_DEBUG, "Failed to parse progress from ProgressMsg plist \n");  		return -1;  	}  	plist_get_uint_val(node, &progress); @@ -781,7 +788,7 @@ int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t  	if ((progress > 0) && (progress <= 100)) {  		if ((int)operation != lastop) { -			info("%s (%d)\n", restore_progress_string(adapted_operation), (int)operation); +			logger(LL_INFO, "%s (%d)\n", restore_progress_string(adapted_operation), (int)operation);  		}  		switch (adapted_operation) {  		case RESTORE_IMAGE: @@ -805,11 +812,11 @@ int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t  		case REQUESTING_EAN_DATA:  			break;  		default: -			debug("Unhandled progress operation %d (%d)\n", adapted_operation, (int)operation); +			logger(LL_DEBUG, "Unhandled progress operation %d (%d)\n", adapted_operation, (int)operation);  			break;  		}  	} else { -		info("%s (%d)\n", restore_progress_string(adapted_operation), (int)operation); +		logger(LL_INFO, "%s (%d)\n", restore_progress_string(adapted_operation), (int)operation);  	}  	lastop = (int)operation; @@ -821,7 +828,7 @@ int restore_handle_status_msg(struct idevicerestore_client_t* client, plist_t ms  	int result = 0;  	uint64_t value = 0;  	char* log = NULL; -	info("Got status message\n"); +	logger(LL_INFO, "Got status message\n");  	// read status code  	plist_t node = plist_dict_get_item(msg, "Status"); @@ -829,34 +836,34 @@ int restore_handle_status_msg(struct idevicerestore_client_t* client, plist_t ms  	switch(value) {  		case 0: -			info("Status: Restore Finished\n"); +			logger(LL_INFO, "Status: Restore Finished\n");  			restore_finished = 1;  			break;  		case 0xFFFFFFFFFFFFFFFFLL: -			info("Status: Verification Error\n"); +			logger(LL_INFO, "Status: Verification Error\n");  			break;  		case 6: -			info("Status: Disk Failure\n"); +			logger(LL_INFO, "Status: Disk Failure\n");  			break;  		case 14: -			info("Status: Fail\n"); +			logger(LL_INFO, "Status: Fail\n");  			break;  		case 27: -			info("Status: Failed to mount filesystems.\n"); +			logger(LL_INFO, "Status: Failed to mount filesystems.\n");  			break;  		case 50:  		case 51: -			info("Status: Failed to load SEP Firmware.\n"); +			logger(LL_INFO, "Status: Failed to load SEP Firmware.\n");  			break;  		case 53: -			info("Status: Failed to recover FDR data.\n"); +			logger(LL_INFO, "Status: Failed to recover FDR data.\n");  			break;  		case 1015: -			info("Status: X-Gold Baseband Update Failed. Defective Unit?\n"); +			logger(LL_INFO, "Status: X-Gold Baseband Update Failed. Defective Unit?\n");  			break;  		default: -			info("Unhandled status message (%" PRIu64 ")\n", value); -			debug_plist(msg); +			logger(LL_INFO, "Unhandled status message (%" PRIu64 ")\n", value); +			logger_dump_plist(LL_VERBOSE, msg, 1);  			break;  	} @@ -874,7 +881,7 @@ int restore_handle_status_msg(struct idevicerestore_client_t* client, plist_t ms  	node = plist_dict_get_item(msg, "Log");  	if (node && plist_get_node_type(node) == PLIST_STRING) {  		plist_get_string_val(node, &log); -		info("Log is available:\n%s\n", log); +		logger(LL_INFO, "Log is available:\n%s\n", log);  		free(log);  		log = NULL;  	} @@ -895,47 +902,47 @@ static int restore_handle_baseband_updater_output_data(struct idevicerestore_cli  	idevice_error_t device_error = IDEVICE_E_SUCCESS;  	if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	} -	debug("Connecting to baseband updater data port\n"); +	logger(LL_DEBUG, "Connecting to baseband updater data port\n");  	while (--attempts > 0) {  		device_error = idevice_connect(client->restore->device, data_port, &connection);  		if (device_error == IDEVICE_E_SUCCESS) {  			break;  		}  		sleep(1); -		debug("Retrying connection...\n"); +		logger(LL_DEBUG, "Retrying connection...\n");  	}  	if (device_error != IDEVICE_E_SUCCESS) { -		error("ERROR: Unable to connect to baseband updater data port\n"); +		logger(LL_ERROR, "Unable to connect to baseband updater data port\n");  		return result;  	}  	int fl = snprintf(NULL, 0, "updater_output-%s.cpio", client->udid);  	if (fl < 0) {  		idevice_disconnect(connection); -		error("ERROR: snprintf failed?!\n"); +		logger(LL_ERROR, "snprintf failed?!\n");  		return result;  	}  	char* updater_out_fn = malloc(fl+1);  	if (!updater_out_fn) {  		idevice_disconnect(connection); -		error("ERROR: Could not allocate buffer for filename\n"); +		logger(LL_ERROR, "Could not allocate buffer for filename\n");  		return result;  	}  	snprintf(updater_out_fn, fl+1, "updater_output-%s.cpio", client->udid);  	FILE* f = fopen(updater_out_fn, "wb");  	if (!f) { -		error("Could not open %s for writing, will not write baseband updater output data.\n", updater_out_fn); +		logger(LL_ERROR, "Could not open %s for writing, will not write baseband updater output data.\n", updater_out_fn);  	}  	const int bufsize = 65536;  	char* buf = malloc(bufsize);  	if (!buf) {  		free(updater_out_fn);  		idevice_disconnect(connection); -		error("ERROR: Could not allocate buffer\n"); +		logger(LL_ERROR, "Could not allocate buffer\n");  		return result;  	}  	uint32_t size = 0; @@ -946,7 +953,7 @@ static int restore_handle_baseband_updater_output_data(struct idevicerestore_cli  	}  	if (f) {  		fclose(f); -		info("Wrote baseband updater output data to %s\n", updater_out_fn); +		logger(LL_INFO, "Wrote baseband updater output data to %s\n", updater_out_fn);  	}  	free(updater_out_fn);  	free(buf); @@ -964,7 +971,7 @@ static int restore_handle_bb_update_status_msg(struct idevicerestore_client_t* c  	plist_get_bool_val(node, &accepted);  	if (!accepted) { -		error("ERROR: device didn't accept BasebandData\n"); +		logger(LL_ERROR, "device didn't accept BasebandData\n");  		return result;  	} @@ -975,27 +982,32 @@ static int restore_handle_bb_update_status_msg(struct idevicerestore_client_t* c  	}  	if (done) { -		info("Updating Baseband completed.\n"); +		logger(LL_INFO, "Updating Baseband completed.\n");  		plist_t provisioning = plist_access_path(message, 2, "Output", "provisioning");  		if (provisioning && plist_get_node_type(provisioning) == PLIST_DICT) {  			char* sval = NULL;  			node = plist_dict_get_item(provisioning, "IMEI");  			if (node && plist_get_node_type(node) == PLIST_STRING) {  				plist_get_string_val(node, &sval); -				info("Provisioning:\n"); -				info("IMEI:%s\n", sval); +				logger(LL_INFO, "Provisioning:\n"); +				logger(LL_INFO, "IMEI:%s\n", sval);  				free(sval);  				sval = NULL;  			}  		}  	} else { -		info("Updating Baseband in progress...\n"); +		logger(LL_INFO, "Updating Baseband in progress...\n");  	}  	result = 0;  	return result;  } +struct _restore_asr_progress_data { +	struct idevicerestore_client_t* client; +	uint32_t tag; +}; +  static void restore_asr_progress_cb(double progress, void* userdata)  {  	struct idevicerestore_client_t* client = (struct idevicerestore_client_t*)userdata; @@ -1012,14 +1024,14 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, plist_t mess  	char* fsname = NULL;  	if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	} -	info("About to send filesystem...\n"); +	logger(LL_INFO, "About to send filesystem...\n");  	if (build_identity_get_component_path(client->restore->build_identity, "OS", &fsname) < 0) { -		error("ERROR: Unable to get path for filesystem component\n"); +		logger(LL_ERROR, "Unable to get path for filesystem component\n");  		return -1;  	}  	if (client->filesystem) { @@ -1033,7 +1045,7 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, plist_t mess  		file = ipsw_file_open(client->ipsw, fsname);  	}  	if (!file) { -		error("ERROR: Unable to open '%s' in ipsw\n", fsname); +		logger(LL_ERROR, "Unable to open '%s' in ipsw\n", fsname);  		free(fsname);  	} @@ -1044,41 +1056,41 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, plist_t mess  	if (asr_open_with_timeout(client->restore->device, &asr, asr_port) < 0) {  		ipsw_file_close(file);  		ipsw_close(ipsw_dummy); -		error("ERROR: Unable to connect to ASR\n"); +		logger(LL_ERROR, "Unable to connect to ASR\n");  		return -1;  	} -	info("Connected to ASR\n"); - -	if (asr_port == ASR_DEFAULT_PORT) { -		asr_set_progress_callback(asr, restore_asr_progress_cb, (void*)client); -	} +	logger(LL_INFO, "Connected to ASR\n");  	// this step sends requested chunks of data from various offsets to asr so  	// it can validate the filesystem before installing it -	info("Validating the filesystem\n"); +	logger(LL_INFO, "Validating the filesystem\n");  	if (asr_perform_validation(asr, file) < 0) {  		ipsw_file_close(file);  		ipsw_close(ipsw_dummy); -		error("ERROR: ASR was unable to validate the filesystem\n"); +		logger(LL_ERROR, "ASR was unable to validate the filesystem\n");  		asr_free(asr);  		return -1;  	} -	info("Filesystem validated\n"); +	logger(LL_INFO, "Filesystem validated\n"); + +	if (asr_port == ASR_DEFAULT_PORT) { +		asr_set_progress_callback(asr, restore_asr_progress_cb, client); +	}  	// once the target filesystem has been validated, ASR then requests the  	// entire filesystem to be sent. -	info("Sending filesystem now...\n"); +	logger(LL_INFO, "Sending filesystem now...\n");  	if (asr_send_payload(asr, file) < 0) {  		ipsw_file_close(file);  		ipsw_close(ipsw_dummy); -		error("ERROR: Unable to send payload to ASR\n"); +		logger(LL_ERROR, "Unable to send payload to ASR\n");  		asr_free(asr);  		return -1;  	}  	ipsw_file_close(file);  	ipsw_close(ipsw_dummy); -	info("Done sending filesystem\n"); +	logger(LL_INFO, "Done sending filesystem\n");  	asr_free(asr);  	return 0; @@ -1089,7 +1101,7 @@ int restore_send_recovery_os_root_ticket(struct idevicerestore_client_t* client,  	restored_error_t restore_error;  	plist_t dict; -	info("About to send RecoveryOSRootTicket...\n"); +	logger(LL_INFO, "About to send RecoveryOSRootTicket...\n");  	if (client->root_ticket) {  		dict = plist_new_dict(); @@ -1099,18 +1111,18 @@ int restore_send_recovery_os_root_ticket(struct idevicerestore_client_t* client,  		unsigned int len = 0;  		if (!client->tss_recoveryos_root_ticket && !(client->flags & FLAG_CUSTOM)) { -			error("ERROR: Cannot send RootTicket without TSS\n"); +			logger(LL_ERROR, "Cannot send RootTicket without TSS\n");  			return -1;  		}  		if (client->image4supported) {  			if (tss_response_get_ap_img4_ticket(client->tss_recoveryos_root_ticket, &data, &len) < 0) { -				error("ERROR: Unable to get ApImg4Ticket from TSS\n"); +				logger(LL_ERROR, "Unable to get ApImg4Ticket from TSS\n");  				return -1;  			}  		} else {  			if (!(client->flags & FLAG_CUSTOM) && (tss_response_get_ap_ticket(client->tss, &data, &len) < 0)) { -				error("ERROR: Unable to get ticket from TSS\n"); +				logger(LL_ERROR, "Unable to get ticket from TSS\n");  				return -1;  			}  		} @@ -1119,27 +1131,27 @@ int restore_send_recovery_os_root_ticket(struct idevicerestore_client_t* client,  		if (data && (len > 0)) {  			plist_dict_set_item(dict, "RootTicketData", plist_new_data((char*)data, len));  		} else { -			info("NOTE: not sending RootTicketData (no data present)\n"); +			logger(LL_NOTICE, "Not sending RootTicketData (no data present)\n");  		}  		free(data);  	}  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("Sending RecoveryOSRootTicket now...\n"); +	logger(LL_INFO, "Sending RecoveryOSRootTicket now...\n");  	restore_error = _restore_service_send(service, dict, 0);  	plist_free(dict);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send RootTicket (%d)\n", restore_error); +		logger(LL_ERROR, "Unable to send RootTicket (%d)\n", restore_error);  		return -1;  	} -	info("Done sending RecoveryOS RootTicket\n"); +	logger(LL_INFO, "Done sending RecoveryOS RootTicket\n");  	return 0;  } @@ -1149,7 +1161,7 @@ int restore_send_root_ticket(struct idevicerestore_client_t* client, plist_t mes  	restored_error_t restore_error;  	plist_t dict; -	info("About to send RootTicket...\n"); +	logger(LL_INFO, "About to send RootTicket...\n");  	if (client->root_ticket) {  		dict = plist_new_dict(); @@ -1159,18 +1171,18 @@ int restore_send_root_ticket(struct idevicerestore_client_t* client, plist_t mes  		unsigned int len = 0;  		if (!client->tss && !(client->flags & FLAG_CUSTOM)) { -			error("ERROR: Cannot send RootTicket without TSS\n"); +			logger(LL_ERROR, "Cannot send RootTicket without TSS\n");  			return -1;  		}  		if (client->image4supported) {  			if (tss_response_get_ap_img4_ticket(client->tss, &data, &len) < 0) { -				error("ERROR: Unable to get ApImg4Ticket from TSS\n"); +				logger(LL_ERROR, "Unable to get ApImg4Ticket from TSS\n");  				return -1;  			}  		} else {  			if (!(client->flags & FLAG_CUSTOM) && (tss_response_get_ap_ticket(client->tss, &data, &len) < 0)) { -				error("ERROR: Unable to get ticket from TSS\n"); +				logger(LL_ERROR, "Unable to get ticket from TSS\n");  				return -1;  			}  		} @@ -1179,27 +1191,27 @@ int restore_send_root_ticket(struct idevicerestore_client_t* client, plist_t mes  		if (data && (len > 0)) {  			plist_dict_set_item(dict, "RootTicketData", plist_new_data((char*)data, len));  		} else { -			info("NOTE: not sending RootTicketData (no data present)\n"); +			logger(LL_INFO, "Not sending RootTicketData (no data present)\n");  		}  		free(data);  	}  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("Sending RootTicket now...\n"); +	logger(LL_INFO, "Sending RootTicket now...\n");  	restore_error = _restore_service_send(service, dict, 0);  	plist_free(dict);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send RootTicket (%d)\n", restore_error); +		logger(LL_ERROR, "Unable to send RootTicket (%d)\n", restore_error);  		return -1;  	} -	info("Done sending RootTicket\n"); +	logger(LL_INFO, "Done sending RootTicket\n");  	return 0;  } @@ -1234,7 +1246,7 @@ static size_t _curl_header_callback(char* buffer, size_t size, size_t nitems, vo  			strncpy(key, buffer, i);  			key[i] = '\0';  			i++; -			while (i < len && buffer[i] == ' ' || buffer[i] == '\t') i++; +			while (i < len && (buffer[i] == ' ' || buffer[i] == '\t')) i++;  			val = malloc(len-i+1);  			strncpy(val, buffer+i, len-i);  			val[len-i] = '\0'; @@ -1252,29 +1264,28 @@ static size_t _curl_header_callback(char* buffer, size_t size, size_t nitems, vo  int restore_send_url_asset(struct idevicerestore_client_t* client, plist_t message)  { -	debug("DEBUG: %s\n", __func__);  	plist_t arguments = plist_dict_get_item(message, "Arguments");  	if (!PLIST_IS_DICT(arguments)) { -		error("ERROR: %s: Unexpected arguments\n", __func__); -		debug_plist(arguments); +		logger(LL_ERROR, "%s: Unexpected arguments\n", __func__); +		logger_dump_plist(LL_VERBOSE, message, 1);  		return -1;  	}  	const char* request_method = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestMethod"), NULL);  	if (!request_method) { -		error("ERROR: %s: Unable to extract RequestMethod from Arguments\n", __func__); +		logger(LL_ERROR, "%s: Unable to extract RequestMethod from Arguments\n", __func__);  		return -1;  	}  	if (strcmp(request_method, "GET")) { -		error("ERROR: %s: Unexpected RequestMethod '%s' in message\n", __func__, request_method); +		logger(LL_ERROR, "%s: Unexpected RequestMethod '%s' in message\n", __func__, request_method);  		return -1;  	}  	const char* request_url = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestURL"), NULL);  	if (!request_url) { -		error("ERROR: %s: Unable to extract RequestURL from Arguments\n", __func__); +		logger(LL_ERROR, "%s: Unable to extract RequestURL from Arguments\n", __func__);  		return -1;  	} -	info("Requesting URLAsset from %s\n", request_url); +	logger(LL_INFO, "Requesting URLAsset from %s\n", request_url);  	char curl_error_message[CURL_ERROR_SIZE];  	CURL* handle = curl_easy_init(); @@ -1283,7 +1294,7 @@ int restore_send_url_asset(struct idevicerestore_client_t* client, plist_t messa  	query_response* response = malloc(sizeof(query_response));  	if (response == NULL) { -		error("ERROR: %s: Unable to allocate sufficient memory\n", __func__); +		logger(LL_ERROR, "%s: Unable to allocate sufficient memory\n", __func__);  		return -1;  	} @@ -1298,7 +1309,7 @@ int restore_send_url_asset(struct idevicerestore_client_t* client, plist_t messa  	plist_t response_headers = plist_new_dict();  	curl_easy_setopt(handle, CURLOPT_HEADERDATA, response_headers);  	curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); -	if (idevicerestore_debug) { +	if (client->debug_level > 0) {  		curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L);  	}  	curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1); @@ -1320,7 +1331,7 @@ int restore_send_url_asset(struct idevicerestore_client_t* client, plist_t messa  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} @@ -1332,26 +1343,26 @@ int restore_send_url_asset(struct idevicerestore_client_t* client, plist_t messa  int restore_send_streamed_image_decryption_key(struct idevicerestore_client_t* client, plist_t message)  { -	debug("DEBUG: %s\n", __func__); +	logger(LL_DEBUG, "%s\n", __func__);  	plist_t arguments = plist_dict_get_item(message, "Arguments");  	if (!PLIST_IS_DICT(arguments)) { -		error("ERROR: %s: Unexpected arguments\n", __func__); -		debug_plist(arguments); +		logger(LL_ERROR, "%s: Unexpected arguments\n", __func__); +		logger_dump_plist(LL_VERBOSE, arguments, 1);  		return -1;  	}  	const char* request_method = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestMethod"), NULL);  	if (!request_method) { -		error("ERROR: %s: Unable to extract RequestMethod from Arguments\n", __func__); +		logger(LL_ERROR, "%s: Unable to extract RequestMethod from Arguments\n", __func__);  		return -1;  	}  	if (strcmp(request_method, "POST")) { -		error("ERROR: %s: Unexpected RequestMethod '%s' in message\n", __func__, request_method); +		logger(LL_ERROR, "%s: Unexpected RequestMethod '%s' in message\n", __func__, request_method);  		return -1;  	}  	const char* request_url = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestURL"), NULL);  	if (!request_url) { -		error("ERROR: %s: Unable to extract RequestURL from Arguments\n", __func__); +		logger(LL_ERROR, "%s: Unable to extract RequestURL from Arguments\n", __func__);  		return -1;  	} @@ -1359,18 +1370,18 @@ int restore_send_streamed_image_decryption_key(struct idevicerestore_client_t* c  	plist_t headers = plist_dict_get_item(arguments, "RequestAdditionalHeaders");  	if (!headers) { -		error("ERROR: %s: Missing 'RequestAdditionalHeaders'\n", __func__); +		logger(LL_ERROR, "%s: Missing 'RequestAdditionalHeaders'\n", __func__);  		return -1;  	}  	uint64_t request_body_size = 0;  	const char* request_body = plist_get_data_ptr(plist_dict_get_item(arguments, "RequestBody"), &request_body_size);  	if (!request_body) { -		error("ERROR: %s: Missing 'RequestBody'\n", __func__); +		logger(LL_ERROR, "%s: Missing 'RequestBody'\n", __func__);  		return -1;  	} -	info("Requesting image decryption key from %s\n", request_url); +	logger(LL_INFO, "Requesting image decryption key from %s\n", request_url);  	char curl_error_message[CURL_ERROR_SIZE];  	char header_tmp[1024]; @@ -1392,7 +1403,7 @@ int restore_send_streamed_image_decryption_key(struct idevicerestore_client_t* c  	query_response* response = malloc(sizeof(query_response));  	if (response == NULL) { -		error("ERROR: %s: Unable to allocate sufficient memory\n", __func__); +		logger(LL_ERROR, "%s: Unable to allocate sufficient memory\n", __func__);  		return -1;  	} @@ -1408,8 +1419,8 @@ int restore_send_streamed_image_decryption_key(struct idevicerestore_client_t* c  	curl_easy_setopt(handle, CURLOPT_WRITEDATA, response);  	curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header);  	curl_easy_setopt(handle, CURLOPT_POSTFIELDS, request_body); -	curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, request_body_size); -	if (idevicerestore_debug) { +	curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, (long)request_body_size); +	if (client->debug_level > 0) {  		curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L);  	}  	curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1); @@ -1432,7 +1443,7 @@ int restore_send_streamed_image_decryption_key(struct idevicerestore_client_t* c  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} @@ -1444,15 +1455,15 @@ int restore_send_streamed_image_decryption_key(struct idevicerestore_client_t* c  int restore_send_component(struct idevicerestore_client_t* client, plist_t message, const char* component, const char* component_name)  { -	unsigned int size = 0; -	unsigned char* data = NULL; +	size_t size = 0; +	void* data = NULL;  	char* path = NULL;  	plist_t blob = NULL;  	plist_t dict = NULL;  	restored_error_t restore_error = RESTORE_E_SUCCESS;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	} @@ -1460,61 +1471,61 @@ int restore_send_component(struct idevicerestore_client_t* client, plist_t messa  		component_name = component;  	} -	info("About to send %s...\n", component_name); +	logger(LL_INFO, "About to send %s...\n", component_name);  	if (client->tss) {  		if (tss_response_get_path_by_entry(client->tss, component, &path) < 0) { -			debug("NOTE: No path for component %s in TSS, will fetch from build identity\n", component); +			logger(LL_DEBUG, "No path for component %s in TSS, will fetch from build identity\n", component);  		}  	}  	if (!path) {  		if (build_identity_get_component_path(client->restore->build_identity, component, &path) < 0) { -			error("ERROR: Unable to find %s path from build identity\n", component); +			logger(LL_ERROR, "Unable to find %s path from build identity\n", component);  			return -1;  		}  	} -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	int ret = extract_component(client->ipsw, path, &component_data, &component_size);  	free(path);  	path = NULL;  	if (ret < 0) { -		error("ERROR: Unable to extract component %s\n", component); +		logger(LL_ERROR, "Unable to extract component %s\n", component);  		return -1;  	} -	ret = personalize_component(component, component_data, component_size, client->tss, &data, &size); +	ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size);  	free(component_data);  	component_data = NULL;  	if (ret < 0) { -		error("ERROR: Unable to get personalized component %s\n", component); +		logger(LL_ERROR, "Unable to get personalized component %s\n", component);  		return -1;  	}  	dict = plist_new_dict();  	blob = plist_new_data((char*)data, size);  	char compkeyname[256]; -	sprintf(compkeyname, "%sFile", component_name); +	snprintf(compkeyname, sizeof(compkeyname), "%sFile", component_name);  	plist_dict_set_item(dict, compkeyname, blob);  	free(data);  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("Sending %s now...\n", component_name); +	logger(LL_INFO, "Sending %s now...\n", component_name);  	restore_error = _restore_service_send(service, dict, 0);  	plist_free(dict);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send component %s data\n", component_name); +		logger(LL_ERROR, "Unable to send component %s data\n", component_name);  		return -1;  	} -	info("Done sending %s\n", component_name); +	logger(LL_INFO, "Done sending %s\n", component_name);  	return 0;  } @@ -1526,24 +1537,24 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  	char* restore_sep_path = NULL;  	char firmware_path[PATH_MAX - 9];  	char manifest_file[PATH_MAX]; -	unsigned int manifest_size = 0; -	unsigned char* manifest_data = NULL; +	size_t manifest_size = 0; +	void* manifest_data = NULL;  	char firmware_filename[PATH_MAX]; -	unsigned int llb_size = 0; -	unsigned char* llb_data = NULL; +	size_t llb_size = 0; +	void* llb_data = NULL;  	plist_t dict = NULL; -	unsigned int nor_size = 0; -	unsigned char* nor_data = NULL; +	size_t nor_size = 0; +	void* nor_data = NULL;  	plist_t norimage = NULL;  	plist_t firmware_files = NULL;  	int flash_version_1 = 0;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	} -	info("About to send NORData...\n"); +	logger(LL_INFO, "About to send NORData...\n");  	plist_t arguments = plist_dict_get_item(message, "Arguments");  	if (arguments && plist_get_node_type(arguments) == PLIST_DICT) { @@ -1552,26 +1563,26 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  	if (client->tss) {  		if (tss_response_get_path_by_entry(client->tss, "LLB", &llb_path) < 0) { -			debug("NOTE: Could not get LLB path from TSS data, will fetch from build identity\n"); +			logger(LL_DEBUG, "Could not get LLB path from TSS data, will fetch from build identity\n");  		}  	}  	if (llb_path == NULL) {  		if (build_identity_get_component_path(client->restore->build_identity, "LLB", &llb_path) < 0) { -			error("ERROR: Unable to get component path for LLB\n"); +			logger(LL_ERROR, "Unable to get component path for LLB\n");  			return -1;  		}  	}  	llb_filename = strstr(llb_path, "LLB");  	if (llb_filename == NULL) { -		error("ERROR: Unable to extract firmware path from LLB filename\n"); +		logger(LL_ERROR, "Unable to extract firmware path from LLB filename\n");  		free(llb_path);  		return -1;  	}  	memset(firmware_path, '\0', sizeof(firmware_path));  	memcpy(firmware_path, llb_path, (llb_filename - 1) - llb_path); -	info("Found firmware path %s\n", firmware_path); +	logger(LL_INFO, "Found firmware path %s\n", firmware_path);  	memset(manifest_file, '\0', sizeof(manifest_file));  	snprintf(manifest_file, sizeof(manifest_file), "%s/manifest", firmware_path); @@ -1581,7 +1592,7 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  		ipsw_extract_to_memory(client->ipsw, manifest_file, &manifest_data, &manifest_size);  	}  	if (manifest_data && manifest_size > 0) { -		info("Getting firmware manifest from %s\n", manifest_file); +		logger(LL_INFO, "Getting firmware manifest from %s\n", manifest_file);  		char *manifest_p = (char*)manifest_data;  		char *filename = NULL;  		while ((filename = strsep(&manifest_p, "\r\n")) != NULL) { @@ -1594,7 +1605,7 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  		}  		free(manifest_data);  	} else { -		info("Getting firmware manifest from build identity\n"); +		logger(LL_INFO, "Getting firmware manifest from build identity\n");  		plist_dict_iter iter = NULL;  		plist_t build_id_manifest = plist_dict_get_item(client->restore->build_identity, "Manifest");  		if (build_id_manifest) { @@ -1642,26 +1653,26 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  	}  	if (plist_dict_get_size(firmware_files) == 0) { -		error("ERROR: Unable to get list of firmware files.\n"); +		logger(LL_ERROR, "Unable to get list of firmware files.\n");  		return -1;  	}  	const char* component = "LLB"; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	int ret = extract_component(client->ipsw, llb_path, &component_data, &component_size);  	free(llb_path);  	if (ret < 0) { -		error("ERROR: Unable to extract component: %s\n", component); +		logger(LL_ERROR, "Unable to extract component: %s\n", component);  		return -1;  	} -	ret = personalize_component(component, component_data, component_size, client->tss, &llb_data, &llb_size); +	ret = personalize_component(client, component, component_data, component_size, client->tss, &llb_data, &llb_size);  	free(component_data);  	component_data = NULL;  	component_size = 0;  	if (ret < 0) { -		error("ERROR: Unable to get personalized component: %s\n", component); +		logger(LL_ERROR, "Unable to get personalized component: %s\n", component);  		return -1;  	} @@ -1701,24 +1712,24 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  		}  		component_data = NULL; -		unsigned int component_size = 0; +		component_size = 0;  		if (extract_component(client->ipsw, comppath, &component_data, &component_size) < 0) {  			free(iter);  			free(comp);  			free(comppath);  			plist_free(firmware_files); -			error("ERROR: Unable to extract component: %s\n", component); +			logger(LL_ERROR, "Unable to extract component: %s\n", component);  			return -1;  		} -		if (personalize_component(component, component_data, component_size, client->tss, &nor_data, &nor_size) < 0) { +		if (personalize_component(client, component, component_data, component_size, client->tss, &nor_data, &nor_size) < 0) {  			free(iter);  			free(comp);  			free(comppath);  			free(component_data);  			plist_free(firmware_files); -			error("ERROR: Unable to get personalized component: %s\n", component); +			logger(LL_ERROR, "Unable to get personalized component: %s\n", component);  			return -1;  		}  		free(component_data); @@ -1746,8 +1757,8 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  	plist_free(firmware_files);  	plist_dict_set_item(dict, "NorImageData", norimage); -	unsigned char* personalized_data = NULL; -	unsigned int personalized_size = 0; +	void* personalized_data = NULL; +	size_t personalized_size = 0;  	if (build_identity_has_component(client->restore->build_identity, "RestoreSEP") &&  	    build_identity_get_component_path(client->restore->build_identity, "RestoreSEP", &restore_sep_path) == 0) { @@ -1755,16 +1766,16 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  		ret = extract_component(client->ipsw, restore_sep_path, &component_data, &component_size);  		free(restore_sep_path);  		if (ret < 0) { -			error("ERROR: Unable to extract component: %s\n", component); +			logger(LL_ERROR, "Unable to extract component: %s\n", component);  			return -1;  		} -		ret = personalize_component(component, component_data, component_size, client->tss, &personalized_data, &personalized_size); +		ret = personalize_component(client, component, component_data, component_size, client->tss, &personalized_data, &personalized_size);  		free(component_data);  		component_data = NULL;  		component_size = 0;  		if (ret < 0) { -			error("ERROR: Unable to get personalized component: %s\n", component); +			logger(LL_ERROR, "Unable to get personalized component: %s\n", component);  			return -1;  		} @@ -1780,16 +1791,16 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  		ret = extract_component(client->ipsw, sep_path, &component_data, &component_size);  		free(sep_path);  		if (ret < 0) { -			error("ERROR: Unable to extract component: %s\n", component); +			logger(LL_ERROR, "Unable to extract component: %s\n", component);  			return -1;  		} -		ret = personalize_component(component, component_data, component_size, client->tss, &personalized_data, &personalized_size); +		ret = personalize_component(client, component, component_data, component_size, client->tss, &personalized_data, &personalized_size);  		free(component_data);  		component_data = NULL;  		component_size = 0;  		if (ret < 0) { -			error("ERROR: Unable to get personalized component: %s\n", component); +			logger(LL_ERROR, "Unable to get personalized component: %s\n", component);  			return -1;  		} @@ -1805,16 +1816,16 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  		ret = extract_component(client->ipsw, sep_path, &component_data, &component_size);  		free(sep_path);  		if (ret < 0) { -			error("ERROR: Unable to extract component: %s\n", component); +			logger(LL_ERROR, "Unable to extract component: %s\n", component);  			return -1;  		} -		ret = personalize_component(component, component_data, component_size, client->tss, &personalized_data, &personalized_size); +		ret = personalize_component(client, component, component_data, component_size, client->tss, &personalized_data, &personalized_size);  		free(component_data);  		component_data = NULL;  		component_size = 0;  		if (ret < 0) { -			error("ERROR: Unable to get personalized component: %s\n", component); +			logger(LL_ERROR, "Unable to get personalized component: %s\n", component);  			return -1;  		} @@ -1824,29 +1835,29 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)  		personalized_size = 0;  	} -	if (idevicerestore_debug) -		debug_plist(dict); +	if (client->debug_level > 1) +		logger_dump_plist(LL_DEBUG, dict, 0);  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("Sending NORData now...\n"); +	logger(LL_INFO, "Sending NORData now...\n");  	restored_error_t restore_error = _restore_service_send(service, dict, 0);  	plist_free(dict);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send NORData\n"); +		logger(LL_ERROR, "Unable to send NORData\n");  		return -1;  	} -	info("Done sending NORData\n"); +	logger(LL_INFO, "Done sending NORData\n");  	return 0;  } -static const char* restore_get_bbfw_fn_for_element(const char* elem) +static const char* restore_get_bbfw_fn_for_element(const char* elem, uint32_t bb_chip_id)  {  	struct bbfw_fn_elem_t {  		const char* element; @@ -1877,29 +1888,43 @@ static const char* restore_get_bbfw_fn_for_element(const char* elem)  		{ NULL, NULL }  	}; +	struct bbfw_fn_elem_t bbfw_fn_elem_mav25[] = { +		// Mav25 Firmware files +		{ "Misc", "multi_image.mbn" }, +		{ "RestoreSBL1", "restorexbl_sc.elf" }, +		{ "SBL1", "xbl_sc.elf" }, +		{ "TME", "signed_firmware_soc_view.elf" }, +		{ NULL, NULL } +	}; + +	struct bbfw_fn_elem_t* bbfw_fn_elems = (struct bbfw_fn_elem_t*)bbfw_fn_elem; +	if (bb_chip_id == 0x1F30E1) { +		bbfw_fn_elems = (struct bbfw_fn_elem_t*)bbfw_fn_elem_mav25; +	} +  	int i; -	for (i = 0; bbfw_fn_elem[i].element != NULL; i++) { -		if (strcmp(bbfw_fn_elem[i].element, elem) == 0) { -			return bbfw_fn_elem[i].fn; +	for (i = 0; bbfw_fn_elems[i].element != NULL; i++) { +		if (strcmp(bbfw_fn_elems[i].element, elem) == 0) { +			return bbfw_fn_elems[i].fn;  		}  	}  	return NULL;  } -static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned char* bb_nonce) +static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned char* bb_nonce, uint32_t bb_chip_id)  {  	int res = -1;  	// check for BBTicket in result  	plist_t bbticket = plist_dict_get_item(bbtss, "BBTicket");  	if (!bbticket || plist_get_node_type(bbticket) != PLIST_DATA) { -		error("ERROR: Could not find BBTicket in Baseband TSS response\n"); +		logger(LL_ERROR, "Could not find BBTicket in Baseband TSS response\n");  		return -1;  	}  	plist_t bbfw_dict = plist_dict_get_item(bbtss, "BasebandFirmware");  	if (!bbfw_dict || plist_get_node_type(bbfw_dict) != PLIST_DICT) { -		error("ERROR: Could not find BasebandFirmware Dictionary node in Baseband TSS response\n"); +		logger(LL_ERROR, "Could not find BasebandFirmware Dictionary node in Baseband TSS response\n");  		return -1;  	} @@ -1914,19 +1939,18 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  	struct zip_file* zfile = NULL;  	struct zip* za = NULL;  	struct zip_source* zs = NULL; -	mbn_file* mbn = NULL;  	fls_file* fls = NULL;  	za = zip_open(bbfwtmp, 0, &zerr);  	if (!za) { -		error("ERROR: Could not open ZIP archive '%s': %d\n", bbfwtmp, zerr); +		logger(LL_ERROR, "Could not open ZIP archive '%s': %d\n", bbfwtmp, zerr);  		goto leave;  	}  	plist_dict_iter iter = NULL;  	plist_dict_new_iter(bbfw_dict, &iter);  	if (!iter) { -		error("ERROR: Could not create dict iter for BasebandFirmware Dictionary\n"); +		logger(LL_ERROR, "Could not create dict iter for BasebandFirmware Dictionary\n");  		return -1;  	} @@ -1942,9 +1966,9 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  		if (node && (strcmp(key + (strlen(key) - 5), "-Blob") == 0) && (plist_get_node_type(node) == PLIST_DATA)) {  			char *ptr = strchr(key, '-');  			*ptr = '\0'; -			const char* signfn = restore_get_bbfw_fn_for_element(key); +			const char* signfn = restore_get_bbfw_fn_for_element(key, bb_chip_id);  			if (!signfn) { -				error("ERROR: can't match element name '%s' to baseband firmware file name.\n", key); +				logger(LL_ERROR, "can't match element name '%s' to baseband firmware file name.\n", key);  				goto leave;  			}  			char* ext = strrchr(signfn, '.'); @@ -1954,30 +1978,30 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  			zindex = zip_name_locate(za, signfn, 0);  			if (zindex < 0) { -				error("ERROR: can't locate '%s' in '%s'\n", signfn, bbfwtmp); +				logger(LL_ERROR, "can't locate '%s' in '%s'\n", signfn, bbfwtmp);  				goto leave;  			}  			zip_stat_init(&zstat);  			if (zip_stat_index(za, zindex, 0, &zstat) != 0) { -				error("ERROR: zip_stat_index failed for index %" PRIi64 "\n", zindex); +				logger(LL_ERROR, "zip_stat_index failed for index %" PRIi64 "\n", zindex);  				goto leave;  			}  			zfile = zip_fopen_index(za, zindex, 0);  			if (zfile == NULL) { -				error("ERROR: zip_fopen_index failed for index %" PRIi64 "\n", zindex); +				logger(LL_ERROR, "zip_fopen_index failed for index %" PRIi64 "\n", zindex);  				goto leave;  			}  			buffer = (unsigned char*) malloc(zstat.size + 1);  			if (buffer == NULL) { -				error("ERROR: Out of memory\n"); +				logger(LL_ERROR, "Out of memory\n");  				goto leave;  			}  			if (zip_fread(zfile, buffer, zstat.size) != zstat.size) { -				error("ERROR: zip_fread: failed\n"); +				logger(LL_ERROR, "zip_fread: failed\n");  				goto leave;  			}  			buffer[zstat.size] = '\0'; @@ -1988,63 +2012,60 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  			if (is_fls) {  				fls = fls_parse(buffer, zstat.size);  				if (!fls) { -					error("ERROR: could not parse fls file\n"); -					goto leave; -				} -			} else { -				mbn = mbn_parse(buffer, zstat.size); -				if (!mbn) { -					error("ERROR: could not parse mbn file\n"); +					logger(LL_ERROR, "could not parse fls file\n");  					goto leave;  				}  			} -			free(buffer); -			buffer = NULL;  			blob_size = 0;  			blob = (const unsigned char*)plist_get_data_ptr(node, &blob_size);  			if (!blob) { -				error("ERROR: could not get %s-Blob data\n", key); +				logger(LL_ERROR, "could not get %s-Blob data\n", key);  				goto leave;  			} +			logger(LL_VERBOSE, "Stitching %s\n", signfn);  			if (is_fls) { -				if (fls_update_sig_blob(fls, blob, (unsigned int)blob_size) != 0) { -					error("ERROR: could not sign %s\n", signfn); +				if (fls_update_sig_blob(fls, blob, (size_t)blob_size) != 0) { +					logger(LL_ERROR, "Could not stitch %s\n", signfn);  					goto leave;  				} -			} else { -				if (mbn_update_sig_blob(mbn, blob, (unsigned int)blob_size) != 0) { -					error("ERROR: could not sign %s\n", signfn); +				fsize = fls->size; +				fdata = (unsigned char*)malloc(fsize); +				if (fdata == NULL)  { +					logger(LL_ERROR, "out of memory\n");  					goto leave;  				} -			} - -			fsize = (is_fls ? fls->size : mbn->size); -			fdata = (unsigned char*)malloc(fsize); -			if (fdata == NULL)  { -				error("ERROR: out of memory\n"); -				goto leave; -			} -			if (is_fls) {  				memcpy(fdata, fls->data, fsize);  				fls_free(fls);  				fls = NULL; +			} else if (bb_chip_id == 0x1F30E1) { // Mav25 - Qualcomm Snapdragon X80 5G Modem +				fdata = mbn_mav25_stitch(buffer, zstat.size, blob, (size_t)blob_size); +				fsize = zstat.size; +				if (!fdata) { +					logger(LL_ERROR, "Could not stitch %s\n", signfn); +					goto leave; +				}  			} else { -				memcpy(fdata, mbn->data, fsize); -				mbn_free(mbn); -				mbn = NULL; +				fdata = mbn_stitch(buffer, zstat.size, blob, (size_t)blob_size); +				fsize = zstat.size; +				if (!fdata) { +					logger(LL_ERROR, "Could not stitch %s\n", signfn); +					goto leave; +				}  			} +			free(buffer); +			buffer = NULL;  			zs = zip_source_buffer(za, fdata, fsize, 1);  			if (!zs) { -				error("ERROR: out of memory\n"); +				logger(LL_ERROR, "out of memory\n");  				free(fdata);  				goto leave;  			}  			if (zip_file_replace(za, zindex, zs, 0) == -1) { -				error("ERROR: could not update signed '%s' in archive\n", signfn); +				logger(LL_ERROR, "Could not update signed '%s' in archive\n", signfn);  				goto leave;  			} @@ -2073,8 +2094,8 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  			}  		}  		// check for anything but .mbn and .fls if bb_nonce is set -		if (bb_nonce && !keep) { -			const char* fn = zip_get_name(za, i, 0); +		const char* fn = zip_get_name(za, i, 0); +		if (!keep) {  			if (fn) {  				char* ext = strrchr(fn, '.');  				if (ext && (!strcmp(ext, ".fls") || !strcmp(ext, ".mbn") || !strcmp(ext, ".elf") || !strcmp(ext, ".bin"))) { @@ -2083,39 +2104,42 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  			}  		}  		if (!keep) { +			logger(LL_DEBUG, "%s: removing %s from bbfw\n", __func__, fn);  			zip_delete(za, i); +		} else { +			logger(LL_DEBUG, "%s: keeping %s in bbfw\n", __func__, fn);  		}  	} -	if (bb_nonce) { +	if (bbticket) {  		if (is_fls) {  			// add BBTicket to file ebl.fls  			zindex = zip_name_locate(za, "ebl.fls", 0);  			if (zindex < 0) { -				error("ERROR: can't locate 'ebl.fls' in '%s'\n", bbfwtmp); +				logger(LL_ERROR, "can't locate 'ebl.fls' in '%s'\n", bbfwtmp);  				goto leave;  			}  			zip_stat_init(&zstat);  			if (zip_stat_index(za, zindex, 0, &zstat) != 0) { -				error("ERROR: zip_stat_index failed for index %" PRIi64 "\n", zindex); +				logger(LL_ERROR, "zip_stat_index failed for index %" PRIi64 "\n", zindex);  				goto leave;  			}  			zfile = zip_fopen_index(za, zindex, 0);  			if (zfile == NULL) { -				error("ERROR: zip_fopen_index failed for index %" PRIi64 "\n", zindex); +				logger(LL_ERROR, "zip_fopen_index failed for index %" PRIi64 "\n", zindex);  				goto leave;  			}  			buffer = (unsigned char*) malloc(zstat.size + 1);  			if (buffer == NULL) { -				error("ERROR: Out of memory\n"); +				logger(LL_ERROR, "Out of memory\n");  				goto leave;  			}  			if (zip_fread(zfile, buffer, zstat.size) != zstat.size) { -				error("ERROR: zip_fread: failed\n"); +				logger(LL_ERROR, "zip_fread: failed\n");  				goto leave;  			}  			buffer[zstat.size] = '\0'; @@ -2127,26 +2151,26 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  			free(buffer);  			buffer = NULL;  			if (!fls) { -				error("ERROR: could not parse fls file\n"); +				logger(LL_ERROR, "could not parse fls file\n");  				goto leave;  			}  			blob_size = 0;  			blob = (const unsigned char*)plist_get_data_ptr(bbticket, &blob_size);  			if (!blob) { -				error("ERROR: could not get BBTicket data\n"); +				logger(LL_ERROR, "could not get BBTicket data\n");  				goto leave;  			}  			if (fls_insert_ticket(fls, blob, (unsigned int)blob_size) != 0) { -				error("ERROR: could not insert BBTicket to ebl.fls\n"); +				logger(LL_ERROR, "could not insert BBTicket to ebl.fls\n");  				goto leave;  			}  			fsize = fls->size;  			fdata = (unsigned char*)malloc(fsize);  			if (!fdata) { -				error("ERROR: out of memory\n"); +				logger(LL_ERROR, "out of memory\n");  				goto leave;  			}  			memcpy(fdata, fls->data, fsize); @@ -2155,13 +2179,13 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  			zs = zip_source_buffer(za, fdata, fsize, 1);  			if (!zs) { -				error("ERROR: out of memory\n"); +				logger(LL_ERROR, "out of memory\n");  				free(fdata);  				goto leave;  			}  			if (zip_file_replace(za, zindex, zs, 0) == -1) { -				error("ERROR: could not update archive with ticketed ebl.fls\n"); +				logger(LL_ERROR, "could not update archive with ticketed ebl.fls\n");  				goto leave;  			}  		} else { @@ -2169,18 +2193,18 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  			blob_size = 0;  			blob = (const unsigned char*)plist_get_data_ptr(bbticket, &blob_size);  			if (!blob) { -				error("ERROR: could not get BBTicket data\n"); +				logger(LL_ERROR, "could not get BBTicket data\n");  				goto leave;  			}  			zs = zip_source_buffer(za, blob, blob_size, 0);  			if (!zs) { -				error("ERROR: out of memory\n"); +				logger(LL_ERROR, "out of memory\n");  				goto leave;  			}  			if (zip_file_add(za, "bbticket.der", zs, ZIP_FL_OVERWRITE) == -1) { -				error("ERROR: could not add bbticket.der to archive\n"); +				logger(LL_ERROR, "could not add bbticket.der to archive\n");  				goto leave;  			}  		} @@ -2188,7 +2212,7 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned  	// this will write out the modified zip  	if (zip_close(za) == -1) { -		error("ERROR: could not close and write modified archive: %s\n", zip_strerror(za)); +		logger(LL_ERROR, "could not close and write modified archive: %s\n", zip_strerror(za));  		res = -1;  	} else {  		res = 0; @@ -2207,7 +2231,6 @@ leave:  		zip_unchange_all(za);  		zip_close(za);  	} -	mbn_free(mbn);  	fls_free(fls);  	free(buffer); @@ -2229,11 +2252,11 @@ static int restore_send_baseband_data(struct idevicerestore_client_t* client, pl  	plist_t dict = NULL;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	} -	info("About to send BasebandData...\n"); +	logger(LL_INFO, "About to send BasebandData...\n");  	// NOTE: this function is called 2 or 3 times! @@ -2274,7 +2297,7 @@ static int restore_send_baseband_data(struct idevicerestore_client_t* client, pl  		/* create baseband request */  		plist_t request = tss_request_new(NULL);  		if (request == NULL) { -			error("ERROR: Unable to create Baseband TSS request\n"); +			logger(LL_ERROR, "Unable to create Baseband TSS request\n");  			plist_free(parameters);  			return -1;  		} @@ -2292,34 +2315,30 @@ static int restore_send_baseband_data(struct idevicerestore_client_t* client, pl  				plist_dict_set_item(request, "ApSecurityMode", plist_new_bool(1));  			}  		} -		if (idevicerestore_debug) -			debug_plist(request); - -		info("Sending Baseband TSS request...\n"); +		logger(LL_INFO, "Sending Baseband TSS request...\n"); +		logger_dump_plist(LL_DEBUG, request, 0);  		response = tss_request_send(request, client->tss_url);  		plist_free(request);  		plist_free(parameters);  		if (response == NULL) { -			error("ERROR: Unable to fetch Baseband TSS\n"); +			logger(LL_ERROR, "Unable to fetch Baseband TSS\n");  			return -1;  		} -		info("Received Baseband SHSH blobs\n"); - -		if (idevicerestore_debug) -			debug_plist(response); +		logger(LL_INFO, "Received Baseband SHSH blobs\n"); +		logger_dump_plist(LL_DEBUG, response, 0);  	}  	// get baseband firmware file path from build identity  	plist_t bbfw_path = plist_access_path(client->restore->build_identity, 4, "Manifest", "BasebandFirmware", "Info", "Path");  	if (!bbfw_path || plist_get_node_type(bbfw_path) != PLIST_STRING) { -		error("ERROR: Unable to get BasebandFirmware/Info/Path node\n"); +		logger(LL_ERROR, "Unable to get BasebandFirmware/Info/Path node\n");  		plist_free(response);  		return -1;  	}  	char* bbfwpath = NULL;  	plist_get_string_val(bbfw_path, &bbfwpath);  	if (!bbfwpath) { -		error("ERROR: Unable to get baseband path\n"); +		logger(LL_ERROR, "Unable to get baseband path\n");  		plist_free(response);  		return -1;  	} @@ -2332,10 +2351,10 @@ static int restore_send_baseband_data(struct idevicerestore_client_t* client, pl  		strcpy(bbfwtmp, "bbfw_");  		strncpy(bbfwtmp + 5, client->udid, l);  		strcpy(bbfwtmp + 5 + l, ".tmp"); -		error("WARNING: Could not generate temporary filename, using %s in current directory\n", bbfwtmp); +		logger(LL_WARNING, "Could not generate temporary filename, using %s in current directory\n", bbfwtmp);  	}  	if (ipsw_extract_to_file(client->ipsw, bbfwpath, bbfwtmp) != 0) { -		error("ERROR: Unable to extract baseband firmware from ipsw\n"); +		logger(LL_ERROR, "Unable to extract baseband firmware from ipsw\n");  		goto leave;  	} @@ -2345,7 +2364,7 @@ static int restore_send_baseband_data(struct idevicerestore_client_t* client, pl  		response = NULL;  	} -	res = restore_sign_bbfw(bbfwtmp, (client->restore->bbtss) ? client->restore->bbtss : response, bb_nonce); +	res = restore_sign_bbfw(bbfwtmp, (client->restore->bbtss) ? client->restore->bbtss : response, bb_nonce, bb_chip_id);  	if (res != 0) {  		goto leave;  	} @@ -2354,7 +2373,7 @@ static int restore_send_baseband_data(struct idevicerestore_client_t* client, pl  	size_t sz = 0;  	if (read_file(bbfwtmp, (void**)&buffer, &sz) < 0) { -		error("ERROR: could not read updated bbfw archive\n"); +		logger(LL_ERROR, "could not read updated bbfw archive\n");  		goto leave;  	} @@ -2366,26 +2385,32 @@ static int restore_send_baseband_data(struct idevicerestore_client_t* client, pl  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("Sending BasebandData now...\n"); +	logger(LL_INFO, "Sending BasebandData now...\n");  	if (_restore_service_send(service, dict, 0) != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send BasebandData data\n"); +		logger(LL_ERROR, "Unable to send BasebandData data\n");  		goto leave;  	}  	_restore_service_free(service); -	info("Done sending BasebandData\n"); +	logger(LL_INFO, "Done sending BasebandData\n");  	res = 0;  leave:  	plist_free(dict);  	free(buffer);  	if (bbfwtmp) { -		remove(bbfwtmp); +		if (client->flags & FLAG_KEEP_PERS) { +			const char* bbfwname = path_get_basename(bbfwtmp); +			logger(LL_VERBOSE, "%s: Keeping personalized BBFW as %s\n", __func__, bbfwname); +			rename(bbfwtmp, bbfwname); +		} else { +			remove(bbfwtmp); +		}  		free(bbfwtmp);  	}  	plist_free(response); @@ -2398,7 +2423,7 @@ int restore_send_fdr_trust_data(struct idevicerestore_client_t* client, plist_t  	restored_error_t restore_error;  	plist_t dict; -	info("About to send FDR Trust data...\n"); +	logger(LL_INFO, "About to send FDR Trust data...\n");  	// FIXME: What should we send here?  	/* Sending an empty dict makes it continue with FDR @@ -2407,20 +2432,20 @@ int restore_send_fdr_trust_data(struct idevicerestore_client_t* client, plist_t  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("Sending FDR Trust data now...\n"); +	logger(LL_INFO, "Sending FDR Trust data now...\n");  	restore_error = _restore_service_send(service, dict, 0);  	plist_free(dict);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: During sending FDR Trust data (%d)\n", restore_error); +		logger(LL_ERROR, "During sending FDR Trust data (%d)\n", restore_error);  		return -1;  	} -	info("Done sending FDR Trust Data\n"); +	logger(LL_INFO, "Done sending FDR Trust Data\n");  	return 0;  } @@ -2439,7 +2464,7 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist  	int want_image_list = 0;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	} @@ -2456,12 +2481,12 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist  		}  	}  	if (!image_type_k) { -		error("ERROR: missing ImageType"); +		logger(LL_ERROR, "Missing ImageType\n");  		return -1;  	}  	if (!want_image_list && !image_name) { -		info("About to send %s...\n", image_data_k); +		logger(LL_INFO, "About to send %s...\n", image_data_k);  	}  	if (want_image_list) { @@ -2489,18 +2514,18 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist  				}  				if (is_image_type) {  					if (want_image_list) { -						info("Found %s component %s\n", image_type_k, component); +						logger(LL_INFO, "Found %s component %s\n", image_type_k, component);  						plist_array_append_item(matched_images, plist_new_string(component));  					} else if (!image_name || !strcmp(image_name, component)) {  						char *path = NULL; -						unsigned char* data = NULL; -						unsigned int size = 0; -						unsigned char* component_data = NULL; -						unsigned int component_size = 0; +						void* data = NULL; +						size_t size = 0; +						void* component_data = NULL; +						size_t component_size = 0;  						int ret = -1;  						if (!image_name) { -							info("Found %s component '%s'\n", image_type_k, component); +							logger(LL_INFO, "Found %s component '%s'\n", image_type_k, component);  						}  						build_identity_get_component_path(client->restore->build_identity, component, &path);  						if (path) { @@ -2509,14 +2534,14 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist  						free(path);  						path = NULL;  						if (ret < 0) { -							error("ERROR: Unable to extract component: %s\n", component); +							logger(LL_ERROR, "Unable to extract component: %s\n", component);  						} -						ret = personalize_component(component, component_data, component_size, client->tss, &data, &size); +						ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size);  						free(component_data);  						component_data = NULL;  						if (ret < 0) { -							error("ERROR: Unable to get personalized component: %s\n", component); +							logger(LL_ERROR, "Unable to get personalized component: %s\n", component);  						}  						plist_dict_set_item(data_dict, component, plist_new_data((const char*)data, size)); @@ -2531,14 +2556,14 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	}  	dict = plist_new_dict();  	if (want_image_list) {  		plist_dict_set_item(dict, image_list_k, matched_images); -		info("Sending %s image list\n", image_type_k); +		logger(LL_INFO, "Sending %s image list\n", image_type_k);  	} else {  		if (image_name) {  			node = plist_dict_get_item(data_dict, image_name); @@ -2546,10 +2571,10 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist  				plist_dict_set_item(dict, image_data_k, plist_copy(node));  			}  			plist_dict_set_item(dict, "ImageName", plist_new_string(image_name)); -			info("Sending %s for %s...\n", image_type_k, image_name); +			logger(LL_INFO, "Sending %s for %s...\n", image_type_k, image_name);  		} else {  			plist_dict_set_item(dict, image_data_k, data_dict); -			info("Sending %s now...\n", image_type_k); +			logger(LL_INFO, "Sending %s now...\n", image_type_k);  		}  	} @@ -2558,13 +2583,13 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) {  		if (want_image_list) { -			error("ERROR: Failed to send %s image list (%d)\n", image_type_k, restore_error); +			logger(LL_ERROR, "Failed to send %s image list (%d)\n", image_type_k, restore_error);  		} else {  			if (image_name) { -				error("ERROR: Failed to send %s for %s (%d)\n", image_type_k, image_name, restore_error); +				logger(LL_ERROR, "Failed to send %s for %s (%d)\n", image_type_k, image_name, restore_error);  				free(image_name);  			} else { -				error("ERROR: Failed to send %s (%d)\n", image_type_k, restore_error); +				logger(LL_ERROR, "Failed to send %s (%d)\n", image_type_k, restore_error);  			}  		}  		return -1; @@ -2574,19 +2599,41 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist  		if (image_name) {  			free(image_name);  		} else { -			info("Done sending %s\n", image_type_k); +			logger(LL_INFO, "Done sending %s\n", image_type_k);  		}  	}  	return 0;  } +static int _wants_firmware_data(plist_t arguments) +{ +	int result = 0; +	plist_t tags = plist_access_path(arguments, 2, "DeviceGeneratedTags", "ResponseTags"); +	if (tags) { +		plist_array_iter iter = NULL; +		plist_array_new_iter(tags, &iter); +		plist_t node = NULL; +		do { +			plist_array_next_item(tags, iter, &node); +			if (node) { +				const char* tag = plist_get_string_ptr(node, NULL); +				if (tag && (strcmp(tag, "FirmwareData") == 0)) { +					result = 1; +				} +			} +		} while (node); +		plist_mem_free(iter); +	} +	return result; +} +  static plist_t restore_get_se_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments)  {  	const char *comp_name = NULL;  	char *comp_path = NULL; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	plist_t parameters = NULL;  	plist_t request = NULL;  	plist_t response = NULL; @@ -2595,7 +2642,7 @@ static plist_t restore_get_se_firmware_data(struct idevicerestore_client_t* clie  	uint64_t chip_id = 0;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return NULL;  	} @@ -2605,46 +2652,33 @@ static plist_t restore_get_se_firmware_data(struct idevicerestore_client_t* clie  	}  	if (chip_id == 0x20211) {  		comp_name = "SE,Firmware"; -	} else if (chip_id == 0x73 || chip_id == 0x64 || chip_id == 0xC8 || chip_id == 0xD2 || chip_id == 0x2C || chip_id == 0x36) { +	} else if (chip_id == 0x73 || chip_id == 0x64 || chip_id == 0xC8 || chip_id == 0xD2 || chip_id == 0x2C || chip_id == 0x36 || chip_id == 0x37) {  		comp_name = "SE,UpdatePayload";  	} else { -		info("WARNING: Unknown SE,ChipID 0x%" PRIx64 " detected. Restore might fail.\n", (uint64_t)chip_id); +		logger(LL_WARNING, "Unknown SE,ChipID 0x%" PRIx64 " detected. Restore might fail.\n", (uint64_t)chip_id);  		if (build_identity_has_component(client->restore->build_identity, "SE,UpdatePayload"))  			comp_name = "SE,UpdatePayload";  		else if (build_identity_has_component(client->restore->build_identity, "SE,Firmware"))  			comp_name = "SE,Firmware";  		else { -			error("ERROR: Neither 'SE,Firmware' nor 'SE,UpdatePayload' found in build identity.\n"); +			logger(LL_ERROR, "Neither 'SE,Firmware' nor 'SE,UpdatePayload' found in build identity.\n");  			return NULL;  		} -		debug("DEBUG: %s: using %s\n", __func__, comp_name); +		logger(LL_DEBUG, "%s: using %s\n", __func__, comp_name);  	}  	p_dgr = plist_dict_get_item(arguments, "DeviceGeneratedRequest");  	if (!p_dgr) { -		info("NOTE: %s: No DeviceGeneratedRequest in firmware updater data request. Continuing anyway.\n", __func__); +		logger(LL_NOTICE, "%s: No DeviceGeneratedRequest in firmware updater data request. Continuing anyway.\n", __func__);  	} else if (!PLIST_IS_DICT(p_dgr)) { -		error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); -		return NULL; -	} - -	if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { -		error("ERROR: Unable to get path for '%s' component\n", comp_name); -		return NULL; -	} - -	ret = extract_component(client->ipsw, comp_path, &component_data, &component_size); -	free(comp_path); -	comp_path = NULL; -	if (ret < 0) { -		error("ERROR: Unable to extract '%s' component\n", comp_name); +		logger(LL_ERROR, "%s: DeviceGeneratedRequest has invalid type!\n", __func__);  		return NULL;  	}  	/* create SE request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create SE TSS request\n"); +		logger(LL_ERROR, "Unable to create SE TSS request\n");  		free(component_data);  		return NULL;  	} @@ -2662,21 +2696,42 @@ static plist_t restore_get_se_firmware_data(struct idevicerestore_client_t* clie  	plist_free(parameters); -	info("Sending SE TSS request...\n"); +	logger(LL_INFO, "Sending SE TSS request...\n");  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch SE ticket\n"); +		logger(LL_ERROR, "Unable to fetch SE ticket\n");  		free(component_data);  		return NULL;  	}  	if (plist_dict_get_item(response, "SE2,Ticket")) { -		info("Received SE2,Ticket\n"); +		logger(LL_INFO, "Received SE2,Ticket\n");  	} else if (plist_dict_get_item(response, "SE,Ticket")) { -		info("Received SE,Ticket\n"); +		logger(LL_INFO, "Received SE,Ticket\n");  	} else { -		error("ERROR: No 'SE ticket' in TSS response, this might not work\n"); +		logger(LL_ERROR, "No 'SE ticket' in TSS response, this might not work\n"); +	} + +	/* don't add FirmwareData if not requested via ResponseTags */ +	if (!_wants_firmware_data(arguments)) { +		logger(LL_DEBUG, "Not adding FirmwareData as it was not requested\n"); +		return response; +	} + +	if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { +		plist_free(response); +		logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name); +		return NULL; +	} + +	ret = extract_component(client->ipsw, comp_path, &component_data, &component_size); +	free(comp_path); +	comp_path = NULL; +	if (ret < 0) { +		plist_free(response); +		logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name); +		return NULL;  	}  	plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, component_size)); @@ -2691,29 +2746,29 @@ static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t*  {  	char *comp_name = NULL;  	char *comp_path = NULL; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; -	unsigned char* component_data_tmp = NULL; +	void* component_data = NULL; +	size_t component_size = 0; +	void* component_data_tmp = NULL;  	plist_t parameters = NULL;  	plist_t request = NULL;  	plist_t response = NULL;  	int ret;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return NULL;  	}  	plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest");  	if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { -		error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: DeviceGeneratedRequest has invalid type!\n", __func__);  		return NULL;  	}  	/* create Savage request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create Savage TSS request\n"); +		logger(LL_ERROR, "Unable to create Savage TSS request\n");  		return NULL;  	} @@ -2731,30 +2786,37 @@ static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t*  	plist_free(parameters);  	if (!comp_name) { -		error("ERROR: Could not determine Savage firmware component\n"); +		logger(LL_ERROR, "Could not determine Savage firmware component\n");  		plist_free(request);  		return NULL;  	} -	debug("DEBUG: %s: using %s\n", __func__, comp_name); +	logger(LL_DEBUG, "%s: using %s\n", __func__, comp_name); -	info("Sending Savage TSS request...\n"); +	logger(LL_INFO, "Sending Savage TSS request...\n");  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch Savage ticket\n"); +		logger(LL_ERROR, "Unable to fetch Savage ticket\n");  		free(comp_name);  		return NULL;  	}  	if (plist_dict_get_item(response, "Savage,Ticket")) { -		info("Received Savage ticket\n"); +		logger(LL_INFO, "Received Savage ticket\n");  	} else { -		error("ERROR: No 'Savage,Ticket' in TSS response, this might not work\n"); +		logger(LL_ERROR, "No 'Savage,Ticket' in TSS response, this might not work\n"); +	} + +	/* don't add FirmwareData if not requested via ResponseTags */ +	if (!_wants_firmware_data(arguments)) { +		logger(LL_DEBUG, "Not adding FirmwareData as it was not requested\n"); +		return response;  	}  	/* now get actual component data */  	if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { -		error("ERROR: Unable to get path for '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name);  		free(comp_name);  		return NULL;  	} @@ -2763,7 +2825,8 @@ static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t*  	free(comp_path);  	comp_path = NULL;  	if (ret < 0) { -		error("ERROR: Unable to extract '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name);  		free(comp_name);  		return NULL;  	} @@ -2773,6 +2836,7 @@ static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t*  	component_data_tmp = realloc(component_data, (size_t)component_size+16);  	if (!component_data_tmp) {  		free(component_data); +		plist_free(response);  		return NULL;  	}  	component_data = component_data_tmp; @@ -2793,30 +2857,28 @@ static plist_t restore_get_yonkers_firmware_data(struct idevicerestore_client_t*  {  	char *comp_name = NULL;  	char *comp_path = NULL; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	plist_t parameters = NULL;  	plist_t request = NULL;  	plist_t response = NULL;  	int ret;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return NULL;  	}  	plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest");  	if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { -		error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: DeviceGeneratedRequest has invalid type!\n", __func__);  		return NULL;  	}  	/* create Yonkers request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create Yonkers TSS request\n"); -		free(component_data); -		free(comp_name); +		logger(LL_ERROR, "Unable to create Yonkers TSS request\n");  		return NULL;  	} @@ -2834,29 +2896,37 @@ static plist_t restore_get_yonkers_firmware_data(struct idevicerestore_client_t*  	plist_free(parameters);  	if (!comp_name) { -		error("ERROR: Could not determine Yonkers firmware component\n"); +		logger(LL_ERROR, "Could not determine Yonkers firmware component\n");  		plist_free(request);  		return NULL;  	} -	debug("DEBUG: %s: using %s\n", __func__, comp_name); +	logger(LL_DEBUG, "%s: using %s\n", __func__, comp_name); -	info("Sending Yonkers TSS request...\n"); +	logger(LL_INFO, "Sending Yonkers TSS request...\n");  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch Yonkers ticket\n"); -		free(component_data); +		logger(LL_ERROR, "Unable to fetch Yonkers ticket\n"); +		free(comp_name);  		return NULL;  	}  	if (plist_dict_get_item(response, "Yonkers,Ticket")) { -		info("Received Yonkers ticket\n"); +		logger(LL_INFO, "Received Yonkers ticket\n");  	} else { -		error("ERROR: No 'Yonkers,Ticket' in TSS response, this might not work\n"); +		logger(LL_ERROR, "No 'Yonkers,Ticket' in TSS response, this might not work\n"); +	} + +	/* don't add FirmwareData if not requested via ResponseTags */ +	if (!_wants_firmware_data(arguments)) { +		logger(LL_DEBUG, "Not adding FirmwareData as it was not requested\n"); +		free(comp_name); +		return response;  	}  	if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { -		error("ERROR: Unable to get path for '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name);  		free(comp_name);  		return NULL;  	} @@ -2866,7 +2936,8 @@ static plist_t restore_get_yonkers_firmware_data(struct idevicerestore_client_t*  	free(comp_path);  	comp_path = NULL;  	if (ret < 0) { -		error("ERROR: Unable to extract '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name);  		free(comp_name);  		return NULL;  	} @@ -2888,8 +2959,8 @@ static plist_t restore_get_rose_firmware_data(struct idevicerestore_client_t* cl  {  	char *comp_name = NULL;  	char *comp_path = NULL; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	ftab_t ftab = NULL;  	ftab_t rftab = NULL;  	uint32_t ftag = 0; @@ -2899,15 +2970,14 @@ static plist_t restore_get_rose_firmware_data(struct idevicerestore_client_t* cl  	int ret;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return NULL;  	}  	/* create Rose request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create Rose TSS request\n"); -		free(component_data); +		logger(LL_ERROR, "Unable to create Rose TSS request\n");  		return NULL;  	} @@ -2938,56 +3008,59 @@ static plist_t restore_get_rose_firmware_data(struct idevicerestore_client_t* cl  	plist_free(parameters); -	info("Sending Rose TSS request...\n"); +	logger(LL_INFO, "Sending Rose TSS request...\n");  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch Rose ticket\n"); -		free(component_data); +		logger(LL_ERROR, "Unable to fetch Rose ticket\n");  		return NULL;  	}  	if (plist_dict_get_item(response, "Rap,Ticket")) { -		info("Received Rose ticket\n"); +		logger(LL_INFO, "Received Rose ticket\n");  	} else { -		error("ERROR: No 'Rap,Ticket' in TSS response, this might not work\n"); +		logger(LL_ERROR, "No 'Rap,Ticket' in TSS response, this might not work\n");  	} -	/* skip FirmwareData for newer versions */ -	if (client->build_major >= 20) { -		debug("DEBUG: Not adding FirmwareData.\n"); +	/* don't add FirmwareData if not requested via ResponseTags */ +	if (!_wants_firmware_data(arguments)) { +		logger(LL_DEBUG, "Not adding FirmwareData as it was not requested\n");  		return response;  	}  	comp_name = "Rap,RTKitOS";  	if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { -		error("ERROR: Unable to get path for '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name);  		return NULL;  	}  	ret = extract_component(client->ipsw, comp_path, &component_data, &component_size);  	free(comp_path);  	comp_path = NULL;  	if (ret < 0) { -		error("ERROR: Unable to extract '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name);  		return NULL;  	}  	if (ftab_parse(component_data, component_size, &ftab, &ftag) != 0) { +		plist_free(response);  		free(component_data); -		error("ERROR: Failed to parse '%s' component data.\n", comp_name); +		logger(LL_ERROR, "Failed to parse '%s' component data.\n", comp_name);  		return NULL;  	}  	free(component_data);  	component_data = NULL;  	component_size = 0;  	if (ftag != 'rkos') { -		error("WARNING: Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos'); +		logger(LL_WARNING, "Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos');  	}  	comp_name = "Rap,RestoreRTKitOS";  	if (build_identity_has_component(client->restore->build_identity, comp_name)) {  		if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {  			ftab_free(ftab); -			error("ERROR: Unable to get path for '%s' component\n", comp_name); +			plist_free(response); +			logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name);  			return NULL;  		}  		ret = extract_component(client->ipsw, comp_path, &component_data, &component_size); @@ -2995,7 +3068,8 @@ static plist_t restore_get_rose_firmware_data(struct idevicerestore_client_t* cl  		comp_path = NULL;  		if (ret < 0) {  			ftab_free(ftab); -			error("ERROR: Unable to extract '%s' component\n", comp_name); +			plist_free(response); +			logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name);  			return NULL;  		} @@ -3003,26 +3077,27 @@ static plist_t restore_get_rose_firmware_data(struct idevicerestore_client_t* cl  		if (ftab_parse(component_data, component_size, &rftab, &ftag) != 0) {  			free(component_data);  			ftab_free(ftab); -			error("ERROR: Failed to parse '%s' component data.\n", comp_name); +			plist_free(response); +			logger(LL_ERROR, "Failed to parse '%s' component data.\n", comp_name);  			return NULL;  		}  		free(component_data);  		component_data = NULL;  		component_size = 0;  		if (ftag != 'rkos') { -			error("WARNING: Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos'); +			logger(LL_WARNING, "Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos');  		}  		if (ftab_get_entry_ptr(rftab, 'rrko', &component_data, &component_size) == 0) {  			ftab_add_entry(ftab, 'rrko', component_data, component_size);  		} else { -			error("ERROR: Could not find 'rrko' entry in ftab. This will probably break things.\n"); +			logger(LL_ERROR, "Could not find 'rrko' entry in ftab. This will probably break things.\n");  		}  		ftab_free(rftab);  		component_data = NULL;  		component_size = 0;  	} else { -		info("NOTE: Build identity does not have a '%s' component.\n", comp_name); +		logger(LL_NOTICE, "Build identity does not have a '%s' component.\n", comp_name);  	}  	ftab_write(ftab, &component_data, &component_size); @@ -3040,28 +3115,28 @@ static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t  {  	char *comp_name = "BMU,FirmwareMap";  	char *comp_path = NULL; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	plist_t parameters = NULL;  	plist_t request = NULL;  	plist_t response = NULL;  	int ret;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return NULL;  	}  	plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest");  	if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { -		error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: DeviceGeneratedRequest has invalid type!\n", __func__);  		return NULL;  	}  	/* create Veridian request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create Veridian TSS request\n"); +		logger(LL_ERROR, "Unable to create Veridian TSS request\n");  		free(component_data);  		return NULL;  	} @@ -3079,23 +3154,30 @@ static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t  	plist_free(parameters); -	info("Sending Veridian TSS request...\n"); +	logger(LL_INFO, "Sending Veridian TSS request...\n");  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch Veridian ticket\n"); +		logger(LL_ERROR, "Unable to fetch Veridian ticket\n");  		free(component_data);  		return NULL;  	}  	if (plist_dict_get_item(response, "BMU,Ticket")) { -		info("Received Veridian ticket\n"); +		logger(LL_INFO, "Received Veridian ticket\n");  	} else { -		error("ERROR: No 'BMU,Ticket' in TSS response, this might not work\n"); +		logger(LL_ERROR, "No 'BMU,Ticket' in TSS response, this might not work\n"); +	} + +	/* don't add FirmwareData if not requested via ResponseTags */ +	if (!_wants_firmware_data(arguments)) { +		logger(LL_DEBUG, "Not adding FirmwareData as it was not requested\n"); +		return response;  	}  	if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { -		error("ERROR: Unable to get path for '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name);  		return NULL;  	} @@ -3104,7 +3186,8 @@ static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t  	free(comp_path);  	comp_path = NULL;  	if (ret < 0) { -		error("ERROR: Unable to extract '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name);  		return NULL;  	} @@ -3119,14 +3202,16 @@ static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t  	component_size = 0;  	if (!fw_map) { -		error("ERROR: Unable to parse '%s' component data as plist\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to parse '%s' component data as plist\n", comp_name);  		return NULL;  	}  	plist_t fw_map_digest = plist_access_path(client->restore->build_identity, 3, "Manifest", comp_name, "Digest");  	if (!fw_map_digest) {  		plist_free(fw_map); -		error("ERROR: Unable to get Digest for '%s' component\n", comp_name); +		plist_free(response); +		logger(LL_ERROR, "Unable to get Digest for '%s' component\n", comp_name);  		return NULL;  	} @@ -3160,39 +3245,41 @@ static plist_t restore_get_generic_firmware_data(struct idevicerestore_client_t*  		}  	}  	if (response_ticket == NULL) { -		error("ERROR: Unable to determine response ticket from device generated tags"); +		logger(LL_ERROR, "Unable to determine response ticket from device generated tags\n");  		return NULL;  	}  	/* create TSS request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create %s TSS request\n", s_updater_name); +		logger(LL_ERROR, "Unable to create %s TSS request\n", s_updater_name);  		return NULL;  	}  	/* add device generated request data to request */  	plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest");  	if (!device_generated_request) { -		error("ERROR: Could not find DeviceGeneratedRequest in arguments dictionary\n"); +		logger(LL_ERROR, "Could not find DeviceGeneratedRequest in arguments dictionary\n");  		plist_free(request);  		return NULL;  	}  	plist_dict_merge(&request, device_generated_request); -	info("Sending %s TSS request...\n", s_updater_name); +	logger(LL_INFO, "Sending %s TSS request...\n", s_updater_name); +	logger_dump_plist(LL_DEBUG, request, 0);  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch %s ticket\n", s_updater_name); +		logger(LL_ERROR, "Unable to fetch %s ticket\n", s_updater_name);  		return NULL;  	} +	logger_dump_plist(LL_DEBUG, response, 0);  	if (plist_dict_get_item(response, response_ticket)) { -		info("Received %s\n", response_ticket); +		logger(LL_INFO, "Received %s\n", response_ticket);  	} else { -		error("ERROR: No '%s' in TSS response, this might not work\n", response_ticket); -		debug_plist(response); +		logger(LL_ERROR, "No '%s' in TSS response, this might not work\n", response_ticket); +		logger_dump_plist(LL_VERBOSE, response, 0);  	}  	return response; @@ -3202,28 +3289,28 @@ static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* cl  {  	char *comp_name = "Baobab,TCON";  	char *comp_path = NULL; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	plist_t parameters = NULL;  	plist_t request = NULL;  	plist_t response = NULL;  	int ret;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return NULL;  	}  	plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest");  	if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { -		error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: DeviceGeneratedRequest has invalid type!\n", __func__);  		return NULL;  	}  	/* create Baobab request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create Baobab TSS request\n"); +		logger(LL_ERROR, "Unable to create Baobab TSS request\n");  		free(component_data);  		return NULL;  	} @@ -3241,23 +3328,30 @@ static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* cl  	plist_free(parameters); -	info("Sending Baobab TSS request...\n"); +	logger(LL_INFO, "Sending Baobab TSS request...\n");  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch Baobab ticket\n"); +		logger(LL_ERROR, "Unable to fetch Baobab ticket\n");  		free(component_data);  		return NULL;  	}  	if (plist_dict_get_item(response, "Baobab,Ticket")) { -		info("Received Baobab ticket\n"); +		logger(LL_INFO, "Received Baobab ticket\n");  	} else { -		error("ERROR: No 'Baobab,Ticket' in TSS response, this might not work\n"); +		logger(LL_ERROR, "No 'Baobab,Ticket' in TSS response, this might not work\n"); +	} + +	/* don't add FirmwareData if not requested via ResponseTags */ +	if (!_wants_firmware_data(arguments)) { +		logger(LL_DEBUG, "Not adding FirmwareData as it was not requested\n"); +		return response;  	}  	if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { -		error("ERROR: Unable to get path for '%s' component\n", comp_name); +		logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name); +		plist_free(response);  		return NULL;  	} @@ -3266,7 +3360,8 @@ static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* cl  	free(comp_path);  	comp_path = NULL;  	if (ret < 0) { -		error("ERROR: Unable to extract '%s' component\n", comp_name); +		logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name); +		plist_free(response);  		return NULL;  	} @@ -3282,8 +3377,8 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c  {  	char comp_name[64];  	char *comp_path = NULL; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	ftab_t ftab = NULL;  	ftab_t rftab = NULL;  	uint32_t ftag = 0; @@ -3295,20 +3390,20 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c  	int ret;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return NULL;  	}  	plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest");  	if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { -		error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: DeviceGeneratedRequest has invalid type!\n", __func__);  		return NULL;  	}  	/* create Timer request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create Timer TSS request\n"); +		logger(LL_ERROR, "Unable to create Timer TSS request\n");  		return NULL;  	} @@ -3328,7 +3423,7 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c  	/* add Timer,* tags from info dictionary to parameters */  	plist_t info_array = plist_dict_get_item(p_info, "InfoArray");  	if (!info_array) { -		error("ERROR: Could not find InfoArray in info dictionary\n"); +		logger(LL_ERROR, "Could not find InfoArray in info dictionary\n");  		plist_free(parameters);  		return NULL;  	} else { @@ -3344,30 +3439,30 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c  			plist_dict_set_item(parameters, "TicketName", plist_copy(node));  		} -		sprintf(key, "Timer,ChipID,%u", tag); +		snprintf(key, sizeof(key), "Timer,ChipID,%u", tag);  		plist_dict_copy_uint(parameters, hwid, key, "ChipID"); -		sprintf(key, "Timer,BoardID,%u", tag); +		snprintf(key, sizeof(key), "Timer,BoardID,%u", tag);  		plist_dict_copy_uint(parameters, hwid, key, "BoardID"); -		sprintf(key, "Timer,ECID,%u", tag); +		snprintf(key, sizeof(key), "Timer,ECID,%u", tag);  		plist_dict_copy_uint(parameters, hwid, key, "ECID"); -		sprintf(key, "Timer,Nonce,%u", tag); +		snprintf(key, sizeof(key), "Timer,Nonce,%u", tag);  		plist_dict_copy_data(parameters, hwid, key, "Nonce"); -		sprintf(key, "Timer,SecurityMode,%u", tag); +		snprintf(key, sizeof(key), "Timer,SecurityMode,%u", tag);  		plist_dict_copy_bool(parameters, hwid, key, "SecurityMode"); -		sprintf(key, "Timer,SecurityDomain,%u", tag); +		snprintf(key, sizeof(key), "Timer,SecurityDomain,%u", tag);  		plist_dict_copy_uint(parameters, hwid, key, "SecurityDomain"); -		sprintf(key, "Timer,ProductionMode,%u", tag); +		snprintf(key, sizeof(key), "Timer,ProductionMode,%u", tag);  		plist_dict_copy_uint(parameters, hwid, key, "ProductionStatus");  	}  	plist_t ap_info = plist_dict_get_item(p_info, "APInfo");  	if (!ap_info) { -		error("ERROR: Could not find APInfo in info dictionary\n"); +		logger(LL_ERROR, "Could not find APInfo in info dictionary\n");  		plist_free(parameters);  		return NULL;  	} else { @@ -3379,53 +3474,63 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c  	plist_free(parameters); -	info("Sending %s TSS request...\n", ticket_name); +	logger(LL_INFO, "Sending %s TSS request...\n", ticket_name);  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch %s\n", ticket_name); +		logger(LL_ERROR, "Unable to fetch %s\n", ticket_name);  		return NULL;  	}  	if (plist_dict_get_item(response, ticket_name)) { -		info("Received %s\n", ticket_name); +		logger(LL_INFO, "Received %s\n", ticket_name);  	} else { -		error("ERROR: No '%s' in TSS response, this might not work\n", ticket_name); +		logger(LL_ERROR, "No '%s' in TSS response, this might not work\n", ticket_name); +	} + +	/* don't add FirmwareData if not requested via ResponseTags */ +	if (!_wants_firmware_data(arguments)) { +		logger(LL_DEBUG, "Not adding FirmwareData as it was not requested\n"); +		return response;  	} -	sprintf(comp_name, "Timer,RTKitOS,%u", tag); +	snprintf(comp_name, sizeof(comp_name), "Timer,RTKitOS,%u", tag);  	if (build_identity_has_component(client->restore->build_identity, comp_name)) {  		if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { -			error("ERROR: Unable to get path for '%s' component\n", comp_name); +			plist_free(response); +			logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name);  			return NULL;  		}  		ret = extract_component(client->ipsw, comp_path, &component_data, &component_size);  		free(comp_path);  		comp_path = NULL;  		if (ret < 0) { -			error("ERROR: Unable to extract '%s' component\n", comp_name); +			logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name); +			plist_free(response);  			return NULL;  		}  		if (ftab_parse(component_data, component_size, &ftab, &ftag) != 0) {  			free(component_data); -			error("ERROR: Failed to parse '%s' component data.\n", comp_name); +			plist_free(response); +			logger(LL_ERROR, "Failed to parse '%s' component data.\n", comp_name);  			return NULL;  		}  		free(component_data);  		component_data = NULL;  		component_size = 0;  		if (ftag != 'rkos') { -			error("WARNING: Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos'); +			logger(LL_WARNING, "Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos');  		}  	} else { -		info("NOTE: Build identity does not have a '%s' component.\n", comp_name); +		logger(LL_NOTICE, "Build identity does not have a '%s' component.\n", comp_name);  	} -	sprintf(comp_name, "Timer,RestoreRTKitOS,%u", tag); +	snprintf(comp_name, sizeof(comp_name), "Timer,RestoreRTKitOS,%u", tag);  	if (build_identity_has_component(client->restore->build_identity, comp_name)) {  		if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {  			ftab_free(ftab); -			error("ERROR: Unable to get path for '%s' component\n", comp_name); +			plist_free(response); +			logger(LL_ERROR, "Unable to get path for '%s' component\n", comp_name);  			return NULL;  		}  		ret = extract_component(client->ipsw, comp_path, &component_data, &component_size); @@ -3433,7 +3538,8 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c  		comp_path = NULL;  		if (ret < 0) {  			ftab_free(ftab); -			error("ERROR: Unable to extract '%s' component\n", comp_name); +			plist_free(response); +			logger(LL_ERROR, "Unable to extract '%s' component\n", comp_name);  			return NULL;  		} @@ -3441,26 +3547,27 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c  		if (ftab_parse(component_data, component_size, &rftab, &ftag) != 0) {  			free(component_data);  			ftab_free(ftab); -			error("ERROR: Failed to parse '%s' component data.\n", comp_name); +			plist_free(response); +			logger(LL_ERROR, "Failed to parse '%s' component data.\n", comp_name);  			return NULL;  		}  		free(component_data);  		component_data = NULL;  		component_size = 0;  		if (ftag != 'rkos') { -			error("WARNING: Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos'); +			logger(LL_WARNING, "Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos');  		}  		if (ftab_get_entry_ptr(rftab, 'rrko', &component_data, &component_size) == 0) {  			ftab_add_entry(ftab, 'rrko', component_data, component_size);  		} else { -			error("ERROR: Could not find 'rrko' entry in ftab. This will probably break things.\n"); +			logger(LL_ERROR, "Could not find 'rrko' entry in ftab. This will probably break things.\n");  		}  		ftab_free(rftab);  		component_data = NULL;  		component_size = 0;  	} else { -		info("NOTE: Build identity does not have a '%s' component.\n", comp_name); +		logger(LL_NOTICE, "Build identity does not have a '%s' component.\n", comp_name);  	}  	ftab_write(ftab, &component_data, &component_size); @@ -3481,7 +3588,7 @@ static plist_t restore_get_cryptex1_firmware_data(struct idevicerestore_client_t  	plist_t response = NULL;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return NULL;  	} @@ -3500,7 +3607,7 @@ static plist_t restore_get_cryptex1_firmware_data(struct idevicerestore_client_t  	/* create Cryptex1 request */  	request = tss_request_new(NULL);  	if (request == NULL) { -		error("ERROR: Unable to create %s TSS request\n", s_updater_name); +		logger(LL_ERROR, "Unable to create %s TSS request\n", s_updater_name);  		return NULL;  	} @@ -3540,7 +3647,7 @@ static plist_t restore_get_cryptex1_firmware_data(struct idevicerestore_client_t  	/* add device generated request data to parameters */  	plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest");  	if (!device_generated_request) { -		error("ERROR: Could not find DeviceGeneratedRequest in arguments dictionary\n"); +		logger(LL_ERROR, "Could not find DeviceGeneratedRequest in arguments dictionary\n");  		plist_free(parameters);  		return NULL;  	} @@ -3551,19 +3658,19 @@ static plist_t restore_get_cryptex1_firmware_data(struct idevicerestore_client_t  	plist_free(parameters); -	info("Sending %s TSS request...\n", s_updater_name); +	logger(LL_INFO, "Sending %s TSS request...\n", s_updater_name);  	response = tss_request_send(request, client->tss_url);  	plist_free(request);  	if (response == NULL) { -		error("ERROR: Unable to fetch %s ticket\n", s_updater_name); +		logger(LL_ERROR, "Unable to fetch %s ticket\n", s_updater_name);  		return NULL;  	}  	if (plist_dict_get_item(response, response_ticket)) { -		info("Received %s\n", response_ticket); +		logger(LL_INFO, "Received %s\n", response_ticket);  	} else { -		error("ERROR: No '%s' in TSS response, this might not work\n", response_ticket); -		debug_plist(response); +		logger(LL_ERROR, "No '%s' in TSS response, this might not work\n", response_ticket); +		logger_dump_plist(LL_VERBOSE, response, 0);  	}  	return response; @@ -3574,29 +3681,29 @@ static int restore_send_firmware_updater_preflight(struct idevicerestore_client_  	plist_t dict = NULL;  	int restore_error; -	if (idevicerestore_debug) { -		debug("DEBUG: %s: Got FirmwareUpdaterPreflight request:\n", __func__); -		debug_plist(message); +	if (client->debug_level > 1) { +		logger(LL_DEBUG, "%s: Got FirmwareUpdaterPreflight request:\n", __func__); +		logger_dump_plist(LL_DEBUG, message, 1);  	}  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	}  	dict = plist_new_dict(); -	info("Sending FirmwareResponsePreflight now...\n"); +	logger(LL_INFO, "Sending FirmwareResponsePreflight now...\n");  	restore_error = _restore_service_send(service, dict, 0);  	plist_free(dict);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Couldn't send FirmwareResponsePreflight data (%d)\n", restore_error); +		logger(LL_ERROR, "Couldn't send FirmwareResponsePreflight data (%d)\n", restore_error);  		return -1;  	} -	info("Done sending FirmwareUpdaterPreflight response\n"); +	logger(LL_INFO, "Done sending FirmwareUpdaterPreflight response\n");  	return 0;  } @@ -3612,30 +3719,30 @@ static int restore_send_firmware_updater_data(struct idevicerestore_client_t* cl  	int restore_error;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	} -	if (idevicerestore_debug) { -		debug("DEBUG: %s: Got FirmwareUpdaterData request:\n", __func__); -		debug_plist(message); +	if (client->debug_level > 1) { +		logger(LL_DEBUG, "%s: Got FirmwareUpdaterData request:\n", __func__); +		logger_dump_plist(LL_DEBUG, message, 1);  	}  	arguments = plist_dict_get_item(message, "Arguments");  	if (!arguments || plist_get_node_type(arguments) != PLIST_DICT) { -		error("ERROR: %s: Arguments missing or has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: Arguments missing or has invalid type!\n", __func__);  		goto error_out;  	}  	p_type = plist_dict_get_item(arguments, "MessageArgType");  	if (!p_type || (plist_get_node_type(p_type) != PLIST_STRING)) { -		error("ERROR: %s: MessageArgType missing or has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: MessageArgType missing or has invalid type!\n", __func__);  		goto error_out;  	}  	p_updater_name = plist_dict_get_item(arguments, "MessageArgUpdaterName");  	if (!p_updater_name || (plist_get_node_type(p_updater_name) != PLIST_STRING)) { -		error("ERROR: %s: MessageArgUpdaterName missing or has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: MessageArgUpdaterName missing or has invalid type!\n", __func__);  		goto error_out;  	} @@ -3647,7 +3754,7 @@ static int restore_send_firmware_updater_data(struct idevicerestore_client_t* cl  	plist_get_string_val(p_type, &s_type);  	if (!s_type || strcmp(s_type, "FirmwareResponseData")) { -		error("ERROR: %s: MessageArgType has unexpected value '%s'\n", __func__, s_type); +		logger(LL_ERROR, "%s: MessageArgType has unexpected value '%s'\n", __func__, s_type);  		goto error_out;  	}  	free(s_type); @@ -3655,78 +3762,95 @@ static int restore_send_firmware_updater_data(struct idevicerestore_client_t* cl  	p_info = plist_dict_get_item(arguments, "MessageArgInfo");  	if (!p_info || (plist_get_node_type(p_info) != PLIST_DICT)) { -		error("ERROR: %s: MessageArgInfo missing or has invalid type!\n", __func__); +		logger(LL_ERROR, "%s: MessageArgInfo missing or has invalid type!\n", __func__);  		goto error_out;  	}  	plist_get_string_val(p_updater_name, &s_updater_name); +	logger_dump_plist(LL_DEBUG, p_info, 1);  	if (strcmp(s_updater_name, "SE") == 0) {  		fwdict = restore_get_se_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get SE firmware data\n", __func__); +			logger(LL_ERROR, "%s: Couldn't get SE firmware data\n", __func__);  			goto error_out;  		}  	} else if (strcmp(s_updater_name, "Savage") == 0) {  		const char *fwtype = "Savage"; -		plist_t p_info2 = plist_dict_get_item(p_info, "YonkersDeviceInfo"); -		if (p_info2 && plist_get_node_type(p_info2) == PLIST_DICT) { +		plist_t p_info_yonkers = plist_dict_get_item(p_info, "YonkersDeviceInfo"); +		plist_t p_info_jasmine = plist_dict_get_item(p_info, "JasmineIR1DeviceInfo"); +		if (PLIST_IS_DICT(p_info_yonkers)) {  			fwtype = "Yonkers"; -			fwdict = restore_get_yonkers_firmware_data(client, p_info2, arguments); +			fwdict = restore_get_yonkers_firmware_data(client, p_info_yonkers, arguments); +		} else if (PLIST_IS_DICT(p_info_jasmine)) { +			fwtype = "Jasmine"; +			fwdict = restore_get_generic_firmware_data(client, p_info_jasmine, arguments);  		} else {  			fwdict = restore_get_savage_firmware_data(client, p_info, arguments);  		}  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get %s firmware data\n", __func__, fwtype); +			logger(LL_ERROR, "%s: Couldn't get %s firmware data\n", __func__, fwtype);  			goto error_out;  		}  	} else if (strcmp(s_updater_name, "Rose") == 0) {  		fwdict = restore_get_rose_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get Rose firmware data\n", __func__); +			logger(LL_ERROR, "%s: Couldn't get Rose firmware data\n", __func__);  			goto error_out;  		}  	} else if (strcmp(s_updater_name, "T200") == 0) {  		fwdict = restore_get_veridian_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get Veridian firmware data\n", __func__); +			logger(LL_ERROR, "%s: Couldn't get Veridian firmware data\n", __func__);  			goto error_out;  		}  	} else if (strcmp(s_updater_name, "AppleTCON") == 0) {  		fwdict = restore_get_tcon_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get AppleTCON firmware data\n", __func__); +			logger(LL_ERROR, "%s: Couldn't get AppleTCON firmware data\n", __func__);  			goto error_out;  		}  	} else if (strcmp(s_updater_name, "PS190") == 0) {  		fwdict = restore_get_generic_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get PCON1 firmware data\n", __func__); +			logger(LL_ERROR, "%s: Couldn't get PCON1 firmware data\n", __func__);  			goto error_out;  		}  	} else if (strcmp(s_updater_name, "AppleTypeCRetimer") == 0) {  		fwdict = restore_get_timer_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get AppleTypeCRetimer firmware data\n", __func__); +			logger(LL_ERROR, "%s: Couldn't get AppleTypeCRetimer firmware data\n", __func__);  			goto error_out;  		}  	} else if ((strcmp(s_updater_name, "Cryptex1") == 0) || (strcmp(s_updater_name, "Cryptex1LocalPolicy") == 0)) {  		fwdict = restore_get_cryptex1_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name); +			logger(LL_ERROR, "%s: Couldn't get %s firmware data\n", __func__, s_updater_name);  			goto error_out;  		}  	} else if (strcmp(s_updater_name, "Ace3") == 0) {  		fwdict = restore_get_generic_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name); +			logger(LL_ERROR, "%s: Couldn't get %s firmware data\n", __func__, s_updater_name); +			goto error_out; +		} +	} else if (strcmp(s_updater_name, "Centauri") == 0) { +		fwdict = restore_get_generic_firmware_data(client, p_info, arguments); +		if (fwdict == NULL) { +			logger(LL_ERROR, "%s: Couldn't get %s firmware data\n", __func__, s_updater_name); +			goto error_out; +		} +	} else if (strcmp(s_updater_name, "Vinyl") == 0) { +		fwdict = restore_get_generic_firmware_data(client, p_info, arguments); +		if (fwdict == NULL) { +			logger(LL_ERROR, "%s: Couldn't get %s firmware data\n", __func__, s_updater_name);  			goto error_out;  		}  	} else { -		error("ERROR: %s: Got unknown updater name '%s', trying to discover from device generated request.\n", __func__, s_updater_name); +		logger(LL_ERROR, "%s: Got unknown updater name '%s', trying to discover from device generated request.\n", __func__, s_updater_name);  		fwdict = restore_get_generic_firmware_data(client, p_info, arguments);  		if (fwdict == NULL) { -			error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name); +			logger(LL_ERROR, "%s: Couldn't get %s firmware data\n", __func__, s_updater_name);  			goto error_out;  		}  	} @@ -3735,23 +3859,23 @@ static int restore_send_firmware_updater_data(struct idevicerestore_client_t* cl  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	}  	dict = plist_new_dict();  	plist_dict_set_item(dict, "FirmwareResponseData", fwdict); -	info("Sending FirmwareResponse data now...\n"); +	logger(LL_INFO, "Sending FirmwareResponse data now...\n");  	restore_error = _restore_service_send(service, dict, 0);  	plist_free(dict);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Couldn't send FirmwareResponse data (%d)\n", restore_error); +		logger(LL_ERROR, "Couldn't send FirmwareResponse data (%d)\n", restore_error);  		goto error_out;  	} -	info("Done sending FirmwareUpdater data\n"); +	logger(LL_INFO, "Done sending FirmwareUpdater data\n");  	return 0; @@ -3768,35 +3892,35 @@ static int restore_send_receipt_manifest(struct idevicerestore_client_t* client,  	int restore_error;  	if (!client || !client->restore || !client->restore->build_identity) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	}  	plist_t manifest = plist_dict_get_item(client->restore->build_identity, "Manifest");  	if (!manifest) { -		error("failed to get Manifest node from build_identity"); +		logger(LL_ERROR, "%s: Failed to get Manifest node from build_identity\n", __func__);  		goto error_out;  	}  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	}  	dict = plist_new_dict();  	plist_dict_set_item(dict, "ReceiptManifest", plist_copy(manifest)); -	info("Sending ReceiptManifest data now...\n"); +	logger(LL_INFO, "Sending ReceiptManifest data now...\n");  	restore_error = _restore_service_send(service, dict, 0);  	plist_free(dict);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Couldn't send ReceiptManifest data (%d)\n", restore_error); +		logger(LL_ERROR, "Couldn't send ReceiptManifest data (%d)\n", restore_error);  		goto error_out;  	} -	info("Done sending ReceiptManifest data\n"); +	logger(LL_INFO, "Done sending ReceiptManifest data\n");  	return 0; @@ -3850,20 +3974,20 @@ static int cpio_send_file(idevice_connection_t connection, const char *name, str  	device_error = idevice_connection_send(connection, (void *)&hdr, sizeof(hdr), &bytes);  	if (device_error != IDEVICE_E_SUCCESS || bytes != sizeof(hdr)) { -		error("ERROR: BootabilityBundle unable to send header. (%d) Sent %u of %lu bytes.\n", device_error, bytes, (long)sizeof(hdr)); +		logger(LL_ERROR, "BootabilityBundle unable to send header. (%d) Sent %u of %lu bytes.\n", device_error, bytes, (long)sizeof(hdr));  		return -1;  	}  	device_error = idevice_connection_send(connection, (void *)name, name_len, &bytes);  	if (device_error != IDEVICE_E_SUCCESS || bytes != name_len) { -		error("ERROR: BootabilityBundle unable to send filename. (%d) Sent %u of %u bytes.\n", device_error, bytes, name_len); +		logger(LL_ERROR, "BootabilityBundle unable to send filename. (%d) Sent %u of %u bytes.\n", device_error, bytes, name_len);  		return -1;  	}  	if (st->st_size && data) {  		device_error = idevice_connection_send(connection, data, st->st_size, &bytes);  		if (device_error != IDEVICE_E_SUCCESS || bytes != st->st_size) { -			error("ERROR: BootabilityBundle unable to send data. (%d) Sent %u of %lu bytes.\n", device_error, bytes, (long)st->st_size); +			logger(LL_ERROR, "BootabilityBundle unable to send data. (%d) Sent %u of %lu bytes.\n", device_error, bytes, (long)st->st_size);  			return -1;  		}  	} @@ -3885,15 +4009,15 @@ static int restore_bootability_send_one(void *ctx, ipsw_archive_t ipsw, const ch  		subpath = name + strlen(prefix);  	} -	debug("DEBUG: BootabilityBundle send m=%07o s=%10ld %s\n", stat->st_mode, (long)stat->st_size, subpath); +	logger(LL_DEBUG, "BootabilityBundle send m=%07o s=%10ld %s\n", stat->st_mode, (long)stat->st_size, subpath); -	unsigned char *buf = NULL; -	unsigned int size = 0; +	void *buf = NULL; +	size_t size = 0;  	if ((S_ISLNK(stat->st_mode) || S_ISREG(stat->st_mode)) && stat->st_size != 0) {  		ipsw_extract_to_memory(ipsw, name, &buf, &size);  		if (size != stat->st_size) { -			error("ERROR: expected %ld bytes but got %d for file %s\n", (long)stat->st_size, size, name); +			logger(LL_ERROR, "expected %zu bytes but got %zu for file %s\n", (size_t)stat->st_size, size, name);  			free(buf);  			return -1;  		} @@ -3909,9 +4033,9 @@ static int restore_bootability_send_one(void *ctx, ipsw_archive_t ipsw, const ch  static int restore_send_bootability_bundle_data(struct idevicerestore_client_t* client, plist_t message)  { -	if (idevicerestore_debug) { -		debug("DEBUG: %s: Got BootabilityBundle request:\n", __func__); -		debug_plist(message); +	if (client->debug_level > 1) { +		logger(LL_DEBUG, "%s: Got BootabilityBundle request:\n", __func__); +		logger_dump_plist(LL_DEBUG, message, 1);  	}  	plist_t node = plist_dict_get_item(message, "DataPort"); @@ -3924,28 +4048,28 @@ static int restore_send_bootability_bundle_data(struct idevicerestore_client_t*  	idevice_error_t device_error = IDEVICE_E_SUCCESS;  	if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) { -		error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); +		logger(LL_ERROR, "%s: idevicerestore client not initialized?!\n", __func__);  		return -1;  	} -	debug("Connecting to BootabilityBundle data port\n"); +	logger(LL_DEBUG, "Connecting to BootabilityBundle data port\n");  	while (--attempts > 0) {  		device_error = idevice_connect(client->restore->device, data_port, &connection);  		if (device_error == IDEVICE_E_SUCCESS) {  			break;  		}  		sleep(1); -		debug("Retrying connection...\n"); +		logger(LL_DEBUG, "Retrying connection...\n");  	}  	if (device_error != IDEVICE_E_SUCCESS) { -		error("ERROR: Unable to connect to BootabilityBundle data port\n"); +		logger(LL_ERROR, "Unable to connect to BootabilityBundle data port\n");  		return -1;  	}  	int ret = ipsw_list_contents(client->ipsw, restore_bootability_send_one, connection);  	if (ret < 0) { -		error("ERROR: Failed to send BootabilityBundle\n"); +		logger(LL_ERROR, "Failed to send BootabilityBundle\n");  		return ret;  	} @@ -3975,7 +4099,7 @@ plist_t restore_get_build_identity(struct idevicerestore_client_t* client, uint8  	plist_t unique_id_node = plist_dict_get_item(client->build_manifest, "UniqueBuildID");  	if (unique_id_node) { -		info("UniqueBuildID: "); +		logger(LL_INFO, "UniqueBuildID: ");  		plist_write_to_stream(unique_id_node, stdout, PLIST_FORMAT_PRINT, PLIST_OPT_NONE);  	} @@ -3992,13 +4116,13 @@ int extract_macos_variant(plist_t build_identity, char** output)  {  	plist_t build_info = plist_dict_get_item(build_identity, "Info");  	if (!build_info) { -		error("ERROR: build identity does not contain an 'Info' element\n"); +		logger(LL_ERROR, "build identity does not contain an 'Info' element\n");  		return -1;  	}  	plist_t macos_variant_node = plist_dict_get_item(build_info, "MacOSVariant");  	if (!macos_variant_node) { -		error("ERROR: build identity info does not contain a MacOSVariant\n"); +		logger(LL_ERROR, "build identity info does not contain a MacOSVariant\n");  		return -1;  	}  	plist_get_string_val(macos_variant_node, output); @@ -4010,13 +4134,13 @@ static char* extract_global_manifest_path(plist_t build_identity, char *variant)  {  	plist_t build_info = plist_dict_get_item(build_identity, "Info");  	if (!build_info) { -		error("ERROR: build identity does not contain an 'Info' element\n"); +		logger(LL_ERROR, "build identity does not contain an 'Info' element\n");  		return NULL;  	}  	plist_t device_class_node = plist_dict_get_item(build_info, "DeviceClass");  	if (!device_class_node) { -		error("ERROR: build identity info does not contain a DeviceClass\n"); +		logger(LL_ERROR, "build identity info does not contain a DeviceClass\n");  		return NULL;  	}  	char *device_class = NULL; @@ -4035,8 +4159,9 @@ static char* extract_global_manifest_path(plist_t build_identity, char *variant)  	}  	// The path of the global manifest is hardcoded. There's no pointer to in the build manifest. -	char *ticket_path = malloc((42+strlen(macos_variant)+strlen(device_class)+1)*sizeof(char)); -	sprintf(ticket_path, "Firmware/Manifests/restore/%s/apticket.%s.im4m", macos_variant, device_class); +	size_t psize = 42+strlen(macos_variant)+strlen(device_class)+1; +	char *ticket_path = malloc(psize); +	snprintf(ticket_path, psize, "Firmware/Manifests/restore/%s/apticket.%s.im4m", macos_variant, device_class);  	free(device_class);  	free(macos_variant); @@ -4044,17 +4169,17 @@ static char* extract_global_manifest_path(plist_t build_identity, char *variant)  	return ticket_path;  } -int extract_global_manifest(struct idevicerestore_client_t* client, plist_t build_identity, char *variant, unsigned char** pbuffer, unsigned int* psize) +int extract_global_manifest(struct idevicerestore_client_t* client, plist_t build_identity, char *variant, void** pbuffer, size_t* psize)  {  	char* ticket_path = extract_global_manifest_path(build_identity, variant);  	if (!ticket_path) { -		error("ERROR: failed to get global manifest path\n"); +		logger(LL_ERROR, "failed to get global manifest path\n");  		return -1;  	}  	int ret = ipsw_extract_to_memory(client->ipsw, ticket_path, pbuffer, psize);  	if (ret != 0) {  		free(ticket_path); -		error("ERROR: failed to read global manifest\n"); +		logger(LL_ERROR, "failed to read global manifest\n");  		return -1;  	}  	free(ticket_path); @@ -4066,9 +4191,10 @@ struct _restore_send_file_data_ctx {  	struct idevicerestore_client_t* client;  	restore_service_client_t service;  	int last_progress; +	uint32_t tag;  }; -static int _restore_send_file_data(struct _restore_send_file_data_ctx* rctx, void* data, size_t size, size_t done, size_t total_size) +static int _restore_send_file_data(struct _restore_send_file_data_ctx* rctx, const void* data, size_t size, size_t done, size_t total_size)  {  	plist_t dict = plist_new_dict();  	if (data != NULL) { @@ -4081,21 +4207,31 @@ static int _restore_send_file_data(struct _restore_send_file_data_ctx* rctx, voi  	restored_error_t restore_error = _restore_service_send(rctx->service, dict, 0);  	if (restore_error != RESTORE_E_SUCCESS) {  		plist_free(dict); -		error("ERROR: %s: Failed to send data (%d)\n", __func__, restore_error); +		logger(LL_ERROR, "%s: Failed to send data (%d)\n", __func__, restore_error);  		return -1;  	}  	plist_free(dict);  	/* special handling for AEA image format */  	if (done == 0 && (memcmp(data, "AEA1", 4) == 0)) { -		info("Encountered First Chunk in AEA image\n"); +		logger(LL_VERBOSE, "Encountered First Chunk in AEA image\n");  		plist_t message = NULL; -		_restore_service_recv(rctx->service, &message); -		restore_send_url_asset(rctx->client, message); +		property_list_service_error_t err = _restore_service_recv_timeout(rctx->service, &message, 3000); +		if (err == PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT) { +			logger(LL_VERBOSE, "No URLAsset requested, assuming it is not necessary.\n"); +		} else if (err == PROPERTY_LIST_SERVICE_E_SUCCESS) { +			if (PLIST_IS_DICT(message) && plist_dict_get_item(message, "Arguments")) { +				restore_send_url_asset(rctx->client, message); +			} else { +				logger(LL_DEBUG, "%s: Unexpected message received\n", __func__); +				logger_dump_plist(LL_DEBUG, message, 1); +			} +		}  	}  	if (total_size > 0x1000000) {  		double progress = (double)done / (double)total_size; +		set_progress(rctx->tag, progress);  		int progress_int = (int)(progress*100.0);  		if (progress_int > rctx->last_progress) {  			idevicerestore_progress(rctx->client, RESTORE_STEP_UPLOAD_IMG, progress); @@ -4107,32 +4243,29 @@ static int _restore_send_file_data(struct _restore_send_file_data_ctx* rctx, voi  int restore_send_personalized_boot_object_v3(struct idevicerestore_client_t* client, plist_t message)  { -	if (idevicerestore_debug) { -		debug("DEBUG: %s: Got PersonalizedBootObjectV3 request:\n", __func__); -		debug_plist(message); +	if (client->debug_level > 1) { +		logger(LL_DEBUG, "%s: Got PersonalizedBootObjectV3 request:\n", __func__); +		logger_dump_plist(LL_DEBUG, message, 1);  	}  	char *image_name = NULL;  	plist_t node = plist_access_path(message, 2, "Arguments", "ImageName");  	if (!node || plist_get_node_type(node) != PLIST_STRING) { -		debug("Failed to parse arguments from PersonalizedBootObjectV3 plist\n"); +		logger(LL_DEBUG, "Failed to parse arguments from PersonalizedBootObjectV3 plist\n");  		return -1;  	}  	plist_get_string_val(node, &image_name);  	if (!image_name) { -		debug("Failed to parse arguments from PersonalizedBootObjectV3 as string\n"); +		logger(LL_DEBUG, "Failed to parse arguments from PersonalizedBootObjectV3 as string\n");  		return -1;  	}  	char *component = image_name; -	unsigned int size = 0; -	unsigned char *data = NULL; +	size_t size = 0; +	void *data = NULL;  	char *path = NULL; -	plist_t blob = NULL; -	plist_t dict = NULL; -	restored_error_t restore_error = RESTORE_E_SUCCESS; -	info("About to send %s...\n", component); +	logger(LL_INFO, "About to send %s...\n", component);  	if (strcmp(image_name, "__GlobalManifest__") == 0) {  		int ret = extract_global_manifest(client, client->restore->build_identity, NULL, &data, &size); @@ -4142,75 +4275,81 @@ int restore_send_personalized_boot_object_v3(struct idevicerestore_client_t* cli  	} else if (strcmp(image_name, "__RestoreVersion__") == 0) {  		int ret = ipsw_extract_to_memory(client->ipsw, "RestoreVersion.plist", &data, &size);  		if (ret != 0) { -			error("ERROR: failed to read global manifest\n"); +			logger(LL_ERROR, "failed to read global manifest\n");  			return -1;  		}  	} else if (strcmp(image_name, "__SystemVersion__") == 0) {  		int ret = ipsw_extract_to_memory(client->ipsw, "SystemVersion.plist", &data, &size);  		if (ret != 0) { -			error("ERROR: failed to read global manifest\n"); +			logger(LL_ERROR, "failed to read global manifest\n");  			return -1;  		}  	} else {  		// Get component path  		if (client->tss) {  			if (tss_response_get_path_by_entry(client->tss, component, &path) < 0) { -				debug("NOTE: No path for component %s in TSS, will fetch from build identity\n", component); +				logger(LL_DEBUG, "No path for component %s in TSS, will fetch from build identity\n", component);  			}  		}  		if (!path) {  			plist_t build_identity = restore_get_build_identity_from_request(client, message);  			if (!build_identity) { -				error("ERROR: Unable to find a matching build identity\n"); +				logger(LL_ERROR, "Unable to find a matching build identity\n");  				return -1;  			}  			if (build_identity_get_component_path(build_identity, component, &path) < 0) { -				error("ERROR: Unable to find %s path from build identity\n", component); +				logger(LL_ERROR, "Unable to find %s path from build identity\n", component);  				return -1;  			}  		}  		// Extract component -		unsigned char *component_data = NULL; -		unsigned int component_size = 0; +		void *component_data = NULL; +		size_t component_size = 0;  		int ret = extract_component(client->ipsw, path, &component_data, &component_size);  		free(path);  		path = NULL;  		if (ret < 0) { -			error("ERROR: Unable to extract component %s\n", component); +			logger(LL_ERROR, "Unable to extract component %s\n", component);  			return -1;  		}  		// Personalize IMG4 -		ret = personalize_component(component, component_data, component_size, client->tss, &data, &size); +		ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size);  		free(component_data);  		component_data = NULL;  		if (ret < 0) { -			error("ERROR: Unable to get personalized component %s\n", component); +			logger(LL_ERROR, "Unable to get personalized component %s\n", component);  			return -1;  		}  	}  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("Sending %s now (%" PRIu64 " bytes)...\n", component, (uint64_t)size); +	logger(LL_INFO, "Sending %s now (%" PRIu64 " bytes)...\n", component, (uint64_t)size);  	struct _restore_send_file_data_ctx rctx;  	rctx.client = client;  	rctx.service = service;  	rctx.last_progress = 0; +	rctx.tag = progress_get_next_tag(); + +	if (size > 0x2000000) { +		register_progress(rctx.tag, component); +	}  	int64_t i = size;  	while (i > 0) {  		int blob_size = i > 8192 ? 8192 : i; -		if (_restore_send_file_data(&rctx, (data + size - i), blob_size, size-i, size) < 0) { +		if (_restore_send_file_data(&rctx, ((char*)data + size - i), blob_size, size-i, size) < 0) {  			free(data);  			_restore_service_free(service); -			error("ERROR: Unable to send component %s data\n", component); +			finalize_progress(rctx.tag); +			logger(LL_ERROR, "Unable to send component %s data\n", component);  			return -1;  		}  		i -= blob_size; @@ -4218,54 +4357,50 @@ int restore_send_personalized_boot_object_v3(struct idevicerestore_client_t* cli  	free(data);  	_restore_send_file_data(&rctx, NULL, 0, size-i, size); +	finalize_progress(rctx.tag);  	_restore_service_free(service); -	info("Done sending %s\n", component); +	logger(LL_INFO, "Done sending %s\n", component);  	return 0;  }  int restore_send_source_boot_object_v4(struct idevicerestore_client_t* client, plist_t message)  { -	if (idevicerestore_debug) { -		debug("DEBUG: %s: Got SourceBootObjectV4 request:\n", __func__); -		debug_plist(message); +	if (client->debug_level > 1) { +		logger(LL_DEBUG, "%s: Got SourceBootObjectV4 request:\n", __func__); +		logger_dump_plist(LL_DEBUG, message, 1);  	}  	char *image_name = NULL;  	plist_t node = plist_access_path(message, 2, "Arguments", "ImageName");  	if (!node || plist_get_node_type(node) != PLIST_STRING) { -		debug("Failed to parse arguments from SourceBootObjectV4 plist\n"); +		logger(LL_DEBUG, "Failed to parse arguments from SourceBootObjectV4 plist\n");  		return -1;  	}  	plist_get_string_val(node, &image_name);  	if (!image_name) { -		debug("Failed to parse arguments from SourceBootObjectV4 as string\n"); +		logger(LL_DEBUG, "Failed to parse arguments from SourceBootObjectV4 as string\n");  		return -1;  	}  	char *component = image_name;  	// Fork from restore_send_component  	// -	unsigned int size = 0; -	unsigned char *data = NULL;  	char *path = NULL; -	plist_t blob = NULL; -	plist_t dict = NULL; -	restored_error_t restore_error = RESTORE_E_SUCCESS; -	info("About to send %s...\n", component); +	logger(LL_INFO, "About to send %s...\n", component);  	if (strcmp(image_name, "__GlobalManifest__") == 0) {  		char *variant = NULL;  		plist_t node = plist_access_path(message, 2, "Arguments", "Variant");  		if (!node || plist_get_node_type(node) != PLIST_STRING) { -			debug("Failed to parse arguments from SourceBootObjectV4 plist\n"); +			logger(LL_DEBUG, "Failed to parse arguments from SourceBootObjectV4 plist\n");  			return -1;  		}  		plist_get_string_val(node, &variant);  		if (!variant) { -			debug("Failed to parse arguments from SourceBootObjectV4 as string\n"); +			logger(LL_DEBUG, "Failed to parse arguments from SourceBootObjectV4 as string\n");  			return -1;  		} @@ -4278,20 +4413,20 @@ int restore_send_source_boot_object_v4(struct idevicerestore_client_t* client, p  		// Get component path  		if (client->tss) {  			if (tss_response_get_path_by_entry(client->tss, component, &path) < 0) { -				debug("NOTE: No path for component %s in TSS, will fetch from build identity\n", component); +				logger(LL_DEBUG, "No path for component %s in TSS, will fetch from build identity\n", component);  			}  		}  		if (!path) {  			plist_t build_identity = restore_get_build_identity_from_request(client, message);  			if (build_identity_get_component_path(build_identity, component, &path) < 0) { -				error("ERROR: Unable to find %s path from build identity\n", component); +				logger(LL_ERROR, "Unable to find %s path from build identity\n", component);  				return -1;  			}  		}  	}  	if (!path) { -		error("ERROR: Failed to get path for component %s\n", component); +		logger(LL_ERROR, "Failed to get path for component %s\n", component);  		return -1;  	} @@ -4300,38 +4435,43 @@ int restore_send_source_boot_object_v4(struct idevicerestore_client_t* client, p  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("Sending %s now (%" PRIu64 " bytes)\n", component, fsize); +	logger(LL_INFO, "Sending %s now (%" PRIu64 " bytes)\n", component, fsize);  	struct _restore_send_file_data_ctx rctx;  	rctx.client = client;  	rctx.service = service;  	rctx.last_progress = 0; +	rctx.tag = progress_get_next_tag(); + +	register_progress(rctx.tag, component);  	if (ipsw_extract_send(client->ipsw, path, 8192, (ipsw_send_cb)_restore_send_file_data, &rctx) < 0) {  		free(path);  		_restore_service_free(service); -		error("ERROR: Failed to send component %s\n", component); +		finalize_progress(rctx.tag); +		logger(LL_ERROR, "Failed to send component %s\n", component);  		return -1;  	}  	free(path);  	_restore_service_free(service); +	finalize_progress(rctx.tag); -	info("Done sending %s\n", component); +	logger(LL_INFO, "Done sending %s\n", component);  	return 0;  }  int restore_send_restore_local_policy(struct idevicerestore_client_t* client, plist_t message)  { -	unsigned int size = 0; -	unsigned char* data = NULL; +	size_t size = 0; +	void* data = NULL; -	unsigned char* component_data = NULL; -	unsigned int component_size = 0; +	void* component_data = NULL; +	size_t component_size = 0;  	char* component = "Ap,LocalPolicy"; @@ -4344,15 +4484,15 @@ int restore_send_restore_local_policy(struct idevicerestore_client_t* client, pl  	int ret = get_recovery_os_local_policy_tss_response(client, build_identity, &client->tss_localpolicy, plist_dict_get_item(message, "Arguments"));  	if (ret < 0) { -		error("ERROR: Unable to get recovery os local policy tss response\n"); +		logger(LL_ERROR, "Unable to get recovery os local policy tss response\n");  		return -1;  	} -	ret = personalize_component(component, component_data, component_size, client->tss_localpolicy, &data, &size); +	ret = personalize_component(client, component, component_data, component_size, client->tss_localpolicy, &data, &size);  	free(component_data);  	component_data = NULL;  	if (ret < 0) { -		error("ERROR: Unable to get personalized component %s\n", component); +		logger(LL_ERROR, "Unable to get personalized component %s\n", component);  		return -1;  	} @@ -4361,7 +4501,7 @@ int restore_send_restore_local_policy(struct idevicerestore_client_t* client, pl  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} @@ -4369,7 +4509,7 @@ int restore_send_restore_local_policy(struct idevicerestore_client_t* client, pl  	restore_error = _restore_service_send(service, dict, 0);  	_restore_service_free(service);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send component %s data\n", component); +		logger(LL_ERROR, "Unable to send component %s data\n", component);  		return -1;  	} @@ -4386,11 +4526,11 @@ int restore_send_buildidentity(struct idevicerestore_client_t* client, plist_t m  	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);  	if (!service) { -		error("ERROR: %s: Unable to connect to service client\n", __func__); +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__);  		return -1;  	} -	info("About to send BuildIdentity Dict...\n"); +	logger(LL_INFO, "About to send BuildIdentity Dict...\n");  	plist_t build_identity = restore_get_build_identity_from_request(client, message); @@ -4404,16 +4544,247 @@ int restore_send_buildidentity(struct idevicerestore_client_t* client, plist_t m  		plist_dict_set_item(dict, "Variant", plist_new_string("Erase"));  	} -	info("Sending BuildIdentityDict now...\n"); +	logger(LL_INFO, "Sending BuildIdentityDict now...\n");  	restore_error = _restore_service_send(service, dict, 0);  	_restore_service_free(service);  	plist_free(dict);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send BuildIdentityDict (%d)\n", restore_error); +		logger(LL_ERROR, "Unable to send BuildIdentityDict (%d)\n", restore_error); +		return -1; +	} + +	logger(LL_INFO, "Done sending BuildIdentityDict\n"); +	return 0; +} + +int restore_send_recovery_os_file_asset_image(struct idevicerestore_client_t* client, plist_t message) +{ +	char *fw_override_key = NULL; +	plist_t node = plist_access_path(message, 2, "Arguments", "FWOverrideKey"); +	if (PLIST_IS_STRING(node)) { +		plist_get_string_val(node, &fw_override_key); +	} +	if (!fw_override_key) { +		logger(LL_ERROR, "Failed to get FWOverrideKey from arguments. Trying to continue anyway.\n"); +		return -1; +	} + +	plist_t dict = plist_new_dict(); +	if (!client->recovery_variant) { +		logger(LL_ERROR, "no RecoveryOS variant in BuildManifest. Trying to continue anyway.\n"); +		plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); +		restored_send(client->restore->client, dict); +		plist_free(dict); +		return 0; +	} + +	if (strncmp(fw_override_key, "RecoveryOS", 10) != 0) { +		logger(LL_ERROR, "FWOVerrideKey has unexpected prefix\n"); +		plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); +		restored_send(client->restore->client, dict); +		plist_free(dict); +		return 0; +	} + +	const char* component = fw_override_key+10; +	char* path = NULL; +	if (build_identity_get_component_path(client->recovery_variant, component, &path) < 0) { +		logger(LL_ERROR, "Unable to find %s path from recovery build identity. Trying to continue anyway.\n", component); +		plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); +		restored_send(client->restore->client, dict); +		plist_free(dict); +		return 0; +	} + +	void* component_data = NULL; +	size_t component_size = 0; +	int ret = extract_component(client->ipsw, path, &component_data, &component_size); +	free(path); +	path = NULL; +	if (ret < 0) { +		logger(LL_ERROR, "Unable to extract component %s. Trying to continue anyway.\n", component); +		plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); +		restored_send(client->restore->client, dict); +		plist_free(dict); +		return 0; +	} + +	void* data = NULL; +	size_t size = 0; +	ret = personalize_component(client, component, component_data, component_size, client->tss_recoveryos_root_ticket, &data, &size); +	free(component_data); +	component_data = NULL; +	if (ret < 0) { +		logger(LL_ERROR, "Unable to get personalized component %s. Trying to continue anyway.\n", component); +		plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); +		restored_send(client->restore->client, dict); +		plist_free(dict); +		return 0; +	} + +	logger(LL_INFO, "Sending %s\n", fw_override_key); + +	plist_dict_set_item(dict, "AdditionalBootImages", plist_new_data((char*)data, size)); +	free(data); +	restored_send(client->restore->client, dict); +	plist_free(dict); + +	return 0; +} + +int restore_send_recovery_os_iboot_fw_files_images(struct idevicerestore_client_t* client, plist_t message) +{ +	plist_t build_id_manifest = plist_dict_get_item(client->recovery_variant, "Manifest"); +	if (!build_id_manifest) { +		logger(LL_ERROR, "Missing Manifest dictionary in build identity?!\n");  		return -1;  	} -	info("Done sending BuildIdentityDict\n"); +	plist_t firmware_files = plist_new_dict(); + +	plist_dict_iter iter = NULL; +	plist_dict_new_iter(build_id_manifest, &iter); +	if (iter) { +		char *component = NULL; +		plist_t manifest_entry; +		do { +			component = NULL; +			manifest_entry = NULL; +			plist_dict_next_item(build_id_manifest, iter, &component, &manifest_entry); +			if (component && PLIST_IS_DICT(manifest_entry)) { +				uint8_t loaded_by_iboot = 0; +				uint8_t loaded_by_iboot_stage1 = 0; +				plist_t fw_node; + +				fw_node = plist_access_path(manifest_entry, 2, "Info", "IsLoadedByiBoot"); +				if (fw_node && plist_get_node_type(fw_node) == PLIST_BOOLEAN) { +					plist_get_bool_val(fw_node, &loaded_by_iboot); +				} +				fw_node = plist_access_path(manifest_entry, 2, "Info", "IsLoadedByiBootStage1"); +				if (fw_node && plist_get_node_type(fw_node) == PLIST_BOOLEAN) { +					plist_get_bool_val(fw_node, &loaded_by_iboot_stage1); +				} +				if (loaded_by_iboot || loaded_by_iboot_stage1) { +					plist_t comp_path = plist_access_path(manifest_entry, 2, "Info", "Path"); +					if (comp_path) { +						const char* path = plist_get_string_ptr(comp_path, NULL); +						void* component_data = NULL; +						size_t component_size = 0; +						int ret = extract_component(client->ipsw, path, &component_data, &component_size); +						if (ret == 0) { +							void* data = NULL; +							size_t size = 0; +							ret = personalize_component(client, component, component_data, component_size, client->tss_recoveryos_root_ticket, &data, &size); +							free(component_data); +							component_data = NULL; +							if (ret == 0) { +								plist_dict_set_item(firmware_files, component, plist_new_data((char*)data, size)); +								free(data); +							} +						} +					} +				} +			} +			free(component); +		} while (manifest_entry); +		plist_mem_free(iter); +	} + +	plist_t dict = plist_new_dict(); + +	if (plist_dict_get_size(firmware_files) == 0) { +		plist_free(firmware_files); +		logger(LL_NOTICE, "No iBoot firmware files. Continuing.\n"); +		plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); +		restored_send(client->restore->client, dict); +		plist_free(dict); +		return 0; + +	} + +	logger(LL_INFO, "Sending iBoot additional firmware files\n"); + +	plist_dict_set_item(dict, "AdditionalBootImages", firmware_files); +	restored_send(client->restore->client, dict); +	plist_free(dict); + +	return 0; +} + +int restore_send_recovery_os_image(struct idevicerestore_client_t* client, plist_t message) +{ +	const char* component = "OS"; +	char* path = NULL; +	if (build_identity_get_component_path(client->recovery_variant, component, &path) < 0) { +		logger(LL_ERROR, "Unable to find %s path from build identity\n", component); +		return -1; +	} +	if (!path) { +		logger(LL_ERROR, "Failed to get path for component %s\n", component); +		return -1; +	} + +	uint64_t fsize = 0; +	ipsw_get_file_size(client->ipsw, path, &fsize); + +	restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); +	if (!service) { +		logger(LL_ERROR, "%s: Unable to connect to service client\n", __func__); +		return -1; +	} + +	logger(LL_INFO, "Sending %s now (%" PRIu64 " bytes)\n", component, fsize); + +	struct _restore_send_file_data_ctx rctx; +	rctx.client = client; +	rctx.service = service; +	rctx.last_progress = 0; +	rctx.tag = progress_get_next_tag(); + +	register_progress(rctx.tag, component); + +	if (ipsw_extract_send(client->ipsw, path, 8192, (ipsw_send_cb)_restore_send_file_data, &rctx) < 0) { +		free(path); +		_restore_service_free(service); +		finalize_progress(rctx.tag); +		logger(LL_ERROR, "Failed to send component %s\n", component); +		return -1; +	} +	free(path); + +	_restore_service_free(service); +	finalize_progress(rctx.tag); + +	logger(LL_INFO, "Done sending %s\n", component); + +	return 0; +} + +int restore_send_recovery_os_version_data(struct idevicerestore_client_t* client, plist_t message) +{ +	plist_t build_id_info = plist_dict_get_item(client->recovery_variant, "Info"); +	if (!build_id_info) { +		logger(LL_ERROR, "Missing Info dictionary in build identity?!\n"); +		return -1; +	} +	plist_t version_data = plist_new_dict(); +	plist_dict_copy_item(version_data, build_id_info, "BuildNumber", NULL); +	plist_dict_copy_item(version_data, build_id_info, "Variant", NULL); +	plist_dict_copy_item(version_data, build_id_info, "BuildTrain", NULL); +	plist_dict_copy_item(version_data, build_id_info, "ProductVersion", "ProductMarketingVersion"); +	char *xml = NULL; +	uint32_t xml_len = 0; +	plist_to_xml(version_data, &xml, &xml_len); +	plist_free(version_data); + +	logger(LL_INFO, "Sending RecoveryOS version data\n"); + +	plist_t dict = plist_new_dict(); +	plist_dict_set_item(dict, "RecoveryOSVersionData", plist_new_data(xml, xml_len)); +	plist_mem_free(xml); +	restored_send(client->restore->client, dict); +	plist_free(dict); +  	return 0;  } @@ -4426,39 +4797,39 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, plis  	node = plist_dict_get_item(message, "DataType");  	if (node && PLIST_STRING == plist_get_node_type(node)) {  		const char *type = plist_get_string_ptr(node, NULL); -debug("%s: type = %s\n", __func__, type); +logger(LL_DEBUG, "%s: type = %s\n", __func__, type);  		// this request is sent when restored is ready to receive the filesystem  		if (!strcmp(type, "SystemImageData")) {  			if (restore_send_filesystem(client, message) < 0) { -				error("ERROR: Unable to send filesystem\n"); +				logger(LL_ERROR, "Unable to send filesystem\n");  				return -2;  			}  		}  		else if (!strcmp(type, "BuildIdentityDict")) {  			if (restore_send_buildidentity(client, message) < 0) { -				error("ERROR: Unable to send RootTicket\n"); +				logger(LL_ERROR, "Unable to send RootTicket\n");  				return -1;  			}  		}  		else if (!strcmp(type, "PersonalizedBootObjectV3")) {  			if (restore_send_personalized_boot_object_v3(client, message) < 0) { -				error("ERROR: Unable to send PersonalizedBootObjectV3\n"); +				logger(LL_ERROR, "Unable to send PersonalizedBootObjectV3\n");  				return -1;  			}  		}  		else if (!strcmp(type, "SourceBootObjectV4")) {  			if (restore_send_source_boot_object_v4(client, message) < 0) { -				error("ERROR: Unable to send SourceBootObjectV4\n"); +				logger(LL_ERROR, "Unable to send SourceBootObjectV4\n");  				return -1;  			}  		}  		else if (!strcmp(type, "RecoveryOSLocalPolicy")) {  			if (restore_send_restore_local_policy(client, message) < 0) { -				error("ERROR: Unable to send RecoveryOSLocalPolicy\n"); +				logger(LL_ERROR, "Unable to send RecoveryOSLocalPolicy\n");  				return -1;  			}  		} @@ -4466,7 +4837,7 @@ debug("%s: type = %s\n", __func__, type);  		// this request is sent when restored is ready to receive the filesystem  		else if (!strcmp(type, "RecoveryOSASRImage")) {  			if (restore_send_filesystem(client, message) < 0) { -				error("ERROR: Unable to send filesystem\n"); +				logger(LL_ERROR, "Unable to send filesystem\n");  				return -2;  			}  		} @@ -4474,7 +4845,7 @@ debug("%s: type = %s\n", __func__, type);  		// Send RecoveryOS RTD  		else if(!strcmp(type, "RecoveryOSRootTicketData")) {  			if (restore_send_recovery_os_root_ticket(client, message) < 0) { -				error("ERROR: Unable to send RootTicket\n"); +				logger(LL_ERROR, "Unable to send RootTicket\n");  				return -1;  			}  		} @@ -4482,35 +4853,35 @@ debug("%s: type = %s\n", __func__, type);  		// send RootTicket (== APTicket from the TSS request)  		else if (!strcmp(type, "RootTicket")) {  			if (restore_send_root_ticket(client, message) < 0) { -				error("ERROR: Unable to send RootTicket\n"); +				logger(LL_ERROR, "Unable to send RootTicket\n");  				return -1;  			}  		}  		// send KernelCache  		else if (!strcmp(type, "KernelCache")) {  			if (restore_send_component(client, message, "KernelCache", NULL) < 0) { -				error("ERROR: Unable to send kernelcache\n"); +				logger(LL_ERROR, "Unable to send kernelcache\n");  				return -1;  			}  		}  		else if (!strcmp(type, "DeviceTree")) {  			if (restore_send_component(client, message, "DeviceTree", NULL) < 0) { -				error("ERROR: Unable to send DeviceTree\n"); +				logger(LL_ERROR, "Unable to send DeviceTree\n");  				return -1;  			}  		}  		else if (!strcmp(type, "SystemImageRootHash")) {  			if (restore_send_component(client, message, "SystemVolume", type) < 0) { -				error("ERROR: Unable to send SystemImageRootHash data\n"); +				logger(LL_ERROR, "Unable to send SystemImageRootHash data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "SystemImageCanonicalMetadata")) {  			if (restore_send_component(client, message, "Ap,SystemVolumeCanonicalMetadata", type) < 0) { -				error("ERROR: Unable to send SystemImageCanonicalMetadata data\n"); +				logger(LL_ERROR, "Unable to send SystemImageCanonicalMetadata data\n");  				return -1;  			}  		} @@ -4518,104 +4889,131 @@ debug("%s: type = %s\n", __func__, type);  		else if (!strcmp(type, "NORData")) {  			if((client->flags & FLAG_EXCLUDE) == 0) {  				if(restore_send_nor(client, message) < 0) { -					error("ERROR: Unable to send NOR data\n"); +					logger(LL_ERROR, "Unable to send NOR data\n");  					return -1;  				}  			} else { -				info("Not sending NORData... Quitting...\n"); +				logger(LL_INFO, "Not sending NORData... Quitting...\n");  				client->flags |= FLAG_QUIT;  			}  		}  		else if (!strcmp(type, "BasebandData")) {  			if(restore_send_baseband_data(client, message) < 0) { -				error("ERROR: Unable to send baseband data\n"); +				logger(LL_ERROR, "Unable to send baseband data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "FDRTrustData")) {  			if(restore_send_fdr_trust_data(client, message) < 0) { -				error("ERROR: Unable to send FDR Trust data\n"); +				logger(LL_ERROR, "Unable to send FDR Trust data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "FUDData")) {  			if(restore_send_image_data(client, message, "FUDImageList", "IsFUDFirmware", "FUDImageData") < 0) { -				error("ERROR: Unable to send FUD data\n"); +				logger(LL_ERROR, "Unable to send FUD data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "FirmwareUpdaterPreflight")) {  			if(restore_send_firmware_updater_preflight(client, message) < 0) { -				error("ERROR: Unable to send FirmwareUpdaterPreflight\n"); +				logger(LL_ERROR, "Unable to send FirmwareUpdaterPreflight\n");  				return -1;  			}  		}  		else if (!strcmp(type, "FirmwareUpdaterData")) {  			if(restore_send_firmware_updater_data(client, message) < 0) { -				error("ERROR: Unable to send FirmwareUpdater data\n"); +				logger(LL_ERROR, "Unable to send FirmwareUpdater data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "PersonalizedData")) {  			if(restore_send_image_data(client, message, "ImageList", NULL, "ImageData") < 0) { -				error("ERROR: Unable to send Personalized data\n"); +				logger(LL_ERROR, "Unable to send Personalized data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "EANData")) {  			if(restore_send_image_data(client, message, "EANImageList", "IsEarlyAccessFirmware", "EANData") < 0) { -				error("ERROR: Unable to send Personalized data\n"); +				logger(LL_ERROR, "Unable to send Personalized data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "BootabilityBundle")) {  			if (restore_send_bootability_bundle_data(client, message) < 0) { -				error("ERROR: Unable to send BootabilityBundle data\n"); +				logger(LL_ERROR, "Unable to send BootabilityBundle data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "ReceiptManifest")) {  			if (restore_send_receipt_manifest(client, message) < 0) { -				error("ERROR: Unable to send ReceiptManifest data\n"); +				logger(LL_ERROR, "Unable to send ReceiptManifest data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "BasebandUpdaterOutputData")) {  			if (restore_handle_baseband_updater_output_data(client, message) < 0) { -				error("ERROR: Unable to send BasebandUpdaterOutputData data\n"); +				logger(LL_ERROR, "Unable to send BasebandUpdaterOutputData data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "URLAsset")) {  			if (restore_send_url_asset(client, message) < 0) { -				error("ERROR: Unable to send URLAsset data\n"); +				logger(LL_ERROR, "Unable to send URLAsset data\n");  				return -1;  			}  		}  		else if (!strcmp(type, "StreamedImageDecryptionKey")) {  			if (restore_send_streamed_image_decryption_key(client, message) < 0) { -				error("ERROR: Unable to send StreamedImageDecryptionKey data\n"); +				logger(LL_ERROR, "Unable to send StreamedImageDecryptionKey data\n"); +				return -1; +			} +		} + +		else if (!strcmp(type, "RecoveryOSFileAssetImage")) { +			if (restore_send_recovery_os_file_asset_image(client, message) < 0) { +				logger(LL_ERROR, "Unable to send RecoveryOSFileImageAssetImage data\n"); +				return -1; +			} +		} + +		else if (!strcmp(type, "RecoveryOSIBootFWFilesImages")) { +			if (restore_send_recovery_os_iboot_fw_files_images(client, message) < 0) { +				logger(LL_ERROR, "Unable to send RecoveryOSIBootFWFilesImages data\n"); +				return -1; +			} +		} + +		else if (!strcmp(type, "RecoveryOSImage")) { +			if (restore_send_recovery_os_image(client, message) < 0) { +				logger(LL_ERROR, "Unable to send RecoveryOSImage data\n"); +				return -1; +			} +		} + +		else if (!strcmp(type, "RecoveryOSVersionData")) { +			if (restore_send_recovery_os_version_data(client, message) < 0) { +				logger(LL_ERROR, "Unable to send RecoveryOSVersionData data\n");  				return -1;  			}  		}  		else {  			// Unknown DataType!! -			error("Unknown data request '%s' received\n", type); -			if (idevicerestore_debug) -				debug_plist(message); +			logger(LL_ERROR, "Unknown data request '%s' received\n", type); +			logger_dump_plist(LL_VERBOSE, message, 1);  		}  	}  	return 0; @@ -4646,49 +5044,107 @@ static void* _restore_handle_async_data_request(void* args)  static int restore_handle_restored_crash(struct idevicerestore_client_t* client, plist_t message)  {  	plist_t backtrace = plist_dict_get_item(message, "RestoredBacktrace"); -	info("*** restored crashed, backtrace following ***"); +	logger(LL_INFO, "*** restored crashed, backtrace following ***\n");  	if (PLIST_IS_STRING(backtrace)) { -		info("%s\n", plist_get_string_ptr(backtrace, NULL)); +		logger(LL_INFO, "%s\n", plist_get_string_ptr(backtrace, NULL));  	} else if (PLIST_IS_ARRAY(backtrace)) {  		uint32_t i = 0;  		for (i = 0; i < plist_array_get_size(backtrace); i++) {  			plist_t line = plist_array_get_item(backtrace, i); -			info("\t%s\n", plist_get_string_ptr(line, NULL)); +			logger(LL_INFO, "\t%s\n", plist_get_string_ptr(line, NULL));  		}  	} else { -		debug_plist(message); +		logger_dump_plist(LL_VERBOSE, message, 1);  	}  	return 0;  }  static int restore_handle_async_wait(struct idevicerestore_client_t* client, plist_t message)  { -	debug("AsyncWait\n"); -	if (idevicerestore_debug) -		debug_plist(message); +	logger(LL_DEBUG, "AsyncWait\n"); +	logger_dump_plist(LL_DEBUG, message, 1);  	return 0;  }  static int restore_handle_restore_attestation(struct idevicerestore_client_t* client, plist_t message)  { -	if (idevicerestore_debug) -		debug_plist(message); -	debug("Sending RestoreShouldAttest: false\n"); +	logger_dump_plist(LL_DEBUG, message, 1); +	logger(LL_DEBUG, "Sending RestoreShouldAttest: false\n");  	plist_t dict = plist_new_dict();  	plist_dict_set_item(dict, "RestoreShouldAttest", plist_new_bool(0));  	restored_error_t restore_error = restored_send(client->restore->client, dict);  	plist_free(dict);	  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to send RestoreShouldAttest (%d)\n", restore_error); +		logger(LL_ERROR, "Unable to send RestoreShouldAttest (%d)\n", restore_error);  		return -1;  	}  	return 0;  } +static void _restore_calculate_recovery_os_partition_size(struct idevicerestore_client_t* client, uint64_t* min_size, uint64_t* max_size) +{ +	const char* asset_list[] = { "OS", "KernelCache", "DeviceTree", "iBEC", "AppleLogo", "StaticTrustCache", "iBootData", "Diags", "Ap,SystemVolumeCanonicalMetadata", "SystemVolume", "BaseSystemVolume", "Ap,BaseSystemTrustCache", "AVISP1,RTKitOS", NULL }; + +	if (min_size) *min_size = 356; +	if (max_size) *max_size = 420; + +	double total_size = 0; +	plist_t firmware_items = plist_new_dict(); +	plist_t build_id_manifest = plist_dict_get_item(client->recovery_variant, "Manifest"); +	plist_dict_iter iter = NULL; +	plist_dict_new_iter(build_id_manifest, &iter); +	if (iter) { +		char *component = NULL; +		plist_t manifest_entry; +		do { +			component = NULL; +			manifest_entry = NULL; +			plist_dict_next_item(build_id_manifest, iter, &component, &manifest_entry); +			if (component && PLIST_IS_DICT(manifest_entry) && plist_dict_get_item(firmware_items, component) == NULL) { +				int add_image = 0; +				int i = 0; +				while (asset_list[i]) { +					if (!strcmp(asset_list[i], component)) { +						add_image = 1; +						break; +					} +					i++; +				} +				plist_t fw_node; +				fw_node = plist_access_path(manifest_entry, 2, "Info", "IsLoadedByiBoot"); +				if (fw_node && plist_get_node_type(fw_node) == PLIST_BOOLEAN) { +					uint8_t loaded_by_iboot = 0; +					plist_get_bool_val(fw_node, &loaded_by_iboot); +					if (loaded_by_iboot) { +						add_image = 1; +					} +				} +				if (add_image) { +					plist_t p_path = plist_access_path(manifest_entry, 2, "Info", "Path"); +					if (p_path) { +						const char* path = plist_get_string_ptr(p_path, NULL); +						uint64_t fsize = 0; +						if (ipsw_get_file_size(client->ipsw, path, &fsize) == 0) { +							logger(LL_DEBUG, "%s: Adding %s (%s, %" PRIu64 " bytes)\n", __func__, component, path, fsize); +							total_size += (double)fsize / 0x100000; +						} +					} +				} +			} +			free(component); +		} while (manifest_entry); +		plist_mem_free(iter); +	} +	total_size = ceil(total_size); +	if (min_size) *min_size = total_size * 1.05 + 25; +	if (max_size) *max_size = total_size * 1.25 + 25; +} +  // Extracted from ac2  plist_t restore_supported_data_types()  {  	plist_t dict = plist_new_dict(); +	plist_dict_set_item(dict, "AuthInstallCACert", plist_new_bool(1));  	plist_dict_set_item(dict, "BasebandBootData", plist_new_bool(0));  	plist_dict_set_item(dict, "BasebandData", plist_new_bool(0));  	plist_dict_set_item(dict, "BasebandStackData", plist_new_bool(0)); @@ -4706,20 +5162,26 @@ plist_t restore_supported_data_types()  	plist_dict_set_item(dict, "FileData", plist_new_bool(0));  	plist_dict_set_item(dict, "FileDataDone", plist_new_bool(0));  	plist_dict_set_item(dict, "FirmwareUpdaterData", plist_new_bool(0)); +	plist_dict_set_item(dict, "FirmwareUpdaterDataV2", plist_new_bool(0)); +	plist_dict_set_item(dict, "FirmwareUpdaterDataV3", plist_new_bool(1)); +	plist_dict_set_item(dict, "FirmwareUpdaterPreflight", plist_new_bool(1));  	plist_dict_set_item(dict, "GrapeFWData", plist_new_bool(0));  	plist_dict_set_item(dict, "HPMFWData", plist_new_bool(0));  	plist_dict_set_item(dict, "HostSystemTime", plist_new_bool(1));  	plist_dict_set_item(dict, "KernelCache", plist_new_bool(0)); +	plist_dict_set_item(dict, "MessageUseStreamedImageFile", plist_new_bool(1));  	plist_dict_set_item(dict, "NORData", plist_new_bool(0));  	plist_dict_set_item(dict, "NitrogenFWData", plist_new_bool(1));  	plist_dict_set_item(dict, "OpalFWData", plist_new_bool(0));  	plist_dict_set_item(dict, "OverlayRootDataCount", plist_new_bool(0));  	plist_dict_set_item(dict, "OverlayRootDataForKey", plist_new_bool(1)); +	plist_dict_set_item(dict, "OverlayRootDataForKeyIndex", plist_new_bool(1));  	plist_dict_set_item(dict, "PeppyFWData", plist_new_bool(1));  	plist_dict_set_item(dict, "PersonalizedBootObjectV3", plist_new_bool(0));  	plist_dict_set_item(dict, "PersonalizedData", plist_new_bool(1));  	plist_dict_set_item(dict, "ProvisioningData", plist_new_bool(0));  	plist_dict_set_item(dict, "RamdiskFWData", plist_new_bool(1)); +	plist_dict_set_item(dict, "ReceiptManifest", plist_new_bool(1));  	plist_dict_set_item(dict, "RecoveryOSASRImage", plist_new_bool(1));  	plist_dict_set_item(dict, "RecoveryOSAppleLogo", plist_new_bool(1));  	plist_dict_set_item(dict, "RecoveryOSDeviceTree", plist_new_bool(1)); @@ -4733,6 +5195,7 @@ plist_t restore_supported_data_types()  	plist_dict_set_item(dict, "RecoveryOSRootTicketData", plist_new_bool(1));  	plist_dict_set_item(dict, "RecoveryOSStaticTrustCache", plist_new_bool(1));  	plist_dict_set_item(dict, "RecoveryOSVersionData", plist_new_bool(1)); +	plist_dict_set_item(dict, "RestoreLocalPolicy", plist_new_bool(1));  	plist_dict_set_item(dict, "RootData", plist_new_bool(0));  	plist_dict_set_item(dict, "RootTicket", plist_new_bool(0));  	plist_dict_set_item(dict, "S3EOverride", plist_new_bool(0)); @@ -4743,18 +5206,10 @@ plist_t restore_supported_data_types()  	plist_dict_set_item(dict, "SystemImageCanonicalMetadata", plist_new_bool(0));  	plist_dict_set_item(dict, "SystemImageData", plist_new_bool(0));  	plist_dict_set_item(dict, "SystemImageRootHash", plist_new_bool(0)); +	plist_dict_set_item(dict, "URLAsset", plist_new_bool(1));  	plist_dict_set_item(dict, "USBCFWData", plist_new_bool(0));  	plist_dict_set_item(dict, "USBCOverride", plist_new_bool(0)); -	plist_dict_set_item(dict, "FirmwareUpdaterPreflight", plist_new_bool(1)); -	plist_dict_set_item(dict, "ReceiptManifest", plist_new_bool(1)); -	plist_dict_set_item(dict, "FirmwareUpdaterDataV2", plist_new_bool(0)); -	plist_dict_set_item(dict, "RestoreLocalPolicy", plist_new_bool(1)); -	plist_dict_set_item(dict, "AuthInstallCACert", plist_new_bool(1)); -	plist_dict_set_item(dict, "OverlayRootDataForKeyIndex", plist_new_bool(1)); -	plist_dict_set_item(dict, "FirmwareUpdaterDataV3", plist_new_bool(1)); -	plist_dict_set_item(dict, "MessageUseStreamedImageFile", plist_new_bool(1));  	plist_dict_set_item(dict, "UpdateVolumeOverlayRootDataCount", plist_new_bool(1)); -	plist_dict_set_item(dict, "URLAsset", plist_new_bool(1));  	return dict;  } @@ -4762,8 +5217,11 @@ plist_t restore_supported_data_types()  plist_t restore_supported_message_types()  {  	plist_t dict = plist_new_dict(); +	plist_dict_set_item(dict, "AsyncDataRequestMsg", plist_new_bool(1)); +	plist_dict_set_item(dict, "AsyncWait", plist_new_bool(1));  	plist_dict_set_item(dict, "BBUpdateStatusMsg", plist_new_bool(0));  	plist_dict_set_item(dict, "CheckpointMsg", plist_new_bool(1)); +	plist_dict_set_item(dict, "CrashLog", plist_new_bool(1));  	plist_dict_set_item(dict, "DataRequestMsg", plist_new_bool(0));  	plist_dict_set_item(dict, "FDRSubmit", plist_new_bool(1));  	plist_dict_set_item(dict, "MsgType", plist_new_bool(0)); @@ -4773,23 +5231,21 @@ plist_t restore_supported_message_types()  	plist_dict_set_item(dict, "ProvisioningInfo", plist_new_bool(0));  	plist_dict_set_item(dict, "ProvisioningStatusMsg", plist_new_bool(0));  	plist_dict_set_item(dict, "ReceivedFinalStatusMsg", plist_new_bool(0)); +	plist_dict_set_item(dict, "RestoreAttestation", plist_new_bool(1));  	plist_dict_set_item(dict, "RestoredCrash", plist_new_bool(1));  	plist_dict_set_item(dict, "StatusMsg", plist_new_bool(0)); -	plist_dict_set_item(dict, "AsyncDataRequestMsg", plist_new_bool(1)); -	plist_dict_set_item(dict, "AsyncWait", plist_new_bool(1)); -	plist_dict_set_item(dict, "RestoreAttestation", plist_new_bool(1));  	return dict;  }  #ifdef HAVE_REVERSE_PROXY  static void rp_log_cb(reverse_proxy_client_t client, const char* log_msg, void* user_data)  { -	info("ReverseProxy[%s]: %s\n", (reverse_proxy_get_type(client) == RP_TYPE_CTRL) ? "Ctrl" : "Conn", log_msg); +	logger(LL_VERBOSE, "ReverseProxy[%s]: %s\n", (reverse_proxy_get_type(client) == RP_TYPE_CTRL) ? "Ctrl" : "Conn", log_msg);  }  static void rp_status_cb(reverse_proxy_client_t client, reverse_proxy_status_t status, const char* status_msg, void* user_data)  { -	info("ReverseProxy[%s]: (status=%d) %s\n", (reverse_proxy_get_type(client) == RP_TYPE_CTRL) ? "Ctrl" : "Conn", status, status_msg); +	logger(LL_VERBOSE, "ReverseProxy[%s]: (status=%d) %s\n", (reverse_proxy_get_type(client) == RP_TYPE_CTRL) ? "Ctrl" : "Conn", status, status_msg);  }  #endif @@ -4812,10 +5268,10 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  	// open our connection to the device and verify we're in restore mode  	err = restore_open_with_timeout(client);  	if (err < 0) { -		error("ERROR: Unable to open device in restore mode\n"); +		logger(LL_ERROR, "Unable to open device in restore mode\n");  		return (err == -2) ? -1: -2;  	} -	info("Device %s has successfully entered restore mode\n", client->udid); +	logger(LL_INFO, "Device %s has successfully entered restore mode\n", client->udid);  	client->restore->build_identity = build_identity;  	restore = client->restore->client; @@ -4825,30 +5281,30 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  	if (restore_error == RESTORE_E_SUCCESS) {  		uint64_t i = 0;  		uint8_t b = 0; -		info("Hardware Information:\n"); +		logger(LL_INFO, "Hardware Information:\n");  		node = plist_dict_get_item(hwinfo, "BoardID");  		if (node && plist_get_node_type(node) == PLIST_UINT) {  			plist_get_uint_val(node, &i); -			info("BoardID: %d\n", (int)i); +			logger(LL_INFO, "BoardID: %d\n", (int)i);  		}  		node = plist_dict_get_item(hwinfo, "ChipID");  		if (node && plist_get_node_type(node) == PLIST_UINT) {  			plist_get_uint_val(node, &i); -			info("ChipID: %d\n", (int)i); +			logger(LL_INFO, "ChipID: %d\n", (int)i);  		}  		node = plist_dict_get_item(hwinfo, "UniqueChipID");  		if (node && plist_get_node_type(node) == PLIST_UINT) {  			plist_get_uint_val(node, &i); -			info("UniqueChipID: %" PRIu64 "\n", i); +			logger(LL_INFO, "UniqueChipID: %" PRIu64 "\n", i);  		}  		node = plist_dict_get_item(hwinfo, "ProductionMode");  		if (node && plist_get_node_type(node) == PLIST_BOOLEAN) {  			plist_get_bool_val(node, &b); -			info("ProductionMode: %s\n", (b==1) ? "true":"false"); +			logger(LL_INFO, "ProductionMode: %s\n", (b==1) ? "true":"false");  		}  		plist_free(hwinfo);  	} @@ -4860,7 +5316,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		node = plist_dict_get_item(hwinfo, "PreviousExitStatus");  		if (node && plist_get_node_type(node) == PLIST_STRING) {  			plist_get_string_val(node, &sval); -			info("Previous restore exit status: %s\n", sval); +			logger(LL_INFO, "Previous restore exit status: %s\n", sval);  			free(sval);  			sval = NULL;  		} @@ -4868,7 +5324,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		node = plist_dict_get_item(hwinfo, "USBLog");  		if (node && plist_get_node_type(node) == PLIST_STRING) {  			plist_get_string_val(node, &sval); -			info("USB log is available:\n%s\n", sval); +			logger(LL_INFO, "USB log is available:\n%s\n", sval);  			free(sval);  			sval = NULL;  		} @@ -4876,7 +5332,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		node = plist_dict_get_item(hwinfo, "PanicLog");  		if (node && plist_get_node_type(node) == PLIST_STRING) {  			plist_get_string_val(node, &sval); -			info("Panic log is available:\n%s\n", sval); +			logger(LL_INFO, "Panic log is available:\n%s\n", sval);  			free(sval);  			sval = NULL;  		} @@ -4888,42 +5344,42 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  	}  #ifdef HAVE_REVERSE_PROXY -	info("Starting Reverse Proxy\n"); +	logger(LL_INFO, "Starting Reverse Proxy\n");  	reverse_proxy_client_t rproxy = NULL;  	if (reverse_proxy_client_create_with_port(device, &rproxy, REVERSE_PROXY_DEFAULT_PORT) != REVERSE_PROXY_E_SUCCESS) { -		error("Could not create Reverse Proxy\n"); +		logger(LL_ERROR, "Could not create Reverse Proxy\n");  	} else {  		if (client->flags & FLAG_DEBUG) {  			reverse_proxy_client_set_log_callback(rproxy, rp_log_cb, NULL);  		}  		reverse_proxy_client_set_status_callback(rproxy, rp_status_cb, NULL);  		if (reverse_proxy_client_start_proxy(rproxy, 2) != REVERSE_PROXY_E_SUCCESS) { -			error("Device didn't accept new reverse proxy protocol, trying to use old one\n"); +			logger(LL_ERROR, "Device didn't accept new reverse proxy protocol, trying to use old one\n");  			reverse_proxy_client_free(rproxy);  			rproxy = NULL;  			if (reverse_proxy_client_create_with_port(device, &rproxy, REVERSE_PROXY_DEFAULT_PORT) != REVERSE_PROXY_E_SUCCESS) { -				error("Could not create Reverse Proxy\n"); +				logger(LL_ERROR, "Could not create Reverse Proxy\n");  			} else {  				if (client->flags & FLAG_DEBUG) {  					reverse_proxy_client_set_log_callback(rproxy, rp_log_cb, NULL);  				}  				reverse_proxy_client_set_status_callback(rproxy, rp_status_cb, NULL);  				if (reverse_proxy_client_start_proxy(rproxy, 1) != REVERSE_PROXY_E_SUCCESS) { -					error("ReverseProxy: Device didn't accept old protocol, giving up\n"); +					logger(LL_ERROR, "ReverseProxy: Device didn't accept old protocol, giving up\n");  				}  			}  		}  	}  #else  	fdr_client_t fdr_control_channel = NULL; -	info("Starting FDR listener thread\n"); +	logger(LL_INFO, "Starting FDR listener thread\n");  	if (!fdr_connect(device, FDR_CTRL, &fdr_control_channel)) {  		if(thread_new(&fdr_thread, fdr_listener_thread, fdr_control_channel)) { -			error("ERROR: Failed to start FDR listener thread\n"); +			logger(LL_ERROR, "Failed to start FDR listener thread\n");  			fdr_thread = THREAD_T_NULL; /* undefined after failure */  		}  	} else { -		error("ERROR: Failed to start FDR Ctrl channel\n"); +		logger(LL_ERROR, "Failed to start FDR Ctrl channel\n");  		// FIXME: We might want to return failure here as it will likely fail  	}  #endif @@ -4933,15 +5389,15 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  	//plist_dict_set_item(opts, "AuthInstallRestoreBehavior", plist_new_string("Erase"));  	plist_dict_set_item(opts, "AutoBootDelay", plist_new_uint(0)); -	if (client->preflight_info) { -		plist_t bbus = plist_copy(client->preflight_info); +	if (client->firmware_preflight_info) { +		plist_t bbus = plist_copy(client->firmware_preflight_info);  		plist_dict_remove_item(bbus, "FusingStatus");  		plist_dict_remove_item(bbus, "PkHash");  		plist_dict_set_item(opts, "BBUpdaterState", bbus); -		plist_dict_copy_data(opts, client->preflight_info, "BasebandNonce", "Nonce"); +		plist_dict_copy_data(opts, client->firmware_preflight_info, "BasebandNonce", "Nonce");  	}  	plist_dict_set_item(opts, "SupportedDataTypes", restore_supported_data_types()); @@ -4987,7 +5443,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		}  	} else {  		// FIXME: new on iOS 5 ? -		plist_dict_set_item(opts, "BootImageType", plist_new_string("UserOrInternal")); +		plist_dict_set_item(opts, "BootImageType", plist_new_string("User"));  		// FIXME: required?  		//plist_dict_set_item(opts, "BootImageFile", plist_new_string("018-7923-347.dmg"));  		plist_dict_set_item(opts, "DFUFileType", plist_new_string("RELEASE")); @@ -5013,19 +5469,32 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		// FIXME: new on iOS 5 ?  		plist_dict_set_item(opts, "SystemImageType", plist_new_string("User"));  		// FIXME: does this have any effect actually? -		plist_dict_set_item(opts, "UpdateBaseband", plist_new_bool(0)); +		plist_dict_set_item(opts, "UpdateBaseband", plist_new_bool(1)); +		plist_dict_set_item(opts, "InstallDiags", plist_new_bool(0)); +		if (client->recovery_variant) { +			plist_dict_set_item(opts, "InstallRecoveryOS", plist_new_bool(1)); +			plist_dict_set_item(opts, "RecoveryOSBundlePath", plist_new_string("/tmp/Per2.tmp")); +			plist_t recovery_variant = plist_access_path(client->recovery_variant, 2, "Info", "Variant"); +			plist_dict_set_item(opts, "AuthInstallRecoveryOSVariant", plist_copy(recovery_variant)); +			uint64_t max_size = 0; +			uint64_t min_size = 0; +			_restore_calculate_recovery_os_partition_size(client, &min_size, &max_size); +			logger(LL_INFO, "Calculated recoveryOSPartitionSize as %" PRIu64 " MB\n", min_size); +			logger(LL_INFO, "Calculated recoveryOSMaxPartitionSize as %" PRIu64 " MB\n", max_size); +			plist_dict_set_item(opts, "recoveryOSMaxPartitionSize", plist_new_uint(max_size)); +			plist_dict_set_item(opts, "recoveryOSPartitionSize", plist_new_uint(min_size)); +		} + +		if (plist_dict_get_bool(client->parameters, "RequiresNonceSlot")) { +			logger(LL_INFO, "Device will use nonce slots.\n"); +		} else { +			logger(LL_INFO, "Device will not use nonce slots.\n"); +		}  		// Added for iOS 18.0 beta 1  		plist_dict_set_item(opts, "HostHasFixFor99053849", plist_new_bool(1));  		plist_dict_set_item(opts, "SystemImageFormat", plist_new_string("AEAWrappedDiskImage"));  		plist_dict_set_item(opts, "WaitForDeviceConnectionToFinishStateMachine", plist_new_bool(0)); -		plist_t async_data_types = plist_new_dict(); -		plist_dict_set_item(async_data_types, "BasebandData", plist_new_bool(0)); -		plist_dict_set_item(async_data_types, "RecoveryOSASRImage", plist_new_bool(0)); -		plist_dict_set_item(async_data_types, "StreamedImageDecryptionKey", plist_new_bool(0)); -		plist_dict_set_item(async_data_types, "SystemImageData", plist_new_bool(0)); -		plist_dict_set_item(async_data_types, "URLAsset", plist_new_bool(1)); -		plist_dict_set_item(opts, "SupportedAsyncDataTypes", async_data_types);  		plist_t sep = plist_access_path(build_identity, 3, "Manifest", "SEP", "Info");  		if (sep) { @@ -5033,7 +5502,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  			if (node && plist_get_node_type(node) == PLIST_STRING) {  				char* sval = NULL;  				plist_get_string_val(node, &sval); -				debug("TZ0RequiredCapacity: %s\n", sval); +				logger(LL_DEBUG, "TZ0RequiredCapacity: %s\n", sval);  				plist_dict_set_item(opts, "TZ0RequiredCapacity", plist_copy(node));  				free(sval);  				sval = NULL; @@ -5045,6 +5514,15 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		plist_dict_set_item(opts, "PersonalizedDuringPreflight", plist_new_bool(1));  	} +	// Added for iOS 18.0 and macOS 15.0 +	plist_t async_data_types = plist_new_dict(); +	plist_dict_set_item(async_data_types, "BasebandData", plist_new_bool(0)); +	plist_dict_set_item(async_data_types, "RecoveryOSASRImage", plist_new_bool(0)); +	plist_dict_set_item(async_data_types, "StreamedImageDecryptionKey", plist_new_bool(0)); +	plist_dict_set_item(async_data_types, "SystemImageData", plist_new_bool(0)); +	plist_dict_set_item(async_data_types, "URLAsset", plist_new_bool(1)); +	plist_dict_set_item(opts, "SupportedAsyncDataTypes", async_data_types); +  	plist_dict_set_item(opts, "RootToInstall", plist_new_bool(0));  	char* guid = generate_guid();  	if (guid) { @@ -5061,10 +5539,14 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		spp = plist_copy(spp);  	} else {  		spp = plist_new_dict(); +		plist_dict_set_item(spp, "1024", plist_new_uint(1280));  		plist_dict_set_item(spp, "128", plist_new_uint(1280));  		plist_dict_set_item(spp, "16", plist_new_uint(160)); +		plist_dict_set_item(spp, "256", plist_new_uint(1280));  		plist_dict_set_item(spp, "32", plist_new_uint(320)); +		plist_dict_set_item(spp, "512", plist_new_uint(1280));  		plist_dict_set_item(spp, "64", plist_new_uint(640)); +		plist_dict_set_item(spp, "768", plist_new_uint(1280));  		plist_dict_set_item(spp, "8", plist_new_uint(80));  	}  	plist_dict_set_item(opts, "SystemPartitionPadding", spp); @@ -5072,7 +5554,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  	// start the restore process  	restore_error = restored_start_restore(restore, opts, client->restore->protocol_version);  	if (restore_error != RESTORE_E_SUCCESS) { -		error("ERROR: Unable to start the restore process\n"); +		logger(LL_ERROR, "Unable to start the restore process\n");  		plist_free(opts);  		restore_client_free(client);  		return -1; @@ -5084,30 +5566,30 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  	// restored and passes that data on to it's specific handler  	while (!(client->flags & FLAG_QUIT)) {  		if (err != 0 && client->flags & FLAG_IGNORE_ERRORS) { -			error("WARNING: Attempting to continue after critical error, restore might fail...\n"); +			logger(LL_WARNING, "Attempting to continue after critical error, restore might fail...\n");  			err = 0;  		}  		// finally, if any of these message handlers returned -1 then we encountered  		// an unrecoverable error, so we need to bail.  		if (err < 0) { -			error("ERROR: Unable to successfully restore device\n"); +			logger(LL_ERROR, "Unable to successfully restore device\n");  			client->flags |= FLAG_QUIT;  		}  		restore_error = restored_receive(restore, &message);  #ifdef HAVE_RESTORE_E_RECEIVE_TIMEOUT  		if (restore_error == RESTORE_E_RECEIVE_TIMEOUT) { -			debug("No data to read (timeout)\n"); +			logger(LL_DEBUG, "No data to read (timeout)\n");  			message = NULL;  			continue;  		} else if (restore_error != RESTORE_E_SUCCESS) { -			error("ERROR: Could not read data (%d). Aborting.\n", restore_error); +			logger(LL_ERROR, "Could not read data (%d). Aborting.\n", restore_error);  			err = -11;  			break;  		}  #else  		if (restore_error != RESTORE_E_SUCCESS) { -			debug("No data to read\n"); +			logger(LL_DEBUG, "No data to read\n");  			message = NULL;  			continue;  		} @@ -5116,9 +5598,8 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		// discover what kind of message has been received  		node = plist_dict_get_item(message, "MsgType");  		if (!node || plist_get_node_type(node) != PLIST_STRING) { -			debug("Unknown message received:\n"); -			//if (idevicerestore_debug) -				debug_plist(message); +			logger(LL_DEBUG, "Unknown message received:\n"); +			logger_dump_plist(LL_DEBUG, message, 1);  			plist_free(message);  			message = NULL;  			continue; @@ -5140,8 +5621,11 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  			args->message = plist_copy(message);  			if (thread_new(&t, _restore_handle_async_data_request, args) < 0) {  				free(args); -				error("ERROR: Failed to start async data request handler thread!\n"); +				logger(LL_ERROR, "Failed to start async data request handler thread!\n");  				err = -1; +				if (client->flags & FLAG_IGNORE_ERRORS) { +					client->flags &= ~FLAG_IGNORE_ERRORS; +				}  			} else {  				thread_detach(t);  			} @@ -5179,7 +5663,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  			// Get checkpoint id  			node = plist_dict_get_item(message, "CHECKPOINT_ID");  			if (!node || plist_get_node_type(node) != PLIST_INT) { -				debug("Failed to parse checkpoint id from checkpoint plist\n"); +				logger(LL_DEBUG, "Failed to parse checkpoint id from checkpoint plist\n");  				err = -1;  				break;  			} @@ -5190,7 +5674,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  			// Get checkpoint result  			node = plist_dict_get_item(message, "CHECKPOINT_RESULT");  			if (!node || plist_get_node_type(node) != PLIST_INT) { -				debug("Failed to parse checkpoint result from checkpoint plist\n"); +				logger(LL_DEBUG, "Failed to parse checkpoint result from checkpoint plist\n");  				err = -1;  				break;  			} @@ -5202,17 +5686,17 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  			}  			if (ckpt_complete) { -				info("Checkpoint completed id: 0x%" PRIX64 " (%s) result=%" PRIi64 "\n", ckpt_id, ckpt_name, ckpt_res); +				logger(LL_VERBOSE, "Checkpoint completed id: 0x%" PRIX64 " (%s) result=%" PRIi64 "\n", ckpt_id, ckpt_name, ckpt_res);  			} else { -				info("Checkpoint started   id: 0x%" PRIX64 " (%s)\n", ckpt_id, ckpt_name); +				logger(LL_VERBOSE, "Checkpoint started   id: 0x%" PRIX64 " (%s)\n", ckpt_id, ckpt_name);  			}  			node = plist_dict_get_item(message, "CHECKPOINT_WARNING");  			if (node) { -				info("Checkpoint WARNING id: 0x%" PRIX64 " result=%" PRIi64 ": %s\n", ckpt_id, ckpt_res, plist_get_string_ptr(node, NULL)); +				logger(LL_VERBOSE, "Checkpoint WARNING id: 0x%" PRIX64 " result=%" PRIi64 ": %s\n", ckpt_id, ckpt_res, plist_get_string_ptr(node, NULL));  			}  			node = plist_dict_get_item(message, "CHECKPOINT_ERROR");  			if (node) { -				info("Checkpoint FAILURE id: 0x%" PRIX64 " result=%" PRIi64 ": %s\n", ckpt_id, ckpt_res, plist_get_string_ptr(node, NULL)); +				logger(LL_VERBOSE, "Checkpoint FAILURE id: 0x%" PRIX64 " result=%" PRIi64 ": %s\n", ckpt_id, ckpt_res, plist_get_string_ptr(node, NULL));  			}  		} @@ -5243,9 +5727,8 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit  		// there might be some other message types i'm not aware of, but I think  		// at least the "previous error logs" messages usually end up here  		else { -			debug("Unknown message type received\n"); -			//if (idevicerestore_debug) -				debug_plist(message); +			logger(LL_DEBUG, "Unknown message type received\n"); +			logger_dump_plist(LL_DEBUG, message, 1);  		}  		free(type); | 
