summaryrefslogtreecommitdiff
path: root/utils/jz4740_tools/jz4740_usbtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/jz4740_tools/jz4740_usbtool.c')
-rwxr-xr-xutils/jz4740_tools/jz4740_usbtool.c732
1 files changed, 732 insertions, 0 deletions
diff --git a/utils/jz4740_tools/jz4740_usbtool.c b/utils/jz4740_tools/jz4740_usbtool.c
new file mode 100755
index 0000000000..4437f63675
--- /dev/null
+++ b/utils/jz4740_tools/jz4740_usbtool.c
@@ -0,0 +1,732 @@
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#include <stdbool.h>
38#include <unistd.h>
39
40#define VERSION "0.3"
41
42#define MAX_FIRMWARESIZE (64*1024*1024) /* Arbitrary limit (for safety) */
43
44/* For win32 compatibility: */
45#ifndef O_BINARY
46#define O_BINARY 0
47#endif
48
49/* USB IDs for USB Boot Mode */
50#define VID 0x601A
51#define PID 0x4740
52
53#define EP_BULK_TO 0x01
54#define TOUT 5000
55
56enum USB_JZ4740_REQUEST
57{
58 VR_GET_CPU_INFO = 0,
59 VR_SET_DATA_ADDRESS,
60 VR_SET_DATA_LENGTH,
61 VR_FLUSH_CACHES,
62 VR_PROGRAM_START1,
63 VR_PROGRAM_START2,
64 VR_NOR_OPS,
65 VR_NAND_OPS,
66 VR_SDRAM_OPS,
67 VR_CONFIGURATION
68};
69
70enum NOR_OPS_TYPE
71{
72 NOR_INIT = 0,
73 NOR_QUERY,
74 NOR_WRITE,
75 NOR_ERASE_CHIP,
76 NOR_ERASE_SECTOR
77};
78
79enum NOR_FLASH_TYPE
80{
81 NOR_AM29 = 0,
82 NOR_SST28,
83 NOR_SST39x16,
84 NOR_SST39x8
85};
86
87enum NAND_OPS_TYPE
88{
89 NAND_QUERY = 0,
90 NAND_INIT,
91 NAND_MARK_BAD,
92 NAND_READ_OOB,
93 NAND_READ_RAW,
94 NAND_ERASE,
95 NAND_READ,
96 NAND_PROGRAM,
97 NAND_READ_TO_RAM
98};
99
100enum SDRAM_OPS_TYPE
101{
102 SDRAM_LOAD,
103
104};
105
106enum DATA_STRUCTURE_OB
107{
108 DS_flash_info ,
109 DS_hand
110};
111
112enum OPTION
113{
114 OOB_ECC,
115 OOB_NO_ECC,
116 NO_OOB,
117};
118
119int filesize(FILE* fd)
120{
121 int tmp;
122 fseek(fd, 0, SEEK_END);
123 tmp = ftell(fd);
124 fseek(fd, 0, SEEK_SET);
125 return tmp;
126}
127
128#define SEND_COMMAND(cmd, arg) err = usb_control_msg(dh, USB_ENDPOINT_OUT | USB_TYPE_VENDOR, cmd, arg>>16, arg&0xFFFF, NULL, 0, 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 GET_CPU_INFO(s) err = usb_control_msg(dh, USB_ENDPOINT_IN | USB_TYPE_VENDOR, VR_GET_CPU_INFO, 0, 0, s, 8, TOUT); \
136 if (err < 0) \
137 { \
138 fprintf(stderr,"\n[ERR] Error sending control message (%d, %s)\n", err, usb_strerror()); \
139 return -1; \
140 }
141
142#define SEND_DATA(ptr, size) err = usb_bulk_write(dh, USB_ENDPOINT_OUT | EP_BULK_TO, ptr, size, TOUT); \
143 if (err != size) \
144 { \
145 fprintf(stderr,"\n[ERR] Error writing data\n"); \
146 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \
147 return -1; \
148 }
149
150#define GET_DATA(ptr, size) err = usb_bulk_read(dh, USB_ENDPOINT_IN | EP_BULK_TO, ptr, size, TOUT); \
151 if (err != size) \
152 { \
153 fprintf(stderr,"\n[ERR] Error writing data\n"); \
154 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \
155 return -1; \
156 }
157
158int upload_app(usb_dev_handle* dh, int address, unsigned char* p, int len, bool stage2)
159{
160 int err;
161 char buf[8];
162 unsigned char* tmp_buf;
163
164 fprintf(stderr, "[INFO] GET_CPU_INFO: ");
165 GET_CPU_INFO(buf);
166 buf[8] = 0;
167 fprintf(stderr, "%s\n", buf);
168#if 0
169 fprintf(stderr, "[INFO] Flushing cache...");
170 SEND_COMMAND(VR_FLUSH_CACHES, 0);
171 fprintf(stderr, " Done!\n");
172#endif
173
174 fprintf(stderr, "[INFO] SET_DATA_ADDRESS to 0x%x...", address);
175 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
176 fprintf(stderr, " Done!\n");
177
178 fprintf(stderr, "[INFO] Sending data...");
179 /* Must not split the file in several packages! */
180 SEND_DATA(p, len);
181 fprintf(stderr, " Done!\n");
182
183 fprintf(stderr, "[INFO] Verifying data...");
184 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
185 SEND_COMMAND(VR_SET_DATA_LENGTH, len);
186 tmp_buf = malloc(len);
187 if (tmp_buf == NULL)
188 {
189 fprintf(stderr, "\n[ERR] Could not allocate memory.\n");
190 return -1;
191 }
192 GET_DATA(tmp_buf, len);
193 if (memcmp(tmp_buf, p, len) != 0)
194 fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n");
195 else
196 fprintf(stderr, " Done!\n");
197 free(tmp_buf);
198
199 fprintf(stderr, "[INFO] Booting device [STAGE%d]...", (stage2 ? 2 : 1));
200 SEND_COMMAND((stage2 ? VR_PROGRAM_START2 : VR_PROGRAM_START1), (address+(stage2 ? 8 : 0)) );
201 fprintf(stderr, " Done!\n");
202
203 return 0;
204}
205
206int read_data(usb_dev_handle* dh, int address, unsigned char *p, int len)
207{
208 int err;
209 char buf[8];
210
211 fprintf(stderr, "[INFO] GET_CPU_INFO: ");
212 GET_CPU_INFO(buf);
213 buf[8] = 0;
214 fprintf(stderr, "%s\n", buf);
215
216 fprintf(stderr, "[INFO] Reading data...");
217 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
218 SEND_COMMAND(VR_SET_DATA_LENGTH, len);
219 GET_DATA(p, len);
220 fprintf(stderr, " Done!\n");
221 return 0;
222}
223
224unsigned int read_reg(usb_dev_handle* dh, int address, int size)
225{
226 int err;
227 unsigned char buf[4];
228
229 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
230 SEND_COMMAND(VR_SET_DATA_LENGTH, size);
231 GET_DATA(buf, size);
232
233 if(size == 1)
234 return buf[0];
235 else if(size == 2)
236 return (buf[1] << 8) | buf[0];
237 else if(size == 4)
238 return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
239 else
240 return 0;
241}
242
243int set_reg(usb_dev_handle* dh, int address, unsigned int val, int size)
244{
245 int err, i;
246 unsigned char buf[4];
247
248 buf[0] = val & 0xff;
249 if(i > 1)
250 {
251 buf[1] = (val >> 8) & 0xff;
252 if(i > 2)
253 {
254 buf[2] = (val >> 16) & 0xff;
255 buf[3] = (val >> 24) & 0xff;
256 }
257 }
258
259 SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
260 SEND_DATA(buf, size);
261
262 return 0;
263}
264#define or_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) | (val)), size);
265#define and_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) & (val)), size);
266#define bc_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) & ~(val)), size);
267#define xor_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) ^ (val)), size);
268
269#define TEST(m, size) fprintf(stderr, "%s -> %x\n", #m, read_reg(dh, m, size));
270int test_device(usb_dev_handle* dh)
271{
272 TEST(INTC_ISR, 4);
273 TEST(INTC_IMR, 4);
274 TEST(INTC_IMSR, 4);
275 TEST(INTC_IMCR, 4);
276 TEST(INTC_IPR, 4);
277
278 fprintf(stderr, "\n");
279 TEST(RTC_RCR, 4);
280 TEST(RTC_RSR, 4);
281 TEST(RTC_RSAR, 4);
282 TEST(RTC_RGR, 4);
283 TEST(RTC_HCR, 4);
284 TEST(RTC_RCR, 4);
285 TEST(RTC_HWFCR, 4);
286 TEST(RTC_HRCR, 4);
287 TEST(RTC_HWCR, 4);
288 TEST(RTC_HWSR, 4);
289
290 fprintf(stderr, "\n");
291 TEST(GPIO_PXPIN(0), 4);
292 TEST(GPIO_PXPIN(1), 4);
293 TEST(GPIO_PXPIN(2), 4);
294 TEST(GPIO_PXPIN(3), 4);
295
296 fprintf(stderr, "\n");
297 TEST(CPM_CLKGR, 4);
298
299 fprintf(stderr, "\n");
300 //or_reg(dh, SADC_ENA, SADC_ENA_TSEN, 1);
301 TEST(SADC_ENA, 1);
302 TEST(SADC_CTRL, 1);
303 TEST(SADC_TSDAT, 4);
304 TEST(SADC_BATDAT, 2);
305 TEST(SADC_STATE, 1);
306
307 fprintf(stderr, "\n");
308
309 TEST(SLCD_CFG, 4);
310 TEST(SLCD_CTRL, 1);
311 TEST(SLCD_STATE, 1);
312
313 return 0;
314}
315
316#define VOL_DOWN (1 << 27)
317#define VOL_UP (1 << 0)
318#define MENU (1 << 1)
319#define HOLD (1 << 16)
320#define OFF (1 << 29)
321#define MASK (VOL_DOWN|VOL_UP|MENU|HOLD|OFF)
322#define TS_MASK (SADC_STATE_PEND|SADC_STATE_PENU|SADC_STATE_TSRDY)
323int probe_device(usb_dev_handle* dh)
324{
325 int tmp;
326
327 //or_reg(dh, SADC_ENA, SADC_ENA_TSEN, 1);
328 while(1)
329 {
330 if(read_reg(dh, SADC_STATE, 1) & SADC_STATE_TSRDY)
331 {
332 printf("%x\n", read_reg(dh, SADC_TSDAT, 4));
333 or_reg(dh, SADC_CTRL, read_reg(dh, SADC_STATE, 1) & TS_MASK, 1);
334 }
335
336 tmp = read_reg(dh, GPIO_PXPIN(3), 4);
337 if(tmp < 0)
338 return tmp;
339 if(tmp ^ MASK)
340 {
341 if(!(tmp & VOL_DOWN))
342 printf("VOL_DOWN\t");
343 if(!(tmp & VOL_UP))
344 printf("VOL_UP\t");
345 if(!(tmp & MENU))
346 printf("MENU\t");
347 if(!(tmp & OFF))
348 printf("OFF\t");
349 if(!(tmp & HOLD))
350 printf("HOLD\t");
351 printf("\n");
352 }
353 }
354 return 0;
355}
356
357unsigned int read_file(const char *name, unsigned char **buffer)
358{
359 FILE *fd;
360 int len, n;
361
362 fd = fopen(name, "rb");
363 if (fd < 0)
364 {
365 fprintf(stderr, "[ERR] Could not open %s\n", name);
366 return 0;
367 }
368
369 len = filesize(fd);
370
371 *buffer = (unsigned char*)malloc(len);
372 if (*buffer == NULL)
373 {
374 fprintf(stderr, "[ERR] Could not allocate memory.\n");
375 fclose(fd);
376 return 0;
377 }
378
379 n = fread(*buffer, 1, len, fd);
380 if (n != len)
381 {
382 fprintf(stderr, "[ERR] Short read.\n");
383 fclose(fd);
384 return 0;
385 }
386 fclose(fd);
387
388 return len;
389}
390#define _GET_CPU fprintf(stderr, "[INFO] GET_CPU_INFO:"); \
391 GET_CPU_INFO(cpu); \
392 cpu[8] = 0; \
393 fprintf(stderr, " %s\n", cpu);
394#define _SET_ADDR(a) fprintf(stderr, "[INFO] Set address to 0x%x...", a); \
395 SEND_COMMAND(VR_SET_DATA_ADDRESS, a); \
396 fprintf(stderr, " Done!\n");
397#define _SEND_FILE(a) fsize = read_file(a, &buffer); \
398 fprintf(stderr, "[INFO] Sending file %s: %d bytes...", a, fsize); \
399 SEND_DATA(buffer, fsize); \
400 free(buffer); \
401 fprintf(stderr, " Done!\n");
402#define _VERIFY_DATA(a,c) fprintf(stderr, "[INFO] Verifying data (%s)...", a); \
403 fsize = read_file(a, &buffer); \
404 buffer2 = (unsigned char*)malloc(fsize); \
405 SEND_COMMAND(VR_SET_DATA_ADDRESS, c); \
406 SEND_COMMAND(VR_SET_DATA_LENGTH, fsize); \
407 GET_DATA(buffer2, fsize); \
408 if(memcmp(buffer, buffer2, fsize) != 0) \
409 fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n"); \
410 else \
411 fprintf(stderr, " Done!\n"); \
412 free(buffer); \
413 free(buffer2);
414#define _STAGE1(a) fprintf(stderr, "[INFO] Stage 1 at 0x%x\n", a); \
415 SEND_COMMAND(VR_PROGRAM_START1, a);
416#define _STAGE2(a) fprintf(stderr, "[INFO] Stage 2 at 0x%x\n", a); \
417 SEND_COMMAND(VR_PROGRAM_START2, a);
418#define _FLUSH fprintf(stderr, "[INFO] Flushing caches...\n"); \
419 SEND_COMMAND(VR_FLUSH_CACHES, 0);
420#ifdef _WIN32
421 #define _SLEEP(x) Sleep(x*1000);
422#else
423 #define _SLEEP(x) sleep(x);
424#endif
425int mimic_of(usb_dev_handle *dh)
426{
427 int err, fsize;
428 unsigned char *buffer, *buffer2;
429 char cpu[8];
430
431 fprintf(stderr, "[INFO] Start!\n");
432 _GET_CPU;
433 _SET_ADDR(0x8000 << 16);
434 _SEND_FILE("1.bin");
435 _GET_CPU;
436 _VERIFY_DATA("1.bin", 0x8000 << 16);
437 _STAGE1(0x8000 << 16);
438 _SLEEP(3);
439 _VERIFY_DATA("2.bin", 0xB3020060);
440 _GET_CPU;
441 _GET_CPU;
442 _FLUSH;
443 _GET_CPU;
444 _GET_CPU;
445 _SET_ADDR(0x8000 << 16);
446 _SEND_FILE("3.bin");
447 _GET_CPU;
448 _VERIFY_DATA("3.bin", 0x8000 << 16);
449 _GET_CPU;
450 _FLUSH;
451 _GET_CPU;
452 _GET_CPU;
453 _SET_ADDR(0x80D0 << 16);
454 _SEND_FILE("4.bin");
455 _GET_CPU;
456 _VERIFY_DATA("4.bin", 0x80D0 << 16);
457 _GET_CPU;
458 _FLUSH;
459 _GET_CPU;
460 _GET_CPU;
461 _SET_ADDR(0x80E0 << 16);
462 _SEND_FILE("5.bin");
463 _GET_CPU;
464 _VERIFY_DATA("5.bin", 0x80E0 << 16);
465 _GET_CPU;
466 _FLUSH;
467 _GET_CPU;
468 _GET_CPU;
469 _SET_ADDR(0x80004000);
470 _SEND_FILE("6.bin");
471 _GET_CPU;
472 _VERIFY_DATA("6.bin", 0x80004000);
473 _GET_CPU;
474 _FLUSH;
475 _GET_CPU;
476 _GET_CPU;
477 _SET_ADDR(0x80FD << 16);
478 _SEND_FILE("7.bin");
479 _GET_CPU;
480 _VERIFY_DATA("7.bin", 0x80FD << 16);
481 _GET_CPU;
482 _FLUSH;
483 _GET_CPU;
484 _STAGE2(0x80FD0004);
485 _VERIFY_DATA("8.bin", 0x80004004);
486 _VERIFY_DATA("9.bin", 0x80004008);
487 _SLEEP(2);
488 _GET_CPU;
489 _SET_ADDR(0x80E0 << 16);
490 _SEND_FILE("10.bin");
491 _GET_CPU;
492 _VERIFY_DATA("10.bin", 0x80E0 << 16);
493 _GET_CPU;
494 _FLUSH;
495 _GET_CPU;
496 _STAGE2(0x80e00008);
497 fprintf(stderr, "[INFO] Done!\n");
498 return 0;
499}
500
501void jzconnect(int address, unsigned char* buf, int len, int func)
502{
503 struct usb_bus *bus;
504 struct usb_device *tmp_dev;
505 struct usb_device *dev = NULL;
506 usb_dev_handle *dh;
507 int err;
508
509 fprintf(stderr,"[INFO] Searching for device...\n");
510
511 usb_init();
512 if(usb_find_busses() < 0)
513 {
514 fprintf(stderr, "[ERR] Could not find any USB busses.\n");
515 return;
516 }
517
518 if (usb_find_devices() < 0)
519 {
520 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n");
521 return;
522 }
523
524 for (bus = usb_get_busses(); bus; bus = bus->next)
525 {
526 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next)
527 {
528 //printf("Found Vendor %04x Product %04x\n",tmp_dev->descriptor.idVendor, tmp_dev->descriptor.idProduct);
529 if (tmp_dev->descriptor.idVendor == VID &&
530 tmp_dev->descriptor.idProduct == PID)
531 {
532 dev = tmp_dev;
533 goto found;
534
535 }
536 }
537 }
538
539 if (dev == NULL)
540 {
541 fprintf(stderr, "[ERR] Device not found.\n");
542 fprintf(stderr, "[ERR] Ensure your device is in USB boot mode and run usbtool again.\n");
543 return;
544 }
545
546found:
547 if ( (dh = usb_open(dev)) == NULL)
548 {
549 fprintf(stderr,"[ERR] Unable to open device.\n");
550 return;
551 }
552
553 err = usb_set_configuration(dh, 1);
554
555 if (err < 0)
556 {
557 fprintf(stderr, "[ERR] usb_set_configuration failed (%d, %s)\n", err, usb_strerror());
558 usb_close(dh);
559 return;
560 }
561
562 /* "must be called" written in the libusb documentation */
563 err = usb_claim_interface(dh, 0);
564 if (err < 0)
565 {
566 fprintf(stderr, "[ERR] Unable to claim interface (%d, %s)\n", err, usb_strerror());
567 usb_close(dh);
568 return;
569 }
570
571 fprintf(stderr,"[INFO] Found device, uploading application.\n");
572
573 /* Now we can transfer the application to the device. */
574
575 switch(func)
576 {
577 case 1:
578 case 5:
579 err = upload_app(dh, address, buf, len, (func == 5));
580 break;
581 case 2:
582 err = read_data(dh, address, buf, len);
583 break;
584 case 3:
585 err = test_device(dh);
586 break;
587 case 4:
588 err = probe_device(dh);
589 break;
590 case 6:
591 err = mimic_of(dh);
592 break;
593 }
594
595 /* release claimed interface */
596 usb_release_interface(dh, 0);
597
598 usb_close(dh);
599}
600
601void print_usage(void)
602{
603#ifdef _WIN32
604 fprintf(stderr, "Usage: usbtool.exe [CMD] [FILE] [ADDRESS] [LEN]\n");
605#else
606 fprintf(stderr, "Usage: usbtool [CMD] [FILE] [ADDRESS] [LEN]\n");
607#endif
608 fprintf(stderr, "\t[ADDRESS] has to be in 0xHEXADECIMAL format\n");
609 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");
610 fprintf(stderr, "\t\t3 -> read device status\n\t\t4 -> probe keys (only Onda VX747)\n");
611 fprintf(stderr, "\t\t5 -> same as 1 but do a stage 2 boot\n\t\t6 -> mimic OF fw recovery\n");
612#ifdef _WIN32
613 fprintf(stderr, "\nExample:\n\t usbtool.exe 1 fw.bin 0x80000000");
614 fprintf(stderr, "\n\t usbtool.exe 2 save.bin 0x81000000 1024");
615#else
616 fprintf(stderr, "\nExample:\n\t usbtool 1 fw.bin 0x80000000");
617 fprintf(stderr, "\n\t usbtool 2 save.bin 0x81000000 1024");
618#endif
619}
620
621int main(int argc, char* argv[])
622{
623 unsigned char* buf;
624 int n, len, address, cmd=0;
625 FILE* fd;
626
627 fprintf(stderr, "USBtool v" VERSION " - (C) 2008 Maurus Cuelenaere\n");
628 fprintf(stderr, "This is free software; see the source for copying conditions. There is NO\n");
629 fprintf(stderr, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
630
631 if(argc > 1)
632 sscanf(argv[1], "%d", &cmd);
633 switch(cmd)
634 {
635 case 5:
636 case 1:
637 if (strcmp(argv[3], "-1") == 0)
638 address = 0x80000000;
639 else
640 {
641 if (sscanf(argv[3], "0x%x", &address) <= 0)
642 {
643 print_usage();
644 return -1;
645 }
646 }
647
648 fd = fopen(argv[2], "rb");
649 if (fd < 0)
650 {
651 fprintf(stderr, "[ERR] Could not open %s\n", argv[2]);
652 return 4;
653 }
654
655 len = filesize(fd);
656
657 if (len > MAX_FIRMWARESIZE)
658 {
659 fprintf(stderr, "[ERR] Firmware file too big\n");
660 fclose(fd);
661 return 5;
662 }
663
664 buf = malloc(len);
665 if (buf == NULL)
666 {
667 fprintf(stderr, "[ERR] Could not allocate memory.\n");
668 fclose(fd);
669 return 6;
670 }
671
672 n = fread(buf, 1, len, fd);
673 if (n != len)
674 {
675 fprintf(stderr, "[ERR] Short read.\n");
676 fclose(fd);
677 return 7;
678 }
679 fclose(fd);
680
681 fprintf(stderr, "[INFO] File size: %d bytes\n", n);
682
683 jzconnect(address, buf, len, cmd);
684 break;
685 case 2:
686 if (sscanf(argv[3], "0x%x", &address) <= 0)
687 {
688 print_usage();
689 return -1;
690 }
691
692 fd = fopen(argv[2], "wb");
693 if (fd < 0)
694 {
695 fprintf(stderr, "[ERR] Could not open %s\n", argv[2]);
696 return 4;
697 }
698
699 sscanf(argv[4], "%d", &len);
700
701 buf = malloc(len);
702 if (buf == NULL)
703 {
704 fprintf(stderr, "[ERR] Could not allocate memory.\n");
705 fclose(fd);
706 return 6;
707 }
708
709 jzconnect(address, buf, len, 2);
710
711 n = fwrite(buf, 1, len, fd);
712 if (n != len)
713 {
714 fprintf(stderr, "[ERR] Short write.\n");
715 fclose(fd);
716 return 7;
717 }
718 fclose(fd);
719 break;
720 case 3:
721 case 4:
722 case 6:
723 jzconnect(address, NULL, 0, cmd);
724 break;
725 default:
726 print_usage();
727 return 1;
728 break;
729 }
730
731 return 0;
732}