summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libirecovery.c100
1 files changed, 99 insertions, 1 deletions
diff --git a/libirecovery.c b/libirecovery.c
index 71de46d..2385174 100644
--- a/libirecovery.c
+++ b/libirecovery.c
@@ -46,6 +46,76 @@ static libusb_context* libirecovery_context = NULL;
46int irecv_write_file(const char* filename, const void* data, size_t size); 46int irecv_write_file(const char* filename, const void* data, size_t size);
47int irecv_read_file(const char* filename, char** data, uint32_t* size); 47int irecv_read_file(const char* filename, char** data, uint32_t* size);
48 48
49static unsigned int dfu_hash_t1[256] = {
50 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
51 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
52 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
53 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
54 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
55 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
56 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
57 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
58 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
59 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
60 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
61 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
62 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
63 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
64 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
65 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
66 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
67 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
68 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
69 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
70 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
71 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
72 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
73 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
74 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
75 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
76 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
77 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
78 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
79 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
80 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
81 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
82 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
83 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
84 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
85 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
86 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
87 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
88 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
89 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
90 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
91 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
92 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
93 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
94 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
95 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
96 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
97 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
98 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
99 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
100 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
101 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
102 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
103 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
104 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
105 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
106 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
107 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
108 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
109 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
110 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
111 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
112 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
113 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
114};
115
116#define dfu_hash_step(a,b) \
117 a = (dfu_hash_t1[(a & 0xFF) ^ ((unsigned char)b)] ^ (a >> 8))
118
49#ifdef WIN32 119#ifdef WIN32
50static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L, 0xD61A, 0x4AF6, {0x9A, 0xB6, 0x11, 0xE5, 0x22, 0x36, 0xC5, 0x76}}; 120static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L, 0xD61A, 0x4AF6, {0x9A, 0xB6, 0x11, 0xE5, 0x22, 0x36, 0xC5, 0x76}};
51static const GUID GUID_DEVINTERFACE_DFU = {0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}}; 121static const GUID GUID_DEVINTERFACE_DFU = {0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}};
@@ -683,6 +753,8 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
683 int recovery_mode = ((client->mode != kDfuMode) && (client->mode != kWTFMode)); 753 int recovery_mode = ((client->mode != kDfuMode) && (client->mode != kWTFMode));
684 if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; 754 if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE;
685 755
756 unsigned int h1 = 0xFFFFFFFF;
757 unsigned char dfu_xbuf[12] = {0xff, 0xff, 0xff, 0xff, 0xac, 0x05, 0x00, 0x01, 0x55, 0x46, 0x44, 0x10};
686 int packet_size = recovery_mode ? 0x8000 : 0x800; 758 int packet_size = recovery_mode ? 0x8000 : 0x800;
687 int last = length % packet_size; 759 int last = length % packet_size;
688 int packets = length / packet_size; 760 int packets = length / packet_size;
@@ -714,7 +786,33 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
714 if (recovery_mode) { 786 if (recovery_mode) {
715 error = irecv_bulk_transfer(client, 0x04, &buffer[i * packet_size], size, &bytes, USB_TIMEOUT); 787 error = irecv_bulk_transfer(client, 0x04, &buffer[i * packet_size], size, &bytes, USB_TIMEOUT);
716 } else { 788 } else {
717 bytes = irecv_control_transfer(client, 0x21, 1, 0, 0, &buffer[i * packet_size], size, USB_TIMEOUT); 789 int j;
790 for (j = 0; j < size; j++) {
791 dfu_hash_step(h1, buffer[i*packet_size + j]);
792 }
793 if (i+1 == packets) {
794 for (j = 0; j < 2; j++) {
795 dfu_hash_step(h1, dfu_xbuf[j*6 + 0]);
796 dfu_hash_step(h1, dfu_xbuf[j*6 + 1]);
797 dfu_hash_step(h1, dfu_xbuf[j*6 + 2]);
798 dfu_hash_step(h1, dfu_xbuf[j*6 + 3]);
799 dfu_hash_step(h1, dfu_xbuf[j*6 + 4]);
800 dfu_hash_step(h1, dfu_xbuf[j*6 + 5]);
801 }
802
803 char* newbuf = (char*)malloc(size + 16);
804 memcpy(newbuf, &buffer[i * packet_size], size);
805 memcpy(newbuf+size, dfu_xbuf, 12);
806 newbuf[size+12] = h1 & 0xFF;
807 newbuf[size+13] = (h1 >> 8) & 0xFF;
808 newbuf[size+14] = (h1 >> 16) & 0xFF;
809 newbuf[size+15] = (h1 >> 24) & 0xFF;
810 size += 16;
811 bytes = irecv_control_transfer(client, 0x21, 1, i, 0, newbuf, size, USB_TIMEOUT);
812 free(newbuf);
813 } else {
814 bytes = irecv_control_transfer(client, 0x21, 1, i, 0, &buffer[i * packet_size], size, USB_TIMEOUT);
815 }
718 } 816 }
719 817
720 if (bytes != size) { 818 if (bytes != size) {