summaryrefslogtreecommitdiffstats
path: root/src/libirecovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libirecovery.c')
-rw-r--r--src/libirecovery.c142
1 files changed, 117 insertions, 25 deletions
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 @@
25#include "libirecovery.h" 25#include "libirecovery.h"
26 26
27#define BUFFER_SIZE 0x1000 27#define BUFFER_SIZE 0x1000
28#define debug(...) if(client->debug) fprintf(stderr, __VA_ARGS__) 28#define debug(...) if(libirecovery_debug) fprintf(stderr, __VA_ARGS__)
29 29
30void irecv_print_progress(const char* operation, float progress); 30static int libirecovery_debug = 0;
31static libusb_context* libirecovery_context = NULL;
32
33int irecv_write_file(const char* filename, const void* data, size_t size);
34int irecv_read_file(const char* filename, char** data, uint32_t* size);
31 35
32irecv_error_t irecv_open(irecv_client_t* pclient) { 36irecv_error_t irecv_open(irecv_client_t* pclient) {
33 int i = 0; 37 int i = 0;
34 char serial[256]; 38 char serial[256];
35 struct libusb_device* usb_device = NULL; 39 struct libusb_device* usb_device = NULL;
36 struct libusb_context* usb_context = NULL;
37 struct libusb_device** usb_device_list = NULL; 40 struct libusb_device** usb_device_list = NULL;
38 struct libusb_device_handle* usb_handle = NULL; 41 struct libusb_device_handle* usb_handle = NULL;
39 struct libusb_device_descriptor usb_descriptor; 42 struct libusb_device_descriptor usb_descriptor;
40 43
41 *pclient = NULL; 44 *pclient = NULL;
42 libusb_init(&usb_context); 45 libusb_init(&libirecovery_context);
46 if(libirecovery_debug) {
47 irecv_set_debug_level(libirecovery_debug);
48 }
49
43 irecv_error_t error = IRECV_E_SUCCESS; 50 irecv_error_t error = IRECV_E_SUCCESS;
44 int usb_device_count = libusb_get_device_list(usb_context, &usb_device_list); 51 int usb_device_count = libusb_get_device_list(libirecovery_context, &usb_device_list);
45 for (i = 0; i < usb_device_count; i++) { 52 for (i = 0; i < usb_device_count; i++) {
46 usb_device = usb_device_list[i]; 53 usb_device = usb_device_list[i];
47 libusb_get_device_descriptor(usb_device, &usb_descriptor); 54 libusb_get_device_descriptor(usb_device, &usb_descriptor);
@@ -57,7 +64,7 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {
57 if (usb_handle == NULL) { 64 if (usb_handle == NULL) {
58 libusb_free_device_list(usb_device_list, 1); 65 libusb_free_device_list(usb_device_list, 1);
59 libusb_close(usb_handle); 66 libusb_close(usb_handle);
60 libusb_exit(usb_context); 67 libusb_exit(libirecovery_context);
61 return IRECV_E_UNABLE_TO_CONNECT; 68 return IRECV_E_UNABLE_TO_CONNECT;
62 } 69 }
63 libusb_free_device_list(usb_device_list, 1); 70 libusb_free_device_list(usb_device_list, 1);
@@ -65,14 +72,13 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {
65 irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client)); 72 irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client));
66 if (client == NULL) { 73 if (client == NULL) {
67 libusb_close(usb_handle); 74 libusb_close(usb_handle);
68 libusb_exit(usb_context); 75 libusb_exit(libirecovery_context);
69 return IRECV_E_OUT_OF_MEMORY; 76 return IRECV_E_OUT_OF_MEMORY;
70 } 77 }
71 78
72 memset(client, '\0', sizeof(struct irecv_client)); 79 memset(client, '\0', sizeof(struct irecv_client));
73 client->interface = 0; 80 client->interface = 0;
74 client->handle = usb_handle; 81 client->handle = usb_handle;
75 client->context = usb_context;
76 client->mode = usb_descriptor.idProduct; 82 client->mode = usb_descriptor.idProduct;
77 83
78 error = irecv_set_configuration(client, 1); 84 error = irecv_set_configuration(client, 1);
@@ -223,9 +229,9 @@ irecv_error_t irecv_close(irecv_client_t client) {
223 client->handle = NULL; 229 client->handle = NULL;
224 } 230 }
225 231
226 if (client->context != NULL) { 232 if (libirecovery_context != NULL) {
227 libusb_exit(client->context); 233 libusb_exit(libirecovery_context);
228 client->context = NULL; 234 libirecovery_context = NULL;
229 } 235 }
230 236
231 free(client); 237 free(client);
@@ -235,14 +241,11 @@ irecv_error_t irecv_close(irecv_client_t client) {
235 return IRECV_E_SUCCESS; 241 return IRECV_E_SUCCESS;
236} 242}
237 243
238irecv_error_t irecv_set_debug(irecv_client_t client, int level) { 244void irecv_set_debug_level(int level) {
239 if (client == NULL || client->context == NULL) { 245 libirecovery_debug = level;
240 return IRECV_E_NO_DEVICE; 246 if(libirecovery_context) {
247 libusb_set_debug(libirecovery_context, libirecovery_debug);
241 } 248 }
242
243 libusb_set_debug(client->context, level);
244 client->debug = level;
245 return IRECV_E_SUCCESS;
246} 249}
247 250
248irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) { 251irecv_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
350 unsigned int status = 0; 353 unsigned int status = 0;
351 for (i = 0; i < packets; i++) { 354 for (i = 0; i < packets; i++) {
352 int size = i + 1 < packets ? 0x800 : last; 355 int size = i + 1 < packets ? 0x800 : last;
353 int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], 356 int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], size, 1000);
354 size, 1000);
355 if (bytes != size) { 357 if (bytes != size) {
356 return IRECV_E_USB_UPLOAD; 358 return IRECV_E_USB_UPLOAD;
357 } 359 }
358 360
359 debug("Sent %d bytes\n", bytes);
360
361 error = irecv_get_status(client, &status); 361 error = irecv_get_status(client, &status);
362 if (error != IRECV_E_SUCCESS) { 362 if (error != IRECV_E_SUCCESS) {
363 return error; 363 return error;
@@ -375,6 +375,8 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
375 event.data = "Uploading"; 375 event.data = "Uploading";
376 event.size = count; 376 event.size = count;
377 client->progress_callback(client, &event); 377 client->progress_callback(client, &event);
378 } else {
379 debug("Sent: %d bytes - %d of %d\n", bytes, count, length);
378 } 380 }
379 } 381 }
380 382
@@ -457,7 +459,6 @@ irecv_error_t irecv_get_cpid(irecv_client_t client, unsigned int* cpid) {
457 } 459 }
458 460
459 libusb_get_string_descriptor_ascii(client->handle, 3, info, 255); 461 libusb_get_string_descriptor_ascii(client->handle, 3, info, 255);
460 printf("%d: %s\n", strlen(info), info);
461 462
462 unsigned char* cpid_string = strstr(info, "CPID:"); 463 unsigned char* cpid_string = strstr(info, "CPID:");
463 if (cpid_string == NULL) { 464 if (cpid_string == NULL) {
@@ -478,7 +479,6 @@ irecv_error_t irecv_get_bdid(irecv_client_t client, unsigned int* bdid) {
478 } 479 }
479 480
480 libusb_get_string_descriptor_ascii(client->handle, 3, info, 255); 481 libusb_get_string_descriptor_ascii(client->handle, 3, info, 255);
481 printf("%d: %s\n", strlen(info), info);
482 482
483 unsigned char* bdid_string = strstr(info, "BDID:"); 483 unsigned char* bdid_string = strstr(info, "BDID:");
484 if (bdid_string == NULL) { 484 if (bdid_string == NULL) {
@@ -499,7 +499,6 @@ irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) {
499 } 499 }
500 500
501 libusb_get_string_descriptor_ascii(client->handle, 3, info, 255); 501 libusb_get_string_descriptor_ascii(client->handle, 3, info, 255);
502 printf("%d: %s\n", strlen(info), info);
503 502
504 unsigned char* ecid_string = strstr(info, "ECID:"); 503 unsigned char* ecid_string = strstr(info, "ECID:");
505 if (ecid_string == NULL) { 504 if (ecid_string == NULL) {
@@ -520,6 +519,37 @@ irecv_error_t irecv_send_exploit(irecv_client_t client) {
520 return IRECV_E_SUCCESS; 519 return IRECV_E_SUCCESS;
521} 520}
522 521
522irecv_error_t irecv_execute_script(irecv_client_t client, const char* filename) {
523 irecv_error_t error = IRECV_E_SUCCESS;
524 if (client == NULL || client->handle == NULL) {
525 return IRECV_E_NO_DEVICE;
526 }
527
528 int file_size = 0;
529 char* file_data = NULL;
530 if(irecv_read_file(filename, &file_data, &file_size) < 0) {
531 return IRECV_E_FILE_NOT_FOUND;
532 }
533
534 char* line = strtok(file_data, "\n");
535 while(line != NULL) {
536 if(line[0] != '#') {
537 error = irecv_send_command(client, line);
538 if(error != IRECV_E_SUCCESS) {
539 return error;
540 }
541
542 error = irecv_receive(client);
543 if(error != IRECV_E_SUCCESS) {
544 return error;
545 }
546 }
547 line = strtok(NULL, "\n");
548 }
549
550 return IRECV_E_SUCCESS;
551}
552
523irecv_error_t irecv_setenv(irecv_client_t client, const char* variable, const char* value) { 553irecv_error_t irecv_setenv(irecv_client_t client, const char* variable, const char* value) {
524 char command[256]; 554 char command[256];
525 if (client == NULL || client->handle == NULL) { 555 if (client == NULL || client->handle == NULL) {
@@ -578,3 +608,65 @@ const char* irecv_strerror(irecv_error_t error) {
578 608
579 return NULL; 609 return NULL;
580} 610}
611
612int irecv_write_file(const char* filename, const void* data, size_t size) {
613 size_t bytes = 0;
614 FILE* file = NULL;
615
616 debug("Writing data to %s\n", filename);
617 file = fopen(filename, "wb");
618 if (file == NULL) {
619 error("read_file: Unable to open file %s\n", filename);
620 return -1;
621 }
622
623 bytes = fwrite(data, 1, size, file);
624 fclose(file);
625
626 if (bytes != size) {
627 error("ERROR: Unable to write entire file: %s: %d of %d\n", filename, bytes, size);
628 return -1;
629 }
630
631 return size;
632}
633
634int irecv_read_file(const char* filename, char** data, uint32_t* size) {
635 size_t bytes = 0;
636 size_t length = 0;
637 FILE* file = NULL;
638 char* buffer = NULL;
639 debug("Reading data from %s\n", filename);
640
641 *size = 0;
642 *data = NULL;
643
644 file = fopen(filename, "rb");
645 if (file == NULL) {
646 error("read_file: File %s not found\n", filename);
647 return -1;
648 }
649
650 fseek(file, 0, SEEK_END);
651 length = ftell(file);
652 rewind(file);
653
654 buffer = (char*) malloc(length);
655 if(buffer == NULL) {
656 error("ERROR: Out of memory\n");
657 fclose(file);
658 return -1;
659 }
660 bytes = fread(buffer, 1, length, file);
661 fclose(file);
662
663 if(bytes != length) {
664 error("ERROR: Unable to read entire file\n");
665 free(buffer);
666 return -1;
667 }
668
669 *size = length;
670 *data = buffer;
671 return 0;
672}