diff options
author | Joshua Hill | 2010-06-16 03:38:47 -0400 |
---|---|---|
committer | Joshua Hill | 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; +} |