diff options
| author | 2010-06-16 03:38:47 -0400 | |
|---|---|---|
| committer | 2010-06-16 03:38:47 -0400 | |
| commit | c2249545efe5451f25e08fbc57e19b9c91a855c5 (patch) | |
| tree | 6a88e84143b613a184039302a6fc5a0f9e1cdf3c | |
| parent | 671640f5e2c9908a3807d537e9e761e398347b57 (diff) | |
| download | libirecovery-c2249545efe5451f25e08fbc57e19b9c91a855c5.tar.gz libirecovery-c2249545efe5451f25e08fbc57e19b9c91a855c5.tar.bz2 | |
Changed debug variable to be a static global variable to allow set once always enabled style debug flag
Added -e flag to load and execute a premade script file along with a sample script
| -rw-r--r-- | TODO | 25 | ||||
| -rw-r--r-- | include/libirecovery.h | 5 | ||||
| -rw-r--r-- | scripts/test.irs | 21 | ||||
| -rw-r--r-- | src/irecovery.c | 42 | ||||
| -rw-r--r-- | src/libirecovery.c | 142 | 
5 files changed, 184 insertions, 51 deletions
| @@ -1,16 +1,15 @@  TODO List  ------------------------------------------------ -1) libirecovery debug should be as static variable so the client doesn't need to be passed and can be set only once. -2) Need to implement irecv_saveenv() -3) Need to implement irecv_bootx() -4) Neex to implement irecv_go() -5) Need to implement irecv_bgcolor() -6) Need to implememt irecv_setpicture() -7) Need to impelemnt irecv_reboot() -8) Should figure out a better place to store callbacks so the CONNECTED callback can actually be used -9) would be nice to change to use asyncronous connections -10) could add a function to identify whether we're connected to iBoot/iBEC/iBSS or DFU -11) could add a function to identify which version we're connected to -12) could add a function to return the device serial number -13) fix command parsing to strip quotes
\ No newline at end of file +o) Need to implement irecv_saveenv() +o) Need to implement irecv_bootx() +o) Neex to implement irecv_go() +o) Need to implement irecv_bgcolor() +o) Need to implememt irecv_setpicture() +o) Need to impelemnt irecv_reboot() +o) Should figure out a better place to store callbacks so the CONNECTED callback can actually be used +o) would be nice to change to use asyncronous connections +o) could add a function to identify whether we're connected to iBoot/iBEC/iBSS or DFU +o) could add a function to identify which version we're connected to +o) could add a function to return the device serial number +o) fix command parsing to strip quotes
\ No newline at end of file diff --git a/include/libirecovery.h b/include/libirecovery.h index 50ec5be..d30dd73 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h @@ -71,7 +71,6 @@ struct irecv_client {  	int interface;  	int alt_interface;  	unsigned short mode; -	libusb_context* context;  	libusb_device_handle* handle;  	irecv_event_cb_t progress_callback;  	irecv_event_cb_t received_callback; @@ -89,12 +88,12 @@ irecv_error_t irecv_reset(irecv_client_t client);  irecv_error_t irecv_close(irecv_client_t client);  irecv_error_t irecv_receive(irecv_client_t client);  irecv_error_t irecv_send_exploit(irecv_client_t client); -irecv_error_t irecv_set_debug(irecv_client_t client, int level); +void irecv_set_debug_level(int level); +irecv_error_t irecv_execute_script(irecv_client_t client, const char* filename);  irecv_error_t irecv_getenv(irecv_client_t client, const char* variable, char** value);  irecv_error_t irecv_get_cpid(irecv_client_t client, unsigned int* cpid);  irecv_error_t irecv_get_bdid(irecv_client_t client, unsigned int* bdid);  irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid); -irecv_error_t irecv_send(irecv_client_t client, unsigned char* command);  irecv_error_t irecv_send_file(irecv_client_t client, const char* filename);  irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command);  irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration); diff --git a/scripts/test.irs b/scripts/test.irs new file mode 100644 index 0000000..77f959d --- /dev/null +++ b/scripts/test.irs @@ -0,0 +1,21 @@ +# This small script should make the device flash +# Red, Green, Blue a few times then reboot. +bgcolor 255 0 0 +bgcolor 0 255 0 +bgcolor 0 0 255 +bgcolor 255 0 0 +bgcolor 0 255 0 +bgcolor 0 0 255 +bgcolor 255 0 0 +bgcolor 0 255 0 +bgcolor 0 0 255 +bgcolor 255 0 0 +bgcolor 0 255 0 +bgcolor 0 0 255 +bgcolor 255 0 0 +bgcolor 0 255 0 +bgcolor 0 0 255 +bgcolor 255 0 0 +bgcolor 0 255 0 +bgcolor 0 0 255 +reboot diff --git a/src/irecovery.c b/src/irecovery.c index baae17e..c282cda 100644 --- a/src/irecovery.c +++ b/src/irecovery.c @@ -27,13 +27,13 @@  #define debug(...) if(verbose) fprintf(stderr, __VA_ARGS__)  enum { -	kResetDevice, kStartShell, kSendCommand, kSendFile, kSendExploit +	kResetDevice, kStartShell, kSendCommand, kSendFile, kSendExploit, kSendScript  };  static unsigned int quit = 0;  static unsigned int verbose = 0; -void print_progress_bar(const char* operation, double progress); +void print_progress_bar(double progress);  int received_cb(irecv_client_t client, const irecv_event_t* event);  int progress_cb(irecv_client_t client, const irecv_event_t* event);  int precommand_cb(irecv_client_t client, const irecv_event_t* event); @@ -61,7 +61,7 @@ void parse_command(irecv_client_t client, unsigned char* command, unsigned int s  	if (!strcmp(cmd, "/upload")) {  		char* filename = strtok(NULL, " "); -		debug("Sending %s\n", filename); +		debug("Uploading files %s\n", filename);  		if (filename != NULL) {  			irecv_send_file(client, filename);  		} @@ -69,12 +69,21 @@ void parse_command(irecv_client_t client, unsigned char* command, unsigned int s  	if (!strcmp(cmd, "/exploit")) {  		char* filename = strtok(NULL, " "); -		debug("Sending %s\n", filename); +		debug("Sending exploit %s\n", filename);  		if (filename != NULL) {  			irecv_send_file(client, filename);  		}  		irecv_send_exploit(client); -	} +	} else + +		if (!strcmp(cmd, "/execute")) { +			char* filename = strtok(NULL, " "); +			debug("Executing script %s\n", filename); +			if (filename != NULL) { +				irecv_execute_script(client, filename); +			} +		} +  	free(action);  } @@ -171,12 +180,12 @@ int postcommand_cb(irecv_client_t client, const irecv_event_t* event) {  int progress_cb(irecv_client_t client, const irecv_event_t* event) {  	if (event->type == IRECV_PROGRESS) { -		print_progress_bar(event->data, event->progress); +		print_progress_bar(event->progress);  	}  	return 0;  } -void print_progress_bar(const char* operation, double progress) { +void print_progress_bar(double progress) {  	int i = 0;  	if(progress < 0) {  		return; @@ -186,7 +195,7 @@ void print_progress_bar(const char* operation, double progress) {  		progress = 100;  	} -	printf("\r%s [", operation); +	printf("\r[");  	for(i = 0; i < 50; i++) {  		if(i < progress / 2) {  			printf("="); @@ -212,6 +221,7 @@ void print_usage() {  	printf("\t-h\t\tShow this help.\n");  	printf("\t-r\t\tReset client.\n");  	printf("\t-s\t\tStart interactive shell.\n"); +	printf("\t-e <script>\tExecutes recovery shell script.");  	exit(1);  } @@ -222,7 +232,7 @@ int main(int argc, char** argv) {  	char* argument = NULL;  	irecv_error_t error = 0;  	if (argc == 1) print_usage(); -	while ((opt = getopt(argc, argv, "vhrsc:f:k::")) > 0) { +	while ((opt = getopt(argc, argv, "vhrsc:f:e:k::")) > 0) {  		switch (opt) {  		case 'v':  			verbose += 1; @@ -255,6 +265,11 @@ int main(int argc, char** argv) {  			argument = optarg;  			break; +		case 'e': +			action = kSendScript; +			argument = optarg; +			break; +  		default:  			fprintf(stderr, "Unknown argument\n");  			return -1; @@ -275,7 +290,7 @@ int main(int argc, char** argv) {  		}  	} -	if (verbose) irecv_set_debug(client, verbose); +	if (verbose) irecv_set_debug_level(verbose);  	switch (action) {  	case kResetDevice: @@ -310,6 +325,13 @@ int main(int argc, char** argv) {  		init_shell(client);  		break; +	case kSendScript: +		error = irecv_execute_script(client, argument); +		if(error != IRECV_E_SUCCESS) { +			debug("%s\n", irecv_strerror(error)); +		} +		break; +  	default:  		fprintf(stderr, "Unknown action\n");  		break; diff --git a/src/libirecovery.c b/src/libirecovery.c index 05a162f..dd5c734 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -25,23 +25,30 @@  #include "libirecovery.h"  #define BUFFER_SIZE 0x1000 -#define debug(...) if(client->debug) fprintf(stderr, __VA_ARGS__) +#define debug(...) if(libirecovery_debug) fprintf(stderr, __VA_ARGS__) -void irecv_print_progress(const char* operation, float progress); +static int libirecovery_debug = 0; +static libusb_context* libirecovery_context = NULL; + +int irecv_write_file(const char* filename, const void* data, size_t size); +int irecv_read_file(const char* filename, char** data, uint32_t* size);  irecv_error_t irecv_open(irecv_client_t* pclient) {  	int i = 0;  	char serial[256];  	struct libusb_device* usb_device = NULL; -	struct libusb_context* usb_context = NULL;  	struct libusb_device** usb_device_list = NULL;  	struct libusb_device_handle* usb_handle = NULL;  	struct libusb_device_descriptor usb_descriptor;  	*pclient = NULL; -	libusb_init(&usb_context); +	libusb_init(&libirecovery_context); +	if(libirecovery_debug) { +		irecv_set_debug_level(libirecovery_debug); +	} +  	irecv_error_t error = IRECV_E_SUCCESS; -	int usb_device_count = libusb_get_device_list(usb_context, &usb_device_list); +	int usb_device_count = libusb_get_device_list(libirecovery_context, &usb_device_list);  	for (i = 0; i < usb_device_count; i++) {  		usb_device = usb_device_list[i];  		libusb_get_device_descriptor(usb_device, &usb_descriptor); @@ -57,7 +64,7 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {  				if (usb_handle == NULL) {  					libusb_free_device_list(usb_device_list, 1);  					libusb_close(usb_handle); -					libusb_exit(usb_context); +					libusb_exit(libirecovery_context);  					return IRECV_E_UNABLE_TO_CONNECT;  				}  				libusb_free_device_list(usb_device_list, 1); @@ -65,14 +72,13 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {  				irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client));  				if (client == NULL) {  					libusb_close(usb_handle); -					libusb_exit(usb_context); +					libusb_exit(libirecovery_context);  					return IRECV_E_OUT_OF_MEMORY;  				}  				memset(client, '\0', sizeof(struct irecv_client));  				client->interface = 0;  				client->handle = usb_handle; -				client->context = usb_context;  				client->mode = usb_descriptor.idProduct;  				error = irecv_set_configuration(client, 1); @@ -223,9 +229,9 @@ irecv_error_t irecv_close(irecv_client_t client) {  			client->handle = NULL;  		} -		if (client->context != NULL) { -			libusb_exit(client->context); -			client->context = NULL; +		if (libirecovery_context != NULL) { +			libusb_exit(libirecovery_context); +			libirecovery_context = NULL;  		}  		free(client); @@ -235,14 +241,11 @@ irecv_error_t irecv_close(irecv_client_t client) {  	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_set_debug(irecv_client_t client, int level) { -	if (client == NULL || client->context == NULL) { -		return IRECV_E_NO_DEVICE; +void irecv_set_debug_level(int level) { +	libirecovery_debug = level; +	if(libirecovery_context) { +		libusb_set_debug(libirecovery_context, libirecovery_debug);  	} - -	libusb_set_debug(client->context, level); -	client->debug = level; -	return IRECV_E_SUCCESS;  }  irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) { @@ -350,14 +353,11 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un  	unsigned int status = 0;  	for (i = 0; i < packets; i++) {  		int size = i + 1 < packets ? 0x800 : last; -		int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], -				size, 1000); +		int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], size, 1000);  		if (bytes != size) {  			return IRECV_E_USB_UPLOAD;  		} -		debug("Sent %d bytes\n", bytes); -  		error = irecv_get_status(client, &status);  		if (error != IRECV_E_SUCCESS) {  			return error; @@ -375,6 +375,8 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un  			event.data = "Uploading";  			event.size = count;  			client->progress_callback(client, &event); +		} else { +			debug("Sent: %d bytes - %d of %d\n", bytes, count, length);  		}  	} @@ -457,7 +459,6 @@ irecv_error_t irecv_get_cpid(irecv_client_t client, unsigned int* cpid) {  	}  	libusb_get_string_descriptor_ascii(client->handle, 3, info, 255); -	printf("%d: %s\n", strlen(info), info);  	unsigned char* cpid_string = strstr(info, "CPID:");  	if (cpid_string == NULL) { @@ -478,7 +479,6 @@ irecv_error_t irecv_get_bdid(irecv_client_t client, unsigned int* bdid) {  	}  	libusb_get_string_descriptor_ascii(client->handle, 3, info, 255); -	printf("%d: %s\n", strlen(info), info);  	unsigned char* bdid_string = strstr(info, "BDID:");  	if (bdid_string == NULL) { @@ -499,7 +499,6 @@ irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) {  	}  	libusb_get_string_descriptor_ascii(client->handle, 3, info, 255); -	printf("%d: %s\n", strlen(info), info);  	unsigned char* ecid_string = strstr(info, "ECID:");  	if (ecid_string == NULL) { @@ -520,6 +519,37 @@ irecv_error_t irecv_send_exploit(irecv_client_t client) {  	return IRECV_E_SUCCESS;  } +irecv_error_t irecv_execute_script(irecv_client_t client, const char* filename) { +	irecv_error_t error = IRECV_E_SUCCESS; +	if (client == NULL || client->handle == NULL) { +		return IRECV_E_NO_DEVICE; +	} + +	int file_size = 0; +	char* file_data = NULL; +	if(irecv_read_file(filename, &file_data, &file_size) < 0) { +		return IRECV_E_FILE_NOT_FOUND; +	} + +	char* line = strtok(file_data, "\n"); +	while(line != NULL) { +		if(line[0] != '#') { +			error = irecv_send_command(client, line); +			if(error != IRECV_E_SUCCESS) { +				return error; +			} + +			error = irecv_receive(client); +			if(error != IRECV_E_SUCCESS) { +				return error; +			} +		} +		line = strtok(NULL, "\n"); +	} + +	return IRECV_E_SUCCESS; +} +  irecv_error_t irecv_setenv(irecv_client_t client, const char* variable, const char* value) {  	char command[256];  	if (client == NULL || client->handle == NULL) { @@ -578,3 +608,65 @@ const char* irecv_strerror(irecv_error_t error) {  	return NULL;  } + +int irecv_write_file(const char* filename, const void* data, size_t size) { +	size_t bytes = 0; +	FILE* file = NULL; + +	debug("Writing data to %s\n", filename); +	file = fopen(filename, "wb"); +	if (file == NULL) { +		error("read_file: Unable to open file %s\n", filename); +		return -1; +	} + +	bytes = fwrite(data, 1, size, file); +	fclose(file); + +	if (bytes != size) { +		error("ERROR: Unable to write entire file: %s: %d of %d\n", filename, bytes, size); +		return -1; +	} + +	return size; +} + +int irecv_read_file(const char* filename, char** data, uint32_t* size) { +	size_t bytes = 0; +	size_t length = 0; +	FILE* file = NULL; +	char* buffer = NULL; +	debug("Reading data from %s\n", filename); + +	*size = 0; +	*data = NULL; + +	file = fopen(filename, "rb"); +	if (file == NULL) { +		error("read_file: File %s not found\n", filename); +		return -1; +	} + +	fseek(file, 0, SEEK_END); +	length = ftell(file); +	rewind(file); + +	buffer = (char*) malloc(length); +	if(buffer == NULL) { +		error("ERROR: Out of memory\n"); +		fclose(file); +		return -1; +	} +	bytes = fread(buffer, 1, length, file); +	fclose(file); + +	if(bytes != length) { +		error("ERROR: Unable to read entire file\n"); +		free(buffer); +		return -1; +	} + +	*size = length; +	*data = buffer; +	return 0; +} | 
