summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-06-16 03:38:47 -0400
committerGravatar Joshua Hill2010-06-16 03:38:47 -0400
commitc2249545efe5451f25e08fbc57e19b9c91a855c5 (patch)
tree6a88e84143b613a184039302a6fc5a0f9e1cdf3c
parent671640f5e2c9908a3807d537e9e761e398347b57 (diff)
downloadlibirecovery-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--TODO25
-rw-r--r--include/libirecovery.h5
-rw-r--r--scripts/test.irs21
-rw-r--r--src/irecovery.c42
-rw-r--r--src/libirecovery.c142
5 files changed, 184 insertions, 51 deletions
diff --git a/TODO b/TODO
index 306a1ae..411f6e6 100644
--- a/TODO
+++ b/TODO
@@ -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;
+}