diff options
Diffstat (limited to 'utils/jz4740_usbtool/jz4740_usbtool.c')
-rwxr-xr-x | utils/jz4740_usbtool/jz4740_usbtool.c | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/utils/jz4740_usbtool/jz4740_usbtool.c b/utils/jz4740_usbtool/jz4740_usbtool.c new file mode 100755 index 0000000000..908cf723d0 --- /dev/null +++ b/utils/jz4740_usbtool/jz4740_usbtool.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * based on tcctool.c by Dave Chapman | ||
13 | * | ||
14 | * USB code based on ifp-line - http://ifp-driver.sourceforge.net | ||
15 | * | ||
16 | * ifp-line is (C) Pavel Kriz, Jun Yamishiro and Joe Roback and | ||
17 | * licensed under the GPL (v2) | ||
18 | * | ||
19 | * | ||
20 | * All files in this archive are subject to the GNU General Public License. | ||
21 | * See the file COPYING in the source tree root for full license agreement. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #include <stdio.h> | ||
29 | #include <inttypes.h> | ||
30 | #include <usb.h> | ||
31 | #include <string.h> | ||
32 | #include <sys/types.h> | ||
33 | #include <sys/stat.h> | ||
34 | #include <unistd.h> | ||
35 | #include <fcntl.h> | ||
36 | #include "jz4740.h" | ||
37 | |||
38 | #define VERSION "0.2" | ||
39 | |||
40 | #define MAX_FIRMWARESIZE (64*1024*1024) /* Arbitrary limit (for safety) */ | ||
41 | |||
42 | /* For win32 compatibility: */ | ||
43 | #ifndef O_BINARY | ||
44 | #define O_BINARY 0 | ||
45 | #endif | ||
46 | |||
47 | /* USB IDs for USB Boot Mode */ | ||
48 | #define VID 0x601A | ||
49 | #define PID 0x4740 | ||
50 | |||
51 | #define EP_BULK_TO 0x01 | ||
52 | #define TOUT 5000 | ||
53 | |||
54 | #ifndef MAX | ||
55 | #define MAX(a,b) (((a)>(b))?(a):(b)) | ||
56 | #endif | ||
57 | |||
58 | enum USB_JZ4740_REQUEST | ||
59 | { | ||
60 | VR_GET_CPU_INFO = 0, | ||
61 | VR_SET_DATA_ADDRESS, | ||
62 | VR_SET_DATA_LENGTH, | ||
63 | VR_FLUSH_CACHES, | ||
64 | VR_PROGRAM_START1, | ||
65 | VR_PROGRAM_START2, | ||
66 | VR_NOR_OPS, | ||
67 | VR_NAND_OPS, | ||
68 | VR_SDRAM_OPS, | ||
69 | VR_CONFIGURATION | ||
70 | }; | ||
71 | |||
72 | enum NOR_OPS_TYPE | ||
73 | { | ||
74 | NOR_INIT = 0, | ||
75 | NOR_QUERY, | ||
76 | NOR_WRITE, | ||
77 | NOR_ERASE_CHIP, | ||
78 | NOR_ERASE_SECTOR | ||
79 | }; | ||
80 | |||
81 | enum NOR_FLASH_TYPE | ||
82 | { | ||
83 | NOR_AM29 = 0, | ||
84 | NOR_SST28, | ||
85 | NOR_SST39x16, | ||
86 | NOR_SST39x8 | ||
87 | }; | ||
88 | |||
89 | enum NAND_OPS_TYPE | ||
90 | { | ||
91 | NAND_QUERY = 0, | ||
92 | NAND_INIT, | ||
93 | NAND_MARK_BAD, | ||
94 | NAND_READ_OOB, | ||
95 | NAND_READ_RAW, | ||
96 | NAND_ERASE, | ||
97 | NAND_READ, | ||
98 | NAND_PROGRAM, | ||
99 | NAND_READ_TO_RAM | ||
100 | }; | ||
101 | |||
102 | enum SDRAM_OPS_TYPE | ||
103 | { | ||
104 | SDRAM_LOAD, | ||
105 | |||
106 | }; | ||
107 | |||
108 | enum DATA_STRUCTURE_OB | ||
109 | { | ||
110 | DS_flash_info , | ||
111 | DS_hand | ||
112 | }; | ||
113 | |||
114 | enum OPTION | ||
115 | { | ||
116 | OOB_ECC, | ||
117 | OOB_NO_ECC, | ||
118 | NO_OOB, | ||
119 | }; | ||
120 | |||
121 | #define SEND_COMMAND(cmd, arg) err = usb_control_msg(dh, USB_ENDPOINT_OUT | USB_TYPE_VENDOR, cmd, arg>>16, arg&0xFFFF, NULL, 0, TOUT);\ | ||
122 | if (err < 0) \ | ||
123 | { \ | ||
124 | fprintf(stderr,"\n[ERR] Error sending control message (%d, %s)\n", err, usb_strerror()); \ | ||
125 | return -1; \ | ||
126 | } | ||
127 | |||
128 | #define GET_CPU_INFO(s) err = usb_control_msg(dh, USB_ENDPOINT_IN | USB_TYPE_VENDOR, VR_GET_CPU_INFO, 0, 0, buf, 8, TOUT); \ | ||
129 | if (err < 0) \ | ||
130 | { \ | ||
131 | fprintf(stderr,"\n[ERR] Error sending control message (%d, %s)\n", err, usb_strerror()); \ | ||
132 | return -1; \ | ||
133 | } | ||
134 | |||
135 | #define SEND_DATA(ptr, size) err = usb_bulk_write(dh, USB_ENDPOINT_OUT | EP_BULK_TO, ptr, size, TOUT); \ | ||
136 | if (err != len) \ | ||
137 | { \ | ||
138 | fprintf(stderr,"\n[ERR] Error writing data\n"); \ | ||
139 | fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \ | ||
140 | return -1; \ | ||
141 | } | ||
142 | |||
143 | #define GET_DATA(ptr, size) err = usb_bulk_read(dh, USB_ENDPOINT_IN | EP_BULK_TO, ptr, size, TOUT); \ | ||
144 | if (err != size) \ | ||
145 | { \ | ||
146 | fprintf(stderr,"\n[ERR] Error writing data\n"); \ | ||
147 | fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \ | ||
148 | return -1; \ | ||
149 | } | ||
150 | |||
151 | int upload_app(usb_dev_handle* dh, int address, unsigned char* p, int len) | ||
152 | { | ||
153 | int err; | ||
154 | char buf[8]; | ||
155 | unsigned char* tmp_buf; | ||
156 | |||
157 | fprintf(stderr, "[INFO] GET_CPU_INFO: "); | ||
158 | GET_CPU_INFO(buf); | ||
159 | buf[8] = 0; | ||
160 | fprintf(stderr, "%s\n", buf); | ||
161 | |||
162 | fprintf(stderr, "[INFO] SET_DATA_ADDRESS to 0x%x...", address); | ||
163 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
164 | fprintf(stderr, " Done!\n"); | ||
165 | |||
166 | fprintf(stderr, "[INFO] Sending data..."); | ||
167 | /* Must not split the file in several packages! */ | ||
168 | SEND_DATA(p, len); | ||
169 | fprintf(stderr, " Done!\n"); | ||
170 | |||
171 | fprintf(stderr, "[INFO] Verifying data..."); | ||
172 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
173 | SEND_COMMAND(VR_SET_DATA_LENGTH, len); | ||
174 | tmp_buf = malloc(len); | ||
175 | if (tmp_buf == NULL) | ||
176 | { | ||
177 | fprintf(stderr, "\n[ERR] Could not allocate memory.\n"); | ||
178 | return -1; | ||
179 | } | ||
180 | GET_DATA(tmp_buf, len); | ||
181 | if (memcmp(tmp_buf, p, len) != 0) | ||
182 | { | ||
183 | fprintf(stderr, "\n[ERR] Sent data isn't the same as received data...\n"); | ||
184 | free(tmp_buf); | ||
185 | return -1; | ||
186 | } | ||
187 | free(tmp_buf); | ||
188 | fprintf(stderr, " Done !\n"); | ||
189 | |||
190 | fprintf(stderr, "[INFO] Booting device..."); | ||
191 | SEND_COMMAND(VR_PROGRAM_START1, address); | ||
192 | fprintf(stderr, " Done!\n"); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | int read_data(usb_dev_handle* dh, int address, unsigned char *p, int len) | ||
198 | { | ||
199 | int err; | ||
200 | char buf[8]; | ||
201 | |||
202 | fprintf(stderr, "[INFO] GET_CPU_INFO: "); | ||
203 | GET_CPU_INFO(buf); | ||
204 | buf[8] = 0; | ||
205 | fprintf(stderr, "%s\n", buf); | ||
206 | |||
207 | fprintf(stderr, "[INFO] Reading data..."); | ||
208 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
209 | SEND_COMMAND(VR_SET_DATA_LENGTH, len); | ||
210 | GET_DATA(p, len); | ||
211 | fprintf(stderr, " Done!\n"); | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | unsigned int read_reg(usb_dev_handle* dh, int address) | ||
216 | { | ||
217 | int err; | ||
218 | unsigned char buf[4]; | ||
219 | |||
220 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
221 | SEND_COMMAND(VR_SET_DATA_LENGTH, 4); | ||
222 | GET_DATA(buf, 4); | ||
223 | |||
224 | return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
225 | } | ||
226 | |||
227 | #define TEST(m) fprintf(stderr, "%s -> %x\n", #m, read_reg(dh, m)); | ||
228 | int test_device(usb_dev_handle* dh) | ||
229 | { | ||
230 | TEST(INTC_ISR); | ||
231 | TEST(INTC_IMR); | ||
232 | TEST(INTC_IMSR); | ||
233 | TEST(INTC_IMCR); | ||
234 | TEST(INTC_IPR); | ||
235 | |||
236 | fprintf(stderr, "\n"); | ||
237 | TEST(RTC_RCR); | ||
238 | TEST(RTC_RSR); | ||
239 | TEST(RTC_RSAR); | ||
240 | TEST(RTC_RGR); | ||
241 | TEST(RTC_HCR); | ||
242 | TEST(RTC_RCR); | ||
243 | TEST(RTC_HWFCR); | ||
244 | TEST(RTC_HRCR); | ||
245 | TEST(RTC_HWCR); | ||
246 | TEST(RTC_HWSR); | ||
247 | |||
248 | fprintf(stderr, "\n"); | ||
249 | TEST(GPIO_PXPIN(0)); | ||
250 | TEST(GPIO_PXPIN(1)); | ||
251 | TEST(GPIO_PXPIN(2)); | ||
252 | TEST(GPIO_PXPIN(3)); | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | void jzconnect(int address, unsigned char* buf, int len, int func) | ||
257 | { | ||
258 | struct usb_bus *bus; | ||
259 | struct usb_device *tmp_dev; | ||
260 | struct usb_device *dev = NULL; | ||
261 | usb_dev_handle *dh; | ||
262 | int err; | ||
263 | |||
264 | fprintf(stderr,"[INFO] Searching for device...\n"); | ||
265 | |||
266 | usb_init(); | ||
267 | if(usb_find_busses() < 0) | ||
268 | { | ||
269 | fprintf(stderr, "[ERR] Could not find any USB busses.\n"); | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | if (usb_find_devices() < 0) | ||
274 | { | ||
275 | fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n"); | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | for (bus = usb_get_busses(); bus; bus = bus->next) | ||
280 | { | ||
281 | for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) | ||
282 | { | ||
283 | //printf("Found Vendor %04x Product %04x\n",tmp_dev->descriptor.idVendor, tmp_dev->descriptor.idProduct); | ||
284 | if (tmp_dev->descriptor.idVendor == VID && | ||
285 | tmp_dev->descriptor.idProduct == PID) | ||
286 | { | ||
287 | dev = tmp_dev; | ||
288 | goto found; | ||
289 | |||
290 | } | ||
291 | } | ||
292 | } | ||
293 | |||
294 | if (dev == NULL) | ||
295 | { | ||
296 | fprintf(stderr, "[ERR] Device not found.\n"); | ||
297 | fprintf(stderr, "[ERR] Ensure your device is in USB boot mode and run usbtool again.\n"); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | found: | ||
302 | if ( (dh = usb_open(dev)) == NULL) | ||
303 | { | ||
304 | fprintf(stderr,"[ERR] Unable to open device.\n"); | ||
305 | return; | ||
306 | } | ||
307 | |||
308 | err = usb_set_configuration(dh, 1); | ||
309 | |||
310 | if (err < 0) | ||
311 | { | ||
312 | fprintf(stderr, "[ERR] usb_set_configuration failed (%d, %s)\n", err, usb_strerror()); | ||
313 | usb_close(dh); | ||
314 | return; | ||
315 | } | ||
316 | |||
317 | /* "must be called" written in the libusb documentation */ | ||
318 | err = usb_claim_interface(dh, 0); | ||
319 | if (err < 0) | ||
320 | { | ||
321 | fprintf(stderr, "[ERR] Unable to claim interface (%d, %s)\n", err, usb_strerror()); | ||
322 | usb_close(dh); | ||
323 | return; | ||
324 | } | ||
325 | |||
326 | fprintf(stderr,"[INFO] Found device, uploading application.\n"); | ||
327 | |||
328 | /* Now we can transfer the application to the device. */ | ||
329 | |||
330 | switch(func) | ||
331 | { | ||
332 | case 1: | ||
333 | err = upload_app(dh, address, buf, len); | ||
334 | break; | ||
335 | case 2: | ||
336 | err = read_data(dh, address, buf, len); | ||
337 | break; | ||
338 | case 3: | ||
339 | err = test_device(dh); | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | /* release claimed interface */ | ||
344 | usb_release_interface(dh, 0); | ||
345 | |||
346 | usb_close(dh); | ||
347 | } | ||
348 | |||
349 | int filesize(FILE* fd) | ||
350 | { | ||
351 | int tmp; | ||
352 | tmp = fseek(fd, 0, SEEK_END); | ||
353 | fseek(fd, 0, SEEK_SET); | ||
354 | return tmp; | ||
355 | } | ||
356 | |||
357 | void print_usage(void) | ||
358 | { | ||
359 | #ifdef _WIN32 | ||
360 | fprintf(stderr, "Usage: usbtool.exe [CMD] [FILE] [ADDRESS] [LEN]\n"); | ||
361 | #else | ||
362 | fprintf(stderr, "Usage: usbtool [CMD] [FILE] [ADDRESS] [LEN]\n"); | ||
363 | #endif | ||
364 | fprintf(stderr, "\t[ADDRESS] has to be in 0xHEXADECIMAL format\n"); | ||
365 | fprintf(stderr, "\t[CMD]:\n\t\t1 -> upload file to specified address and boot from it\n\t\t2 -> read data from [ADDRESS] with length [LEN] to [FILE]\n"); | ||
366 | fprintf(stderr, "\t\t3 -> read device status\n"); | ||
367 | #ifdef _WIN32 | ||
368 | fprintf(stderr, "\nExample:\n\t usbtool.exe 1 fw.bin 0x80000000"); | ||
369 | fprintf(stderr, "\n\t usbtool.exe 2 save.bin 0x81000000 1024"); | ||
370 | #else | ||
371 | fprintf(stderr, "\nExample:\n\t usbtool 1 fw.bin 0x80000000"); | ||
372 | fprintf(stderr, "\n\t usbtool 2 save.bin 0x81000000 1024"); | ||
373 | #endif | ||
374 | } | ||
375 | |||
376 | int main(int argc, char* argv[]) | ||
377 | { | ||
378 | unsigned char* buf; | ||
379 | int n, len, address, cmd=0; | ||
380 | FILE* fd; | ||
381 | |||
382 | fprintf(stderr, "USBtool v" VERSION " - (C) 2008 Maurus Cuelenaere\n"); | ||
383 | fprintf(stderr, "This is free software; see the source for copying conditions. There is NO\n"); | ||
384 | fprintf(stderr, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); | ||
385 | |||
386 | if(argc > 1) | ||
387 | sscanf(argv[1], "%d", &cmd); | ||
388 | switch(cmd) | ||
389 | { | ||
390 | case 1: | ||
391 | if (sscanf(argv[3], "0x%x", &address) <= 0) | ||
392 | { | ||
393 | print_usage(); | ||
394 | return -1; | ||
395 | } | ||
396 | |||
397 | fd = fopen(argv[2], "rb"); | ||
398 | if (fd < 0) | ||
399 | { | ||
400 | fprintf(stderr, "[ERR] Could not open %s\n", argv[2]); | ||
401 | return 4; | ||
402 | } | ||
403 | |||
404 | len = filesize(fd); | ||
405 | |||
406 | if (len > MAX_FIRMWARESIZE) | ||
407 | { | ||
408 | fprintf(stderr, "[ERR] Firmware file too big\n"); | ||
409 | fclose(fd); | ||
410 | return 5; | ||
411 | } | ||
412 | |||
413 | buf = malloc(len); | ||
414 | if (buf == NULL) | ||
415 | { | ||
416 | fprintf(stderr, "[ERR] Could not allocate memory.\n"); | ||
417 | fclose(fd); | ||
418 | return 6; | ||
419 | } | ||
420 | |||
421 | n = fread(buf, 1, len, fd); | ||
422 | if (n != len) | ||
423 | { | ||
424 | fprintf(stderr, "[ERR] Short read.\n"); | ||
425 | fclose(fd); | ||
426 | return 7; | ||
427 | } | ||
428 | fclose(fd); | ||
429 | |||
430 | jzconnect(address, buf, len, 1); | ||
431 | break; | ||
432 | case 2: | ||
433 | if (sscanf(argv[3], "0x%x", &address) <= 0) | ||
434 | { | ||
435 | print_usage(); | ||
436 | return -1; | ||
437 | } | ||
438 | |||
439 | fd = fopen(argv[2], "wb"); | ||
440 | if (fd < 0) | ||
441 | { | ||
442 | fprintf(stderr, "[ERR] Could not open %s\n", argv[2]); | ||
443 | return 4; | ||
444 | } | ||
445 | |||
446 | sscanf(argv[4], "%d", &len); | ||
447 | |||
448 | buf = malloc(len); | ||
449 | if (buf == NULL) | ||
450 | { | ||
451 | fprintf(stderr, "[ERR] Could not allocate memory.\n"); | ||
452 | fclose(fd); | ||
453 | return 6; | ||
454 | } | ||
455 | |||
456 | jzconnect(address, buf, len, 2); | ||
457 | |||
458 | n = fwrite(buf, 1, len, fd); | ||
459 | if (n != len) | ||
460 | { | ||
461 | fprintf(stderr, "[ERR] Short write.\n"); | ||
462 | fclose(fd); | ||
463 | return 7; | ||
464 | } | ||
465 | fclose(fd); | ||
466 | break; | ||
467 | case 3: | ||
468 | jzconnect(address, NULL, 0, 3); | ||
469 | break; | ||
470 | default: | ||
471 | print_usage(); | ||
472 | return 1; | ||
473 | break; | ||
474 | } | ||
475 | |||
476 | return 0; | ||
477 | } | ||