blob: b1aa198d23d82dced379326d4972cc9cab469347 [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 Cuelenaerec8bdcbf2008-08-07 10:24:11 +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);\
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000131 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 Cuelenaerec8bdcbf2008-08-07 10:24:11 +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
Maurus Cuelenaerec8bdcbf2008-08-07 10:24:11 +0000144#define SEND_DATA(ptr, size) err = usb_bulk_write(dh, USB_ENDPOINT_OUT | EP_BULK_TO, ((char*)(ptr)), (size), TOUT); \
145 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
Maurus Cuelenaerec8bdcbf2008-08-07 10:24:11 +0000152#define GET_DATA(ptr, size) err = usb_bulk_read(dh, USB_ENDPOINT_IN | EP_BULK_TO, ((char*)(ptr)), (size), TOUT); \
153 if (err != (size)) \
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000154 { \
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));
Maurus Cuelenaere6fd40a52008-07-03 12:17:56 +0000202 SEND_COMMAND((stage2 ? VR_PROGRAM_START2 : VR_PROGRAM_START1), address );
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");
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000365 if (fd == NULL)
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000366 {
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); \
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000400 if(fsize == 0) \
401 return -1; \
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000402 fprintf(stderr, "[INFO] Sending file %s: %d bytes...", a, fsize); \
403 SEND_DATA(buffer, fsize); \
404 free(buffer); \
405 fprintf(stderr, " Done!\n");
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000406#define _VERIFY_DATA(a,c) fprintf(stderr, "[INFO] Verifying data (%s)...", a); \
407 fsize = read_file(a, &buffer); \
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000408 if(fsize == 0) \
409 return -1; \
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000410 buffer2 = (unsigned char*)malloc(fsize); \
411 SEND_COMMAND(VR_SET_DATA_ADDRESS, c); \
412 SEND_COMMAND(VR_SET_DATA_LENGTH, fsize); \
413 GET_DATA(buffer2, fsize); \
414 if(memcmp(buffer, buffer2, fsize) != 0) \
415 fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n"); \
416 else \
417 fprintf(stderr, " Done!\n"); \
418 free(buffer); \
419 free(buffer2);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000420#define _STAGE1(a) fprintf(stderr, "[INFO] Stage 1 at 0x%x\n", a); \
421 SEND_COMMAND(VR_PROGRAM_START1, a);
422#define _STAGE2(a) fprintf(stderr, "[INFO] Stage 2 at 0x%x\n", a); \
423 SEND_COMMAND(VR_PROGRAM_START2, a);
424#define _FLUSH fprintf(stderr, "[INFO] Flushing caches...\n"); \
425 SEND_COMMAND(VR_FLUSH_CACHES, 0);
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000426#ifdef _WIN32
427 #define _SLEEP(x) Sleep(x*1000);
428#else
429 #define _SLEEP(x) sleep(x);
430#endif
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000431int mimic_of(usb_dev_handle *dh, bool vx767)
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000432{
433 int err, fsize;
434 unsigned char *buffer, *buffer2;
435 char cpu[8];
436
437 fprintf(stderr, "[INFO] Start!\n");
438 _GET_CPU;
439 _SET_ADDR(0x8000 << 16);
440 _SEND_FILE("1.bin");
441 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000442 _VERIFY_DATA("1.bin", 0x8000 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000443 _STAGE1(0x8000 << 16);
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000444 _SLEEP(3);
445 _VERIFY_DATA("2.bin", 0xB3020060);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000446 _GET_CPU;
447 _GET_CPU;
448 _FLUSH;
449 _GET_CPU;
450 _GET_CPU;
451 _SET_ADDR(0x8000 << 16);
452 _SEND_FILE("3.bin");
453 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000454 _VERIFY_DATA("3.bin", 0x8000 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000455 _GET_CPU;
456 _FLUSH;
457 _GET_CPU;
458 _GET_CPU;
459 _SET_ADDR(0x80D0 << 16);
460 _SEND_FILE("4.bin");
461 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000462 _VERIFY_DATA("4.bin", 0x80D0 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000463 _GET_CPU;
464 _FLUSH;
465 _GET_CPU;
466 _GET_CPU;
467 _SET_ADDR(0x80E0 << 16);
468 _SEND_FILE("5.bin");
469 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000470 _VERIFY_DATA("5.bin", 0x80E0 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000471 _GET_CPU;
472 _FLUSH;
473 _GET_CPU;
474 _GET_CPU;
475 _SET_ADDR(0x80004000);
476 _SEND_FILE("6.bin");
477 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000478 _VERIFY_DATA("6.bin", 0x80004000);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000479 _GET_CPU;
480 _FLUSH;
481 _GET_CPU;
482 _GET_CPU;
483 _SET_ADDR(0x80FD << 16);
484 _SEND_FILE("7.bin");
485 _GET_CPU;
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000486 _VERIFY_DATA("7.bin", 0x80FD << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000487 _GET_CPU;
488 _FLUSH;
489 _GET_CPU;
490 _STAGE2(0x80FD0004);
Maurus Cuelenaere19e58142008-06-25 21:40:48 +0000491 _VERIFY_DATA("8.bin", 0x80004004);
492 _VERIFY_DATA("9.bin", 0x80004008);
493 _SLEEP(2);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000494 _GET_CPU;
495 _SET_ADDR(0x80E0 << 16);
Maurus Cuelenaere0a359762008-07-30 10:19:33 +0000496 _SEND_FILE("onda.bin");
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000497 _GET_CPU;
Maurus Cuelenaere0a359762008-07-30 10:19:33 +0000498 _VERIFY_DATA("onda.bin", 0x80E0 << 16);
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000499 _GET_CPU;
500 _FLUSH;
501 _GET_CPU;
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000502 if(vx767)
503 {
504 _STAGE2(0x80E10008);
505 }
506 else
507 {
508 _STAGE2(0x80E00008);
509 }
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000510 fprintf(stderr, "[INFO] Done!\n");
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000511 return 0;
512}
513
Maurus Cuelenaere606c7982008-08-24 21:18:22 +0000514#define SEND_NAND_COMMAND(cs, cmd, option) SEND_COMMAND(VR_NAND_OPS, ((cmd&0xF)|((cs&0xFF)<<4)|((option&0xFF)<<12)) );
515#define LENGTH 1024*1024*5
516int nand_dump(usb_dev_handle *dh)
517{
518 int err;
519 unsigned int n;
520 FILE *fd;
521 unsigned char* buffer;
522
523 fd = fopen("nand_dump.bin", "wb");
524 if (fd == NULL)
525 {
526 fprintf(stderr, "[ERR] Could not open nand_dump.bin\n");
527 return 0;
528 }
529
530 buffer = (unsigned char*)malloc(LENGTH);
531 if (buffer == NULL)
532 {
533 fprintf(stderr, "[ERR] Could not allocate memory.\n");
534 fclose(fd);
535 return 0;
536 }
537 memset(buffer, 0, LENGTH);
538
539 SEND_NAND_COMMAND(0, NAND_INIT, 0);
540 /*
541 fprintf(stderr, "[INFO] Querying NAND...\n");
542 SEND_NAND_COMMAND(0, NAND_QUERY, 0);
543 GET_DATA(buffer, 4);
544 printf("[INFO] %x %x %x %x\n", buffer[0], buffer[1], buffer[2], buffer[3]);
545 */
546 SEND_COMMAND(VR_SET_DATA_ADDRESS, 0);
547 SEND_COMMAND(VR_SET_DATA_LENGTH, LENGTH);
548 SEND_NAND_COMMAND(0, NAND_READ, NO_OOB);
549
550 fprintf(stderr, "[INFO] Reading data...\n");
551 err = usb_bulk_read(dh, USB_ENDPOINT_IN | EP_BULK_TO, (char*)buffer, LENGTH, TOUT);
Maurus Cuelenaerec9e31fb2008-09-01 19:56:12 +0000552 if (err != LENGTH)
Maurus Cuelenaere606c7982008-08-24 21:18:22 +0000553 {
554 fprintf(stderr,"\n[ERR] Error writing data\n");
555 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
556 return -1;
557 }
558
559 n = fwrite(buffer, 1, LENGTH, fd);
560 if (n != LENGTH)
561 {
562 fprintf(stderr, "[ERR] Short write.\n");
563 fclose(fd);
564 free(buffer);
565 return 0;
566 }
567 fclose(fd);
568 free(buffer);
569
570 return n;
571}
572#undef LENGTH
573
574#define LENGTH 0x1000*16
575int rom_dump(usb_dev_handle *dh)
576{
577 int err;
578 unsigned int n;
579 FILE *fd;
580 unsigned char* buffer;
581
582 fd = fopen("rom_dump.bin", "wb");
583 if (fd == NULL)
584 {
585 fprintf(stderr, "[ERR] Could not open rom_dump.bin\n");
586 return 0;
587 }
588
589 buffer = (unsigned char*)malloc(LENGTH);
590 if (buffer == NULL)
591 {
592 fprintf(stderr, "[ERR] Could not allocate memory.\n");
593 fclose(fd);
594 return 0;
595 }
596 memset(buffer, 0, LENGTH);
597
598 SEND_COMMAND(VR_SET_DATA_ADDRESS, 0x1FC00000);
599 SEND_COMMAND(VR_SET_DATA_LENGTH, LENGTH);
600
601 fprintf(stderr, "[INFO] Reading data...\n");
602 err = usb_bulk_read(dh, USB_ENDPOINT_IN | EP_BULK_TO, (char*)buffer, LENGTH, TOUT);
Maurus Cuelenaerec9e31fb2008-09-01 19:56:12 +0000603 if (err != LENGTH)
Maurus Cuelenaere606c7982008-08-24 21:18:22 +0000604 {
605 fprintf(stderr,"\n[ERR] Error writing data\n");
606 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
607 return -1;
608 }
609
610 n = fwrite(buffer, 1, LENGTH, fd);
611 if (n != LENGTH)
612 {
613 fprintf(stderr, "[ERR] Short write.\n");
614 fclose(fd);
615 free(buffer);
616 return 0;
617 }
618 fclose(fd);
619 free(buffer);
620
621 return n;
622}
623
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000624int jzconnect(int address, unsigned char* buf, int len, int func)
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000625{
626 struct usb_bus *bus;
627 struct usb_device *tmp_dev;
628 struct usb_device *dev = NULL;
629 usb_dev_handle *dh;
630 int err;
631
632 fprintf(stderr,"[INFO] Searching for device...\n");
633
634 usb_init();
635 if(usb_find_busses() < 0)
636 {
637 fprintf(stderr, "[ERR] Could not find any USB busses.\n");
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000638 return -2;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000639 }
640
641 if (usb_find_devices() < 0)
642 {
643 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n");
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000644 return -3;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000645 }
646
647 for (bus = usb_get_busses(); bus; bus = bus->next)
648 {
649 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next)
650 {
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000651 if (tmp_dev->descriptor.idVendor == VID &&
652 tmp_dev->descriptor.idProduct == PID)
653 {
654 dev = tmp_dev;
655 goto found;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000656 }
657 }
658 }
659
660 if (dev == NULL)
661 {
662 fprintf(stderr, "[ERR] Device not found.\n");
663 fprintf(stderr, "[ERR] Ensure your device is in USB boot mode and run usbtool again.\n");
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000664 return -4;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000665 }
666
667found:
668 if ( (dh = usb_open(dev)) == NULL)
669 {
670 fprintf(stderr,"[ERR] Unable to open device.\n");
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000671 return -5;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000672 }
673
Maurus Cuelenaere72bc4e32008-08-12 16:55:59 +0000674/* usb_set_configuration() calls are already done in Linux */
675#ifdef _WIN32
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000676 err = usb_set_configuration(dh, 1);
677
678 if (err < 0)
679 {
680 fprintf(stderr, "[ERR] usb_set_configuration failed (%d, %s)\n", err, usb_strerror());
681 usb_close(dh);
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000682 return -6;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000683 }
Maurus Cuelenaere72bc4e32008-08-12 16:55:59 +0000684#endif
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000685
686 /* "must be called" written in the libusb documentation */
687 err = usb_claim_interface(dh, 0);
688 if (err < 0)
689 {
690 fprintf(stderr, "[ERR] Unable to claim interface (%d, %s)\n", err, usb_strerror());
691 usb_close(dh);
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000692 return -7;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000693 }
694
695 fprintf(stderr,"[INFO] Found device, uploading application.\n");
696
697 /* Now we can transfer the application to the device. */
698
699 switch(func)
700 {
701 case 1:
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000702 case 5:
703 err = upload_app(dh, address, buf, len, (func == 5));
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000704 break;
705 case 2:
706 err = read_data(dh, address, buf, len);
707 break;
708 case 3:
709 err = test_device(dh);
710 break;
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000711 case 4:
712 err = probe_device(dh);
713 break;
714 case 6:
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000715 case 7:
716 err = mimic_of(dh, (func == 7));
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000717 break;
Maurus Cuelenaere606c7982008-08-24 21:18:22 +0000718 case 8:
719 err = nand_dump(dh);
720 break;
721 case 9:
722 err = rom_dump(dh);
723 break;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000724 }
725
726 /* release claimed interface */
727 usb_release_interface(dh, 0);
728
729 usb_close(dh);
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000730
731 return err;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000732}
733
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000734void print_usage(void)
735{
736#ifdef _WIN32
737 fprintf(stderr, "Usage: usbtool.exe [CMD] [FILE] [ADDRESS] [LEN]\n");
738#else
739 fprintf(stderr, "Usage: usbtool [CMD] [FILE] [ADDRESS] [LEN]\n");
740#endif
741 fprintf(stderr, "\t[ADDRESS] has to be in 0xHEXADECIMAL format\n");
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000742 fprintf(stderr, "\t[CMD]:\n");
743 fprintf(stderr, "\t\t1 -> upload file to specified address and boot from it\n");
744 fprintf(stderr, "\t\t2 -> read data from [ADDRESS] with length [LEN] to [FILE]\n");
745 fprintf(stderr, "\t\t3 -> read device status\n");
746 fprintf(stderr, "\t\t4 -> probe keys (only Onda VX747)\n");
747 fprintf(stderr, "\t\t5 -> same as 1 but do a stage 2 boot\n");
748 fprintf(stderr, "\t\t6 -> mimic VX747 OF fw recovery\n");
749 fprintf(stderr, "\t\t7 -> mimic VX767 OF fw recovery\n");
Maurus Cuelenaere606c7982008-08-24 21:18:22 +0000750 fprintf(stderr, "\t\t8 -> do a NAND dump\n");
751 fprintf(stderr, "\t\t9 -> do a ROM dump\n");
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000752#ifdef _WIN32
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000753 fprintf(stderr, "\nExample:\n\t usbtool.exe 1 fw.bin 0x80000000\n");
754 fprintf(stderr, "\t usbtool.exe 2 save.bin 0x81000000 1024\n");
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000755#else
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000756 fprintf(stderr, "\nExample:\n\t usbtool 1 fw.bin 0x80000000\n");
757 fprintf(stderr, "\t usbtool 2 save.bin 0x81000000 1024\n");
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000758#endif
759}
760
761int main(int argc, char* argv[])
762{
763 unsigned char* buf;
764 int n, len, address, cmd=0;
765 FILE* fd;
766
767 fprintf(stderr, "USBtool v" VERSION " - (C) 2008 Maurus Cuelenaere\n");
768 fprintf(stderr, "This is free software; see the source for copying conditions. There is NO\n");
769 fprintf(stderr, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
770
771 if(argc > 1)
772 sscanf(argv[1], "%d", &cmd);
773 switch(cmd)
774 {
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000775 case 5:
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000776 case 1:
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000777 if (strcmp(argv[3], "-1") == 0)
778 address = 0x80000000;
779 else
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000780 {
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000781 if (sscanf(argv[3], "0x%x", &address) <= 0)
782 {
783 print_usage();
784 return -1;
785 }
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000786 }
787
788 fd = fopen(argv[2], "rb");
789 if (fd < 0)
790 {
791 fprintf(stderr, "[ERR] Could not open %s\n", argv[2]);
792 return 4;
793 }
794
795 len = filesize(fd);
796
797 if (len > MAX_FIRMWARESIZE)
798 {
799 fprintf(stderr, "[ERR] Firmware file too big\n");
800 fclose(fd);
801 return 5;
802 }
803
804 buf = malloc(len);
805 if (buf == NULL)
806 {
807 fprintf(stderr, "[ERR] Could not allocate memory.\n");
808 fclose(fd);
809 return 6;
810 }
811
812 n = fread(buf, 1, len, fd);
813 if (n != len)
814 {
815 fprintf(stderr, "[ERR] Short read.\n");
816 fclose(fd);
817 return 7;
818 }
819 fclose(fd);
820
Maurus Cuelenaere8f9b2932008-06-22 11:58:44 +0000821 fprintf(stderr, "[INFO] File size: %d bytes\n", n);
822
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000823 return jzconnect(address, buf, len, cmd);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000824 break;
825 case 2:
826 if (sscanf(argv[3], "0x%x", &address) <= 0)
827 {
828 print_usage();
829 return -1;
830 }
831
832 fd = fopen(argv[2], "wb");
833 if (fd < 0)
834 {
835 fprintf(stderr, "[ERR] Could not open %s\n", argv[2]);
836 return 4;
837 }
838
839 sscanf(argv[4], "%d", &len);
840
841 buf = malloc(len);
842 if (buf == NULL)
843 {
844 fprintf(stderr, "[ERR] Could not allocate memory.\n");
845 fclose(fd);
846 return 6;
847 }
848
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000849 int err = jzconnect(address, buf, len, 2);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000850
851 n = fwrite(buf, 1, len, fd);
852 if (n != len)
853 {
854 fprintf(stderr, "[ERR] Short write.\n");
855 fclose(fd);
856 return 7;
857 }
858 fclose(fd);
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000859
860 return err;
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000861 break;
862 case 3:
Maurus Cuelenaere349c14c2008-06-24 20:14:00 +0000863 case 4:
864 case 6:
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000865 case 7:
Maurus Cuelenaere606c7982008-08-24 21:18:22 +0000866 case 8:
867 case 9:
Maurus Cuelenaere438e3632008-08-12 12:58:24 +0000868 return jzconnect(address, NULL, 0, cmd);
Maurus Cuelenaere00daa7c2008-06-21 17:18:24 +0000869 break;
870 default:
871 print_usage();
872 return 1;
873 break;
874 }
875
876 return 0;
877}