blob: 6d670254e4938a8a1ca2a44a6a2883b0e20124df [file] [log] [blame]
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +00001/***************************************************************************
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 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000020 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +000024 *
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
26 * KIND, either express or implied.
27 *
28 ****************************************************************************/
29
30#include <stdio.h>
31#include <inttypes.h>
32#include <usb.h>
33#include <string.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include "jz4740.h"
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +000039#include <stdbool.h>
40#include <unistd.h>
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +000041
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +000042#define VERSION "0.3"
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +000043
44#define MAX_FIRMWARESIZE (64*1024*1024) /* Arbitrary limit (for safety) */
45
46/* For win32 compatibility: */
47#ifndef O_BINARY
48#define O_BINARY 0
49#endif
50
51/* USB IDs for USB Boot Mode */
52#define VID 0x601A
53#define PID 0x4740
54
55#define EP_BULK_TO 0x01
56#define TOUT 5000
57
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +000058enum 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
72enum NOR_OPS_TYPE
73{
74 NOR_INIT = 0,
75 NOR_QUERY,
76 NOR_WRITE,
77 NOR_ERASE_CHIP,
78 NOR_ERASE_SECTOR
79};
80
81enum NOR_FLASH_TYPE
82{
83 NOR_AM29 = 0,
84 NOR_SST28,
85 NOR_SST39x16,
86 NOR_SST39x8
87};
88
89enum 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
102enum SDRAM_OPS_TYPE
103{
104 SDRAM_LOAD,
105
106};
107
108enum DATA_STRUCTURE_OB
109{
110 DS_flash_info ,
111 DS_hand
112};
113
114enum OPTION
115{
116 OOB_ECC,
117 OOB_NO_ECC,
118 NO_OOB,
119};
120
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000121int filesize(FILE* fd)
122{
123 int tmp;
124 fseek(fd, 0, SEEK_END);
125 tmp = ftell(fd);
126 fseek(fd, 0, SEEK_SET);
127 return tmp;
128}
129
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000130#define SEND_COMMAND(cmd, arg) err = usb_control_msg(dh, USB_ENDPOINT_OUT | USB_TYPE_VENDOR, cmd, arg>>16, arg&0xFFFF, NULL, 0, TOUT);\
131 if (err < 0) \
132 { \
133 fprintf(stderr,"\n[ERR] Error sending control message (%d, %s)\n", err, usb_strerror()); \
134 return -1; \
135 }
136
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000137#define GET_CPU_INFO(s) err = usb_control_msg(dh, USB_ENDPOINT_IN | USB_TYPE_VENDOR, VR_GET_CPU_INFO, 0, 0, s, 8, TOUT); \
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000138 if (err < 0) \
139 { \
140 fprintf(stderr,"\n[ERR] Error sending control message (%d, %s)\n", err, usb_strerror()); \
141 return -1; \
142 }
143
144#define SEND_DATA(ptr, size) err = usb_bulk_write(dh, USB_ENDPOINT_OUT | EP_BULK_TO, ptr, size, TOUT); \
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000145 if (err != size) \
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000146 { \
147 fprintf(stderr,"\n[ERR] Error writing data\n"); \
148 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \
149 return -1; \
150 }
151
152#define GET_DATA(ptr, size) err = usb_bulk_read(dh, USB_ENDPOINT_IN | EP_BULK_TO, ptr, size, TOUT); \
153 if (err != size) \
154 { \
155 fprintf(stderr,"\n[ERR] Error writing data\n"); \
156 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \
157 return -1; \
158 }
159
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000160int upload_app(usb_dev_handle* dh, int address, unsigned char* p, int len, bool stage2)
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000161{
162 int err;
163 char buf[8];
164 unsigned char* tmp_buf;
165
166 fprintf(stderr, "[INFO] GET_CPU_INFO: ");
167 GET_CPU_INFO(buf);
168 buf[8] = 0;
169 fprintf(stderr, "%s\n", buf);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000170#if 0
171 fprintf(stderr, "[INFO] Flushing cache...");
172 SEND_COMMAND(VR_FLUSH_CACHES, 0);
173 fprintf(stderr, " Done!\n");
174#endif
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000175
176 fprintf(stderr, "[INFO] SET_DATA_ADDRESS to 0x%x...", address);
177 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
178 fprintf(stderr, " Done!\n");
179
180 fprintf(stderr, "[INFO] Sending data...");
181 /* Must not split the file in several packages! */
182 SEND_DATA(p, len);
183 fprintf(stderr, " Done!\n");
184
185 fprintf(stderr, "[INFO] Verifying data...");
186 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
187 SEND_COMMAND(VR_SET_DATA_LENGTH, len);
188 tmp_buf = malloc(len);
189 if (tmp_buf == NULL)
190 {
191 fprintf(stderr, "\n[ERR] Could not allocate memory.\n");
192 return -1;
193 }
194 GET_DATA(tmp_buf, len);
195 if (memcmp(tmp_buf, p, len) != 0)
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000196 fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n");
197 else
198 fprintf(stderr, " Done!\n");
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000199 free(tmp_buf);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000200
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000201 fprintf(stderr, "[INFO] Booting device [STAGE%d]...", (stage2 ? 2 : 1));
202 SEND_COMMAND((stage2 ? VR_PROGRAM_START2 : VR_PROGRAM_START1), (address+(stage2 ? 8 : 0)) );
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000203 fprintf(stderr, " Done!\n");
204
205 return 0;
206}
207
208int read_data(usb_dev_handle* dh, int address, unsigned char *p, int len)
209{
210 int err;
211 char buf[8];
212
213 fprintf(stderr, "[INFO] GET_CPU_INFO: ");
214 GET_CPU_INFO(buf);
215 buf[8] = 0;
216 fprintf(stderr, "%s\n", buf);
217
218 fprintf(stderr, "[INFO] Reading data...");
219 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
220 SEND_COMMAND(VR_SET_DATA_LENGTH, len);
221 GET_DATA(p, len);
222 fprintf(stderr, " Done!\n");
223 return 0;
224}
225
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000226unsigned int read_reg(usb_dev_handle* dh, int address, int size)
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000227{
228 int err;
229 unsigned char buf[4];
230
231 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000232 SEND_COMMAND(VR_SET_DATA_LENGTH, size);
233 GET_DATA(buf, size);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000234
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000235 if(size == 1)
236 return buf[0];
237 else if(size == 2)
238 return (buf[1] << 8) | buf[0];
239 else if(size == 4)
240 return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
241 else
242 return 0;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000243}
244
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000245int set_reg(usb_dev_handle* dh, int address, unsigned int val, int size)
246{
247 int err, i;
248 unsigned char buf[4];
249
250 buf[0] = val & 0xff;
251 if(i > 1)
252 {
253 buf[1] = (val >> 8) & 0xff;
254 if(i > 2)
255 {
256 buf[2] = (val >> 16) & 0xff;
257 buf[3] = (val >> 24) & 0xff;
258 }
259 }
260
261 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
262 SEND_DATA(buf, size);
263
264 return 0;
265}
266#define or_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) | (val)), size);
267#define and_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) & (val)), size);
268#define bc_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) & ~(val)), size);
269#define xor_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) ^ (val)), size);
270
271#define TEST(m, size) fprintf(stderr, "%s -> %x\n", #m, read_reg(dh, m, size));
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000272int test_device(usb_dev_handle* dh)
273{
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000274 TEST(INTC_ISR, 4);
275 TEST(INTC_IMR, 4);
276 TEST(INTC_IMSR, 4);
277 TEST(INTC_IMCR, 4);
278 TEST(INTC_IPR, 4);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000279
280 fprintf(stderr, "\n");
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000281 TEST(RTC_RCR, 4);
282 TEST(RTC_RSR, 4);
283 TEST(RTC_RSAR, 4);
284 TEST(RTC_RGR, 4);
285 TEST(RTC_HCR, 4);
286 TEST(RTC_RCR, 4);
287 TEST(RTC_HWFCR, 4);
288 TEST(RTC_HRCR, 4);
289 TEST(RTC_HWCR, 4);
290 TEST(RTC_HWSR, 4);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000291
292 fprintf(stderr, "\n");
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000293 TEST(GPIO_PXPIN(0), 4);
294 TEST(GPIO_PXPIN(1), 4);
295 TEST(GPIO_PXPIN(2), 4);
296 TEST(GPIO_PXPIN(3), 4);
297
298 fprintf(stderr, "\n");
299 TEST(CPM_CLKGR, 4);
300
301 fprintf(stderr, "\n");
302 //or_reg(dh, SADC_ENA, SADC_ENA_TSEN, 1);
303 TEST(SADC_ENA, 1);
304 TEST(SADC_CTRL, 1);
305 TEST(SADC_TSDAT, 4);
306 TEST(SADC_BATDAT, 2);
307 TEST(SADC_STATE, 1);
308
309 fprintf(stderr, "\n");
310
311 TEST(SLCD_CFG, 4);
312 TEST(SLCD_CTRL, 1);
313 TEST(SLCD_STATE, 1);
314
315 return 0;
316}
317
318#define VOL_DOWN (1 << 27)
319#define VOL_UP (1 << 0)
320#define MENU (1 << 1)
321#define HOLD (1 << 16)
322#define OFF (1 << 29)
323#define MASK (VOL_DOWN|VOL_UP|MENU|HOLD|OFF)
324#define TS_MASK (SADC_STATE_PEND|SADC_STATE_PENU|SADC_STATE_TSRDY)
325int probe_device(usb_dev_handle* dh)
326{
327 int tmp;
328
329 //or_reg(dh, SADC_ENA, SADC_ENA_TSEN, 1);
330 while(1)
331 {
332 if(read_reg(dh, SADC_STATE, 1) & SADC_STATE_TSRDY)
333 {
334 printf("%x\n", read_reg(dh, SADC_TSDAT, 4));
335 or_reg(dh, SADC_CTRL, read_reg(dh, SADC_STATE, 1) & TS_MASK, 1);
336 }
337
338 tmp = read_reg(dh, GPIO_PXPIN(3), 4);
339 if(tmp < 0)
340 return tmp;
341 if(tmp ^ MASK)
342 {
343 if(!(tmp & VOL_DOWN))
344 printf("VOL_DOWN\t");
345 if(!(tmp & VOL_UP))
346 printf("VOL_UP\t");
347 if(!(tmp & MENU))
348 printf("MENU\t");
349 if(!(tmp & OFF))
350 printf("OFF\t");
351 if(!(tmp & HOLD))
352 printf("HOLD\t");
353 printf("\n");
354 }
355 }
356 return 0;
357}
358
359unsigned int read_file(const char *name, unsigned char **buffer)
360{
361 FILE *fd;
362 int len, n;
363
364 fd = fopen(name, "rb");
365 if (fd < 0)
366 {
367 fprintf(stderr, "[ERR] Could not open %s\n", name);
368 return 0;
369 }
370
371 len = filesize(fd);
372
373 *buffer = (unsigned char*)malloc(len);
374 if (*buffer == NULL)
375 {
376 fprintf(stderr, "[ERR] Could not allocate memory.\n");
377 fclose(fd);
378 return 0;
379 }
380
381 n = fread(*buffer, 1, len, fd);
382 if (n != len)
383 {
384 fprintf(stderr, "[ERR] Short read.\n");
385 fclose(fd);
386 return 0;
387 }
388 fclose(fd);
389
390 return len;
391}
392#define _GET_CPU fprintf(stderr, "[INFO] GET_CPU_INFO:"); \
393 GET_CPU_INFO(cpu); \
394 cpu[8] = 0; \
395 fprintf(stderr, " %s\n", cpu);
396#define _SET_ADDR(a) fprintf(stderr, "[INFO] Set address to 0x%x...", a); \
397 SEND_COMMAND(VR_SET_DATA_ADDRESS, a); \
398 fprintf(stderr, " Done!\n");
399#define _SEND_FILE(a) fsize = read_file(a, &buffer); \
400 fprintf(stderr, "[INFO] Sending file %s: %d bytes...", a, fsize); \
401 SEND_DATA(buffer, fsize); \
402 free(buffer); \
403 fprintf(stderr, " Done!\n");
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000404#define _VERIFY_DATA(a,c) fprintf(stderr, "[INFO] Verifying data (%s)...", a); \
405 fsize = read_file(a, &buffer); \
406 buffer2 = (unsigned char*)malloc(fsize); \
407 SEND_COMMAND(VR_SET_DATA_ADDRESS, c); \
408 SEND_COMMAND(VR_SET_DATA_LENGTH, fsize); \
409 GET_DATA(buffer2, fsize); \
410 if(memcmp(buffer, buffer2, fsize) != 0) \
411 fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n"); \
412 else \
413 fprintf(stderr, " Done!\n"); \
414 free(buffer); \
415 free(buffer2);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000416#define _STAGE1(a) fprintf(stderr, "[INFO] Stage 1 at 0x%x\n", a); \
417 SEND_COMMAND(VR_PROGRAM_START1, a);
418#define _STAGE2(a) fprintf(stderr, "[INFO] Stage 2 at 0x%x\n", a); \
419 SEND_COMMAND(VR_PROGRAM_START2, a);
420#define _FLUSH fprintf(stderr, "[INFO] Flushing caches...\n"); \
421 SEND_COMMAND(VR_FLUSH_CACHES, 0);
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000422#ifdef _WIN32
423 #define _SLEEP(x) Sleep(x*1000);
424#else
425 #define _SLEEP(x) sleep(x);
426#endif
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000427int mimic_of(usb_dev_handle *dh)
428{
429 int err, fsize;
430 unsigned char *buffer, *buffer2;
431 char cpu[8];
432
433 fprintf(stderr, "[INFO] Start!\n");
434 _GET_CPU;
435 _SET_ADDR(0x8000 << 16);
436 _SEND_FILE("1.bin");
437 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000438 _VERIFY_DATA("1.bin", 0x8000 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000439 _STAGE1(0x8000 << 16);
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000440 _SLEEP(3);
441 _VERIFY_DATA("2.bin", 0xB3020060);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000442 _GET_CPU;
443 _GET_CPU;
444 _FLUSH;
445 _GET_CPU;
446 _GET_CPU;
447 _SET_ADDR(0x8000 << 16);
448 _SEND_FILE("3.bin");
449 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000450 _VERIFY_DATA("3.bin", 0x8000 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000451 _GET_CPU;
452 _FLUSH;
453 _GET_CPU;
454 _GET_CPU;
455 _SET_ADDR(0x80D0 << 16);
456 _SEND_FILE("4.bin");
457 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000458 _VERIFY_DATA("4.bin", 0x80D0 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000459 _GET_CPU;
460 _FLUSH;
461 _GET_CPU;
462 _GET_CPU;
463 _SET_ADDR(0x80E0 << 16);
464 _SEND_FILE("5.bin");
465 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000466 _VERIFY_DATA("5.bin", 0x80E0 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000467 _GET_CPU;
468 _FLUSH;
469 _GET_CPU;
470 _GET_CPU;
471 _SET_ADDR(0x80004000);
472 _SEND_FILE("6.bin");
473 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000474 _VERIFY_DATA("6.bin", 0x80004000);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000475 _GET_CPU;
476 _FLUSH;
477 _GET_CPU;
478 _GET_CPU;
479 _SET_ADDR(0x80FD << 16);
480 _SEND_FILE("7.bin");
481 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000482 _VERIFY_DATA("7.bin", 0x80FD << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000483 _GET_CPU;
484 _FLUSH;
485 _GET_CPU;
486 _STAGE2(0x80FD0004);
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000487 _VERIFY_DATA("8.bin", 0x80004004);
488 _VERIFY_DATA("9.bin", 0x80004008);
489 _SLEEP(2);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000490 _GET_CPU;
491 _SET_ADDR(0x80E0 << 16);
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000492 _SEND_FILE("10.bin");
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000493 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000494 _VERIFY_DATA("10.bin", 0x80E0 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000495 _GET_CPU;
496 _FLUSH;
497 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000498 _STAGE2(0x80e00008);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000499 fprintf(stderr, "[INFO] Done!\n");
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000500 return 0;
501}
502
503void jzconnect(int address, unsigned char* buf, int len, int func)
504{
505 struct usb_bus *bus;
506 struct usb_device *tmp_dev;
507 struct usb_device *dev = NULL;
508 usb_dev_handle *dh;
509 int err;
510
511 fprintf(stderr,"[INFO] Searching for device...\n");
512
513 usb_init();
514 if(usb_find_busses() < 0)
515 {
516 fprintf(stderr, "[ERR] Could not find any USB busses.\n");
517 return;
518 }
519
520 if (usb_find_devices() < 0)
521 {
522 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n");
523 return;
524 }
525
526 for (bus = usb_get_busses(); bus; bus = bus->next)
527 {
528 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next)
529 {
530 //printf("Found Vendor %04x Product %04x\n",tmp_dev->descriptor.idVendor, tmp_dev->descriptor.idProduct);
531 if (tmp_dev->descriptor.idVendor == VID &&
532 tmp_dev->descriptor.idProduct == PID)
533 {
534 dev = tmp_dev;
535 goto found;
536
537 }
538 }
539 }
540
541 if (dev == NULL)
542 {
543 fprintf(stderr, "[ERR] Device not found.\n");
544 fprintf(stderr, "[ERR] Ensure your device is in USB boot mode and run usbtool again.\n");
545 return;
546 }
547
548found:
549 if ( (dh = usb_open(dev)) == NULL)
550 {
551 fprintf(stderr,"[ERR] Unable to open device.\n");
552 return;
553 }
554
555 err = usb_set_configuration(dh, 1);
556
557 if (err < 0)
558 {
559 fprintf(stderr, "[ERR] usb_set_configuration failed (%d, %s)\n", err, usb_strerror());
560 usb_close(dh);
561 return;
562 }
563
564 /* "must be called" written in the libusb documentation */
565 err = usb_claim_interface(dh, 0);
566 if (err < 0)
567 {
568 fprintf(stderr, "[ERR] Unable to claim interface (%d, %s)\n", err, usb_strerror());
569 usb_close(dh);
570 return;
571 }
572
573 fprintf(stderr,"[INFO] Found device, uploading application.\n");
574
575 /* Now we can transfer the application to the device. */
576
577 switch(func)
578 {
579 case 1:
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000580 case 5:
581 err = upload_app(dh, address, buf, len, (func == 5));
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000582 break;
583 case 2:
584 err = read_data(dh, address, buf, len);
585 break;
586 case 3:
587 err = test_device(dh);
588 break;
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000589 case 4:
590 err = probe_device(dh);
591 break;
592 case 6:
593 err = mimic_of(dh);
594 break;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000595 }
596
597 /* release claimed interface */
598 usb_release_interface(dh, 0);
599
600 usb_close(dh);
601}
602
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000603void print_usage(void)
604{
605#ifdef _WIN32
606 fprintf(stderr, "Usage: usbtool.exe [CMD] [FILE] [ADDRESS] [LEN]\n");
607#else
608 fprintf(stderr, "Usage: usbtool [CMD] [FILE] [ADDRESS] [LEN]\n");
609#endif
610 fprintf(stderr, "\t[ADDRESS] has to be in 0xHEXADECIMAL format\n");
611 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");
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000612 fprintf(stderr, "\t\t3 -> read device status\n\t\t4 -> probe keys (only Onda VX747)\n");
613 fprintf(stderr, "\t\t5 -> same as 1 but do a stage 2 boot\n\t\t6 -> mimic OF fw recovery\n");
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000614#ifdef _WIN32
615 fprintf(stderr, "\nExample:\n\t usbtool.exe 1 fw.bin 0x80000000");
616 fprintf(stderr, "\n\t usbtool.exe 2 save.bin 0x81000000 1024");
617#else
618 fprintf(stderr, "\nExample:\n\t usbtool 1 fw.bin 0x80000000");
619 fprintf(stderr, "\n\t usbtool 2 save.bin 0x81000000 1024");
620#endif
621}
622
623int main(int argc, char* argv[])
624{
625 unsigned char* buf;
626 int n, len, address, cmd=0;
627 FILE* fd;
628
629 fprintf(stderr, "USBtool v" VERSION " - (C) 2008 Maurus Cuelenaere\n");
630 fprintf(stderr, "This is free software; see the source for copying conditions. There is NO\n");
631 fprintf(stderr, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
632
633 if(argc > 1)
634 sscanf(argv[1], "%d", &cmd);
635 switch(cmd)
636 {
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000637 case 5:
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000638 case 1:
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000639 if (strcmp(argv[3], "-1") == 0)
640 address = 0x80000000;
641 else
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000642 {
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000643 if (sscanf(argv[3], "0x%x", &address) <= 0)
644 {
645 print_usage();
646 return -1;
647 }
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000648 }
649
650 fd = fopen(argv[2], "rb");
651 if (fd < 0)
652 {
653 fprintf(stderr, "[ERR] Could not open %s\n", argv[2]);
654 return 4;
655 }
656
657 len = filesize(fd);
658
659 if (len > MAX_FIRMWARESIZE)
660 {
661 fprintf(stderr, "[ERR] Firmware file too big\n");
662 fclose(fd);
663 return 5;
664 }
665
666 buf = malloc(len);
667 if (buf == NULL)
668 {
669 fprintf(stderr, "[ERR] Could not allocate memory.\n");
670 fclose(fd);
671 return 6;
672 }
673
674 n = fread(buf, 1, len, fd);
675 if (n != len)
676 {
677 fprintf(stderr, "[ERR] Short read.\n");
678 fclose(fd);
679 return 7;
680 }
681 fclose(fd);
682
Maurus Cuelenaere8f9b2932008-06-22 11:58:44 +0000683 fprintf(stderr, "[INFO] File size: %d bytes\n", n);
684
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000685 jzconnect(address, buf, len, cmd);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000686 break;
687 case 2:
688 if (sscanf(argv[3], "0x%x", &address) <= 0)
689 {
690 print_usage();
691 return -1;
692 }
693
694 fd = fopen(argv[2], "wb");
695 if (fd < 0)
696 {
697 fprintf(stderr, "[ERR] Could not open %s\n", argv[2]);
698 return 4;
699 }
700
701 sscanf(argv[4], "%d", &len);
702
703 buf = malloc(len);
704 if (buf == NULL)
705 {
706 fprintf(stderr, "[ERR] Could not allocate memory.\n");
707 fclose(fd);
708 return 6;
709 }
710
711 jzconnect(address, buf, len, 2);
712
713 n = fwrite(buf, 1, len, fd);
714 if (n != len)
715 {
716 fprintf(stderr, "[ERR] Short write.\n");
717 fclose(fd);
718 return 7;
719 }
720 fclose(fd);
721 break;
722 case 3:
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000723 case 4:
724 case 6:
725 jzconnect(address, NULL, 0, cmd);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000726 break;
727 default:
728 print_usage();
729 return 1;
730 break;
731 }
732
733 return 0;
734}