forked from frederic/exynos-usbdl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexynos-usbdl.c
134 lines (111 loc) · 3.11 KB
/
exynos-usbdl.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* exynos-usbdl - github.com/frederic/exynos-usbdl
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "libusb-1.0/libusb.h"
#define DEBUG 1
#define VENDOR_ID 0x18d1
#define PRODUCT_ID 0x4f00
#define BLOCK_SIZE 512
#define CHUNK_SIZE (uint32_t)0xfffe00
#if DEBUG
#define dprint(args...) printf(args)
#else
#define dprint(args...)
#endif
libusb_device_handle *handle = NULL;
#define MAX_PAYLOAD_SIZE (BLOCK_SIZE - 10)
typedef struct __attribute__ ((__packed__)) dldata_s {
u_int32_t unk0;
u_int32_t size;// header(8) + data(n) + footer(2)
u_int8_t data[];
//u_int16_t footer;
} dldata_t;
static int send(dldata_t *payload) {
int rc;
int transferred;
uint total_size = payload->size;
uint8_t *payload_ptr = (uint8_t *)payload;
do {
rc = libusb_bulk_transfer(handle, LIBUSB_ENDPOINT_OUT | 2, payload_ptr, (total_size < BLOCK_SIZE ? total_size : BLOCK_SIZE), &transferred, 0);
if(rc) {
fprintf(stderr, "Error libusb_bulk_transfer: %s\n", libusb_error_name(rc));
return rc;
}
dprint("libusb_bulk_transfer: transferred=%d\n", transferred);
payload_ptr += transferred;
assert(total_size>=transferred);
total_size -= transferred;
} while(total_size > 0);
return rc;
}
int main(int argc, char *argv[])
{
libusb_context *ctx;
FILE *fd;
dldata_t *payload;
size_t payload_size, fd_size;
int target_id = -1;
uint8_t mode;
int rc;
if (!(argc == 2 || argc == 3)) {
printf("Usage: %s <input_file> [<output_file>]\n", argv[0]);
printf("\tmode: mode of operation\n");
printf("\tinput_file: payload binary to load and execute\n");
return EXIT_SUCCESS;
}
fd = fopen(argv[1],"rb");
if (fd == NULL) {
fprintf(stderr, "Can't open input file %s !\n", argv[1]);
return EXIT_FAILURE;
}
fseek(fd, 0, SEEK_END);
fd_size = ftell(fd);
payload_size = sizeof(dldata_t) + fd_size + 2;// +2 bytes for footer
payload = (dldata_t*)calloc(1, payload_size);
payload->size = payload_size;
fseek(fd, 0, SEEK_SET);
payload_size = fread(&payload->data, 1, fd_size, fd);
if (payload_size != fd_size) {
fprintf(stderr, "Error: cannot read entire file !\n");
return EXIT_FAILURE;
}
rc = libusb_init (&ctx);
if (rc < 0)
{
fprintf(stderr, "Error: failed to initialise libusb: %s\n", libusb_error_name(rc));
return EXIT_FAILURE;
}
#if DEBUG
libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
#endif
handle = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!handle) {
fprintf(stderr, "Error: cannot open device %04x:%04x\n", VENDOR_ID, PRODUCT_ID);
libusb_exit (NULL);
return EXIT_FAILURE;
}
libusb_set_auto_detach_kernel_driver(handle, 1);
rc = libusb_claim_interface(handle, 0);
if(rc) {
fprintf(stderr, "Error claiming interface: %s\n", libusb_error_name(rc));
return EXIT_FAILURE;
}
printf("Sending file %s (0x%lx)...\n", argv[1], fd_size);
rc = send(payload);
if(!rc)
printf("File %s sent !\n", argv[1]);
#if DEBUG
sleep(5);
#endif
libusb_release_interface(handle, 0);
if (handle) {
libusb_close (handle);
}
libusb_exit (NULL);
return EXIT_SUCCESS;
}