Revisión | 874fa66c4dd785bb2daf39cfb2aa7068d9523656 (tree) |
---|---|
Tiempo | 2015-04-19 21:28:32 |
Autor | Yoshinori Sato <ysato@sa76...> |
Commiter | Yoshinori Sato |
RX64M protocol support
@@ -1,3 +1,3 @@ | ||
1 | 1 | bin_PROGRAMS = h8flash |
2 | -h8flash_SOURCES = main.c comm.c serial.c usb.c | |
2 | +h8flash_SOURCES = main.c comm.c comm2.c serial.c usb.c | |
3 | 3 | h8flash_LDADD = $(LIBOBJS) |
@@ -19,8 +19,69 @@ | ||
19 | 19 | #include <errno.h> |
20 | 20 | #include "h8flash.h" |
21 | 21 | |
22 | -#define TRY1COUNT 60 | |
23 | -#define BAUD_ADJUST_LEN 30 | |
22 | +#define ACK 0x06 | |
23 | + | |
24 | +#define QUERY_DEVICE 0x20 | |
25 | +#define QUERY_DEVICE_RES 0x30 | |
26 | +#define QUERY_CLOCKMODE 0x21 | |
27 | +#define QUERY_CLOCKMODE_RES 0x31 | |
28 | +#define QUERY_MULTIRATE 0x22 | |
29 | +#define QUERY_MULTIRATE_RES 0x32 | |
30 | +#define QUERY_FREQ 0x23 | |
31 | +#define QUERY_FREQ_RES 0x33 | |
32 | +#define QUERY_BOOT_AREA 0x24 | |
33 | +#define QUERY_BOOT_AREA_RES 0x34 | |
34 | +#define QUERY_USER_AREA 0x25 | |
35 | +#define QUERY_USER_AREA_RES 0x35 | |
36 | +#define QUERY_WRITESIZE 0x27 | |
37 | +#define QUERY_WRITESIZE_RES 0x37 | |
38 | + | |
39 | +#define SELECT_DEVICE 0x10 | |
40 | +#define SET_CLOCKMODE 0x11 | |
41 | + | |
42 | +#define SET_BITRATE 0x3f | |
43 | + | |
44 | +#define WRITEMODE 0x40 | |
45 | +#define WRITE_USERBOOT 0x42 | |
46 | +#define WRITE_USER 0x43 | |
47 | +#define BLANKCHECK_USERBOOT 0x4c | |
48 | +#define BLANKCHECK_USER 0x4d | |
49 | +#define WRITE 0x50 | |
50 | + | |
51 | +struct devinfo_t { | |
52 | + char code[4]; | |
53 | + char name[256]; | |
54 | +}; | |
55 | + | |
56 | +struct devicelist_t { | |
57 | + int numdevs; | |
58 | + struct devinfo_t devs[0]; | |
59 | +}; | |
60 | + | |
61 | +struct clockmode_t { | |
62 | + int nummode; | |
63 | + int mode[0]; | |
64 | +}; | |
65 | + | |
66 | +struct multirate_t { | |
67 | + int numrate; | |
68 | + int rate[0]; | |
69 | +}; | |
70 | + | |
71 | +struct multilist_t { | |
72 | + int nummulti; | |
73 | + struct multirate_t *muls[0]; | |
74 | +}; | |
75 | + | |
76 | +struct freq_t { | |
77 | + int min; | |
78 | + int max; | |
79 | +}; | |
80 | + | |
81 | +struct freqlist_t { | |
82 | + int numfreq; | |
83 | + struct freq_t freq[0]; | |
84 | +}; | |
24 | 85 | |
25 | 86 | /* NAK answer list */ |
26 | 87 | const unsigned char naktable[] = {0x80, 0x90, 0x91, 0xbf, 0xc0, 0xc2, 0xc3, 0xc8, |
@@ -107,7 +168,7 @@ static int receive(struct port_t *p, unsigned char *data) | ||
107 | 168 | } |
108 | 169 | |
109 | 170 | /* get target device list */ |
110 | -struct devicelist_t *get_devicelist(struct port_t *port) | |
171 | +static struct devicelist_t *get_devicelist(struct port_t *port) | |
111 | 172 | { |
112 | 173 | unsigned char rxbuf[255+3]; |
113 | 174 | unsigned char *devp; |
@@ -139,7 +200,7 @@ struct devicelist_t *get_devicelist(struct port_t *port) | ||
139 | 200 | } |
140 | 201 | |
141 | 202 | /* set target device ID */ |
142 | -int select_device(struct port_t *port, const char *code) | |
203 | +static int select_device(struct port_t *port, const char *code) | |
143 | 204 | { |
144 | 205 | unsigned char buf[6] = {SELECT_DEVICE, 0x04, 0x00, 0x00, 0x00, 0x00}; |
145 | 206 |
@@ -151,7 +212,7 @@ int select_device(struct port_t *port, const char *code) | ||
151 | 212 | } |
152 | 213 | |
153 | 214 | /* get target clock mode */ |
154 | -struct clockmode_t *get_clockmode(struct port_t *port) | |
215 | +static struct clockmode_t *get_clockmode(struct port_t *port) | |
155 | 216 | { |
156 | 217 | unsigned char rxbuf[255+3]; |
157 | 218 | unsigned char *clkmdp; |
@@ -183,7 +244,7 @@ struct clockmode_t *get_clockmode(struct port_t *port) | ||
183 | 244 | } |
184 | 245 | |
185 | 246 | /* set target clock mode */ |
186 | -int set_clockmode(struct port_t *port, int mode) | |
247 | +static int set_clockmode(struct port_t *port, int mode) | |
187 | 248 | { |
188 | 249 | unsigned char buf[3] = {SET_CLOCKMODE, 0x01, 0x00}; |
189 | 250 |
@@ -196,7 +257,7 @@ int set_clockmode(struct port_t *port, int mode) | ||
196 | 257 | } |
197 | 258 | |
198 | 259 | /* get target multiplier/divider rate */ |
199 | -struct multilist_t *get_multirate(struct port_t *port) | |
260 | +static struct multilist_t *get_multirate(struct port_t *port) | |
200 | 261 | { |
201 | 262 | unsigned char rxbuf[255+3]; |
202 | 263 | unsigned char *mulp; |
@@ -242,7 +303,7 @@ struct multilist_t *get_multirate(struct port_t *port) | ||
242 | 303 | } |
243 | 304 | |
244 | 305 | /* get target operation frequency list */ |
245 | -struct freqlist_t *get_freqlist(struct port_t *port) | |
306 | +static struct freqlist_t *get_freqlist(struct port_t *port) | |
246 | 307 | { |
247 | 308 | unsigned char rxbuf[255+3]; |
248 | 309 | unsigned char *freqp; |
@@ -273,13 +334,35 @@ struct freqlist_t *get_freqlist(struct port_t *port) | ||
273 | 334 | } |
274 | 335 | |
275 | 336 | /* get target rom mapping */ |
276 | -struct arealist_t *get_arealist(struct port_t *port, enum mat_t mat) | |
337 | +/* get write page size */ | |
338 | +static int get_writesize(struct port_t *port) | |
339 | +{ | |
340 | + unsigned char rxbuf[5]; | |
341 | + unsigned short size; | |
342 | + | |
343 | + rxbuf[0] = QUERY_WRITESIZE; | |
344 | + send(port, rxbuf, 1); | |
345 | + if (receive(port, rxbuf) == -1) | |
346 | + return -1; | |
347 | + if (rxbuf[0] != QUERY_WRITESIZE_RES) | |
348 | + return -1; | |
349 | + | |
350 | + if (rxbuf[1] != 2) | |
351 | + return -1; | |
352 | + size = rxbuf[2] << 8 | rxbuf[3]; | |
353 | + return size; | |
354 | +} | |
355 | + | |
356 | +static struct arealist_t *get_arealist(struct port_t *port, enum mat_t mat) | |
277 | 357 | { |
278 | 358 | char ans; |
279 | 359 | unsigned char rxbuf[255+3]; |
280 | 360 | unsigned char *areap; |
281 | 361 | struct arealist_t *arealist; |
282 | 362 | int numarea; |
363 | + int wsize; | |
364 | + | |
365 | + wsize = get_writesize(port); | |
283 | 366 | |
284 | 367 | switch(mat) { |
285 | 368 | case user: |
@@ -308,32 +391,20 @@ struct arealist_t *get_arealist(struct port_t *port, enum mat_t mat) | ||
308 | 391 | arealist->areas = numarea; |
309 | 392 | areap = &rxbuf[3]; |
310 | 393 | for(numarea = 0; numarea < arealist->areas; numarea++) { |
394 | + int size; | |
395 | + | |
311 | 396 | arealist->area[numarea].start = getlong(areap); |
312 | 397 | arealist->area[numarea].end = getlong(areap+4); |
398 | + arealist->area[numarea].size = wsize; | |
313 | 399 | areap += 8; |
400 | + size = arealist->area[numarea].end - arealist->area[numarea].start; | |
401 | + if (!(arealist->area[numarea].image = malloc(size))) | |
402 | + return NULL; | |
403 | + memset(arealist->area[numarea].image, 0xff, size); | |
314 | 404 | } |
315 | 405 | return arealist; |
316 | 406 | } |
317 | 407 | |
318 | -/* get write page size */ | |
319 | -int get_writesize(struct port_t *port) | |
320 | -{ | |
321 | - unsigned char rxbuf[5]; | |
322 | - unsigned short size; | |
323 | - | |
324 | - rxbuf[0] = QUERY_WRITESIZE; | |
325 | - send(port, rxbuf, 1); | |
326 | - if (receive(port, rxbuf) == -1) | |
327 | - return -1; | |
328 | - if (rxbuf[0] != QUERY_WRITESIZE_RES) | |
329 | - return -1; | |
330 | - | |
331 | - if (rxbuf[1] != 2) | |
332 | - return -1; | |
333 | - size = rxbuf[2] << 8 | rxbuf[3]; | |
334 | - return size; | |
335 | -} | |
336 | - | |
337 | 408 | /* bitrate candidate list */ |
338 | 409 | static const int rate_list[]={1152,576,384,192,96}; |
339 | 410 |
@@ -476,16 +547,12 @@ static int skipcheck(unsigned char *data, unsigned short size) | ||
476 | 547 | } |
477 | 548 | |
478 | 549 | /* write rom image */ |
479 | -int write_rom(struct port_t *port, const unsigned char *romimage, struct writeinfo_t *writeinfo) | |
550 | +static int write_rom(struct port_t *port, struct arealist_t *arealist, enum mat_t mat) | |
480 | 551 | { |
481 | 552 | unsigned char *buf = NULL; |
482 | 553 | unsigned int romaddr; |
483 | - | |
484 | - buf = (unsigned char *)malloc(5 + writeinfo->size); | |
485 | - if (buf == NULL) { | |
486 | - perror(""); | |
487 | - return 0; | |
488 | - } | |
554 | + int i; | |
555 | + struct area_t *area; | |
489 | 556 | |
490 | 557 | puts("Erase flash..."); |
491 | 558 | /* enter writemode */ |
@@ -498,7 +565,7 @@ int write_rom(struct port_t *port, const unsigned char *romimage, struct writein | ||
498 | 565 | } |
499 | 566 | |
500 | 567 | /* mat select */ |
501 | - switch (writeinfo->mat) { | |
568 | + switch (mat) { | |
502 | 569 | case user: |
503 | 570 | buf[0] = WRITE_USER; |
504 | 571 | break; |
@@ -514,35 +581,47 @@ int write_rom(struct port_t *port, const unsigned char *romimage, struct writein | ||
514 | 581 | } |
515 | 582 | |
516 | 583 | /* writing loop */ |
517 | - for (romaddr = writeinfo->area.start; | |
518 | - romaddr >= writeinfo->area.start && romaddr < writeinfo->area.end; | |
519 | - romaddr += writeinfo->size) { | |
520 | - if (skipcheck((unsigned char *)(romimage + romaddr - writeinfo->area.start), writeinfo->size)) | |
521 | - continue; | |
522 | - /* set write data */ | |
523 | - *(buf + 0) = WRITE; | |
524 | - setlong(buf + 1, romaddr); | |
525 | - if ((romaddr + writeinfo->size) < writeinfo->area.end) { | |
526 | - memcpy(buf + 5, romimage + romaddr - writeinfo->area.start, writeinfo->size); | |
527 | - } else { | |
528 | - /* lastpage < writesize */ | |
529 | - memcpy(buf + 5, romimage + romaddr - writeinfo->area.start, | |
530 | - (writeinfo->area.end - romaddr)); | |
531 | - memset(buf + 5 + writeinfo->area.end - romaddr, 0xff, | |
532 | - writeinfo->size - (writeinfo->area.end - romaddr)); | |
533 | - } | |
534 | - /* write */ | |
535 | - send(port, buf, 5 + writeinfo->size); | |
536 | - if (receive(port, buf) != 1) { | |
537 | - fprintf(stderr, PROGNAME ": write data %08x failed.", romaddr); | |
538 | - goto error; | |
539 | - } | |
540 | - if (verbose) | |
541 | - printf("write - %08x\n",romaddr); | |
542 | - else { | |
543 | - printf("writing %d/%d byte\r", romaddr - writeinfo->area.start, | |
544 | - writeinfo->area.end - writeinfo->area.start); | |
545 | - fflush(stdout); | |
584 | + for (i = 0; i < arealist->areas; i++) { | |
585 | + area = &arealist->area[i]; | |
586 | + for (romaddr = area->start; | |
587 | + romaddr < area->end; | |
588 | + romaddr += area->size) { | |
589 | + if (skipcheck(area->image + romaddr - area->start, | |
590 | + area->size)) { | |
591 | + if (verbose) | |
592 | + printf("skip - %08x\n",romaddr); | |
593 | + else { | |
594 | + printf("writing %d/%d byte\r", | |
595 | + romaddr - area->start, | |
596 | + area->end - area->start); | |
597 | + fflush(stdout); | |
598 | + } | |
599 | + continue; | |
600 | + } | |
601 | + buf = malloc(area->size + 5); | |
602 | + if (buf == NULL) | |
603 | + goto error; | |
604 | + /* set write data */ | |
605 | + *(buf + 0) = WRITE; | |
606 | + setlong(buf + 1, romaddr); | |
607 | + memcpy(buf + 5, | |
608 | + area->image + romaddr - area->start, | |
609 | + area->size); | |
610 | + /* write */ | |
611 | + send(port, buf, 5 + area->size); | |
612 | + free(buf); | |
613 | + if (receive(port, buf) != 1) { | |
614 | + fprintf(stderr, PROGNAME ": write data %08x failed.", romaddr); | |
615 | + goto error; | |
616 | + } | |
617 | + if (verbose) | |
618 | + printf("write - %08x\n",romaddr); | |
619 | + else { | |
620 | + printf("writing %d/%d byte\r", | |
621 | + romaddr - area->start, | |
622 | + area->end - area->start); | |
623 | + fflush(stdout); | |
624 | + } | |
546 | 625 | } |
547 | 626 | } |
548 | 627 | /* write finish */ |
@@ -553,20 +632,16 @@ int write_rom(struct port_t *port, const unsigned char *romimage, struct writein | ||
553 | 632 | fputs(PROGNAME ": writemode exit failed", stderr); |
554 | 633 | goto error; |
555 | 634 | } |
556 | - free(buf); | |
557 | 635 | if (!verbose) |
558 | - printf("writing %d/%d byte\n", writeinfo->area.end - writeinfo->area.start, | |
559 | - writeinfo->area.end - writeinfo->area.start); | |
560 | - | |
636 | + putc('\n', stdout); | |
561 | 637 | |
562 | 638 | return 1; |
563 | 639 | error: |
564 | - free(buf); | |
565 | 640 | return 0; |
566 | 641 | } |
567 | 642 | |
568 | 643 | /* connect to target chip */ |
569 | -int setup_connection(struct port_t *p, int input_freq) | |
644 | +static int setup_connection(struct port_t *p, int input_freq, char endian) | |
570 | 645 | { |
571 | 646 | int c; |
572 | 647 | int r = -1; |
@@ -575,15 +650,6 @@ int setup_connection(struct port_t *p, int input_freq) | ||
575 | 650 | struct multilist_t *multilist = NULL; |
576 | 651 | struct freqlist_t *freqlist = NULL; |
577 | 652 | |
578 | - /* connect target */ | |
579 | - if (!p->connect_target(p->dev)) { | |
580 | - if (errno != 0) | |
581 | - perror(PROGNAME); | |
582 | - else | |
583 | - fputs("target no response\n", stderr); | |
584 | - goto error; | |
585 | - } | |
586 | - | |
587 | 653 | /* query target infomation */ |
588 | 654 | devicelist = get_devicelist(p); |
589 | 655 | if (devicelist == NULL) { |
@@ -704,7 +770,7 @@ int setup_connection(struct port_t *p, int input_freq) | ||
704 | 770 | } |
705 | 771 | |
706 | 772 | /* connect to target chip */ |
707 | -void dump_configs(struct port_t *p) | |
773 | +static void dump_configs(struct port_t *p) | |
708 | 774 | { |
709 | 775 | struct devicelist_t *devicelist = NULL; |
710 | 776 | struct clockmode_t *clockmode = NULL; |
@@ -714,15 +780,6 @@ void dump_configs(struct port_t *p) | ||
714 | 780 | int clk; |
715 | 781 | int c1,c2; |
716 | 782 | |
717 | - /* connect target */ | |
718 | - if (!p->connect_target(p->dev)) { | |
719 | - if (errno != 0) | |
720 | - perror(PROGNAME); | |
721 | - else | |
722 | - fputs("target no response\n", stderr); | |
723 | - goto error; | |
724 | - } | |
725 | - | |
726 | 783 | /* query target infomation */ |
727 | 784 | devicelist = get_devicelist(p); |
728 | 785 | if (devicelist == NULL) { |
@@ -795,4 +852,15 @@ error: | ||
795 | 852 | free(devicelist); |
796 | 853 | free(clockmode); |
797 | 854 | } |
798 | - | |
855 | + | |
856 | +static struct comm_t v1 = { | |
857 | + .get_arealist = get_arealist, | |
858 | + .write_rom = write_rom, | |
859 | + .setup_connection = setup_connection, | |
860 | + .dump_configs = dump_configs, | |
861 | +}; | |
862 | + | |
863 | +struct comm_t *comm_v1(void) | |
864 | +{ | |
865 | + return &v1; | |
866 | +} |
@@ -0,0 +1,488 @@ | ||
1 | +/* | |
2 | + * Renesas CPU On-chip Flash memory writer | |
3 | + * target communication (New) | |
4 | + * | |
5 | + * Yoshinori Sato <ysato@users.sourceforge.jp> | |
6 | + * | |
7 | + * This file is subject to the terms and conditions of the GNU Lesser | |
8 | + * General Public License version 2.1 (or later). | |
9 | + */ | |
10 | + | |
11 | +#include <stdio.h> | |
12 | +#include <sys/time.h> | |
13 | +#include <sys/types.h> | |
14 | +#include <unistd.h> | |
15 | +#include <string.h> | |
16 | +#include <termios.h> | |
17 | +#include <fcntl.h> | |
18 | +#include <stdlib.h> | |
19 | +#include <errno.h> | |
20 | +#include <stdint.h> | |
21 | +#include "h8flash.h" | |
22 | + | |
23 | +#define TRY1COUNT 60 | |
24 | +#define BAUD_ADJUST_LEN 30 | |
25 | + | |
26 | +#define SOH 0x01 | |
27 | +#define ETX 0x03 | |
28 | +#define ETB 0x17 | |
29 | +#define SOD 0x81 | |
30 | + | |
31 | +/* big endian to cpu endian convert 32bit */ | |
32 | +static __inline__ int getlong(uint32_t *p) | |
33 | +{ | |
34 | + uint8_t *b = (uint8_t *)p; | |
35 | + return (*b << 24) | (*(b+1) << 16) | (*(b+2) << 8) | *(b+3); | |
36 | +} | |
37 | + | |
38 | +/* big endian to cpu endian convert 16bit */ | |
39 | +static __inline__ short getword(uint16_t *p) | |
40 | +{ | |
41 | + uint8_t *b = (uint8_t *)p; | |
42 | + return (*b << 8) | *(b+1); | |
43 | +} | |
44 | + | |
45 | +/* cpu endian to big endian 32bit */ | |
46 | +static __inline__ void setlong(unsigned char *buf, unsigned long val) | |
47 | +{ | |
48 | + *(buf + 0) = (val >> 24) & 0xff; | |
49 | + *(buf + 1) = (val >> 16) & 0xff; | |
50 | + *(buf + 2) = (val >> 8) & 0xff; | |
51 | + *(buf + 3) = (val ) & 0xff; | |
52 | +} | |
53 | + | |
54 | +/* cpu endian to big endian 16bit */ | |
55 | +static __inline__ void setword(unsigned char *buf, unsigned short val) | |
56 | +{ | |
57 | + *(buf + 0) = (val >> 8) & 0xff; | |
58 | + *(buf + 1) = (val ) & 0xff; | |
59 | +} | |
60 | + | |
61 | +/* send multibyte command */ | |
62 | +static void send(struct port_t *p, unsigned char *data, int len, | |
63 | + unsigned char head, unsigned char tail) | |
64 | +{ | |
65 | + unsigned char buf[2]; | |
66 | + unsigned char sum; | |
67 | + | |
68 | + p->send_data(&head, 1); | |
69 | + setword(buf, len); | |
70 | + p->send_data(buf, 2); | |
71 | + p->send_data(data, len); | |
72 | + if (len > 0) { | |
73 | + for(sum = 0; len > 0; len--, data++) | |
74 | + sum += *data; | |
75 | + } | |
76 | + sum += buf[0]; | |
77 | + sum += buf[1]; | |
78 | + sum = 0x100 - sum; | |
79 | + p->send_data(&sum, 1); | |
80 | + p->send_data(&tail, 1); | |
81 | +} | |
82 | + | |
83 | +/* receive answer */ | |
84 | +static unsigned int receive(struct port_t *p, unsigned char *data) | |
85 | +{ | |
86 | + int len; | |
87 | + unsigned char *rxptr; | |
88 | + unsigned char sum = 0; | |
89 | + | |
90 | + rxptr = data; | |
91 | + /* Header */ | |
92 | + for (len = 0; len < 3; len++) { | |
93 | + if (p->receive_byte(rxptr) != 1) | |
94 | + return -1; | |
95 | + rxptr++; | |
96 | + } | |
97 | + | |
98 | + /* Res + Data */ | |
99 | + len = getword((uint16_t *)(data + 1)); | |
100 | + for(; len > 0; len--) { | |
101 | + if (p->receive_byte(rxptr) != 1) | |
102 | + return -1; | |
103 | + rxptr++; | |
104 | + } | |
105 | + | |
106 | + /* SUM + ETX/ETB */ | |
107 | + for (len = 0; len < 2; len++) { | |
108 | + if (p->receive_byte(rxptr) != 1) | |
109 | + return -1; | |
110 | + rxptr++; | |
111 | + } | |
112 | + | |
113 | + /* sum check */ | |
114 | + for (sum = 0, rxptr = data + 1, len = getword((uint16_t *)(data + 1)) + 3; | |
115 | + len > 0; len--, rxptr++) | |
116 | + sum += *rxptr; | |
117 | + if (sum != 0) | |
118 | + return -1; | |
119 | + return *(data + 3); | |
120 | +} | |
121 | + | |
122 | +struct raw_devtype_t { | |
123 | + uint8_t sod; | |
124 | + uint16_t len; | |
125 | + uint8_t res; | |
126 | + uint64_t typ; | |
127 | + uint32_t osa; | |
128 | + uint32_t osi; | |
129 | + uint32_t cpa; | |
130 | + uint32_t cpi; | |
131 | + uint8_t sum; | |
132 | + uint8_t etx; | |
133 | +} __attribute__((packed,aligned(1))); | |
134 | + | |
135 | +struct devtype_t { | |
136 | + uint64_t typ; | |
137 | + uint32_t osa; | |
138 | + uint32_t osi; | |
139 | + uint32_t cpa; | |
140 | + uint32_t cpi; | |
141 | +}; | |
142 | + | |
143 | +/* get target device type */ | |
144 | +static int get_devtype(struct port_t *port, struct devtype_t *type) | |
145 | +{ | |
146 | + struct raw_devtype_t raw_type; | |
147 | + unsigned char cmd[] = {0x38}; | |
148 | + | |
149 | + send(port, cmd, 1, SOH, ETX); | |
150 | + if (receive(port, (unsigned char *)&raw_type) == -1) | |
151 | + return -1; | |
152 | + send(port, cmd, 1, SOD, ETX); | |
153 | + if (receive(port, (unsigned char *)&raw_type) == -1) | |
154 | + return -1; | |
155 | + if (raw_type.res != 0x38) | |
156 | + return -1; | |
157 | + type->typ = raw_type.typ; | |
158 | + type->osa = getlong(&raw_type.osa); | |
159 | + type->osi = getlong(&raw_type.osi); | |
160 | + type->cpa = getlong(&raw_type.cpa); | |
161 | + type->cpi = getlong(&raw_type.cpi); | |
162 | + return 0; | |
163 | +} | |
164 | + | |
165 | +/* set endian */ | |
166 | +static int set_endian(struct port_t *port, unsigned int endian) | |
167 | +{ | |
168 | + unsigned char cmd[2] = {0x36, 0x00}; | |
169 | + unsigned char rcv[8]; | |
170 | + | |
171 | + cmd[1] = endian; | |
172 | + send(port, cmd, 2, SOH, ETX); | |
173 | + return receive(port, rcv); | |
174 | +} | |
175 | + | |
176 | +struct raw_freq_t { | |
177 | + uint8_t sod; | |
178 | + uint16_t len; | |
179 | + uint8_t res; | |
180 | + uint32_t fq; | |
181 | + uint32_t pf; | |
182 | + uint8_t sum; | |
183 | + uint8_t etx; | |
184 | +} __attribute__((packed,aligned(1))); | |
185 | + | |
186 | +/* set frequency */ | |
187 | +static int set_frequency(struct port_t *port, unsigned int input, unsigned int system) | |
188 | +{ | |
189 | + unsigned char cmd[] = {0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
190 | + struct raw_freq_t freq; | |
191 | + unsigned int core, peripheral; | |
192 | + setlong(cmd + 1, input); | |
193 | + setlong(cmd + 5, system); | |
194 | + send(port, cmd, sizeof(cmd), SOH, ETX); | |
195 | + if (receive(port, (unsigned char *)&freq) == -1) | |
196 | + return -1; | |
197 | + send(port, cmd, 1, SOD, ETX); | |
198 | + if (receive(port, (unsigned char *)&freq) == -1) | |
199 | + return -1; | |
200 | + core = getlong(&freq.fq); | |
201 | + peripheral = getlong(&freq.pf); | |
202 | + VERBOSE_PRINT("Core %dHz / Pereipheral %dHz\n", core, peripheral); | |
203 | + return peripheral; | |
204 | +} | |
205 | + | |
206 | +/* bitrate candidate list */ | |
207 | +static const int rate_list[]={115200,57600,38400,19200,9600}; | |
208 | + | |
209 | +/* bitrate error margine (%) */ | |
210 | +#define ERR_MARGIN 4 | |
211 | + | |
212 | +/* select communication bitrate */ | |
213 | +static int adjust_bitrate(int p_freq) | |
214 | +{ | |
215 | + int brr; | |
216 | + int errorrate; | |
217 | + int rate_no; | |
218 | + | |
219 | + for (rate_no = 0; rate_no < sizeof(rate_list) / sizeof(int); rate_no++) { | |
220 | + brr = p_freq / (32 * rate_list[rate_no]) - 2; | |
221 | + errorrate = abs(p_freq / ((brr + 1) * rate_list[rate_no] * 32)); | |
222 | + if (errorrate <= ERR_MARGIN) | |
223 | + return rate_list[rate_no]; | |
224 | + } | |
225 | + return 0; | |
226 | +} | |
227 | + | |
228 | +/* set target bitrate */ | |
229 | +static int set_bitrate(struct port_t *p, int bitrate) | |
230 | +{ | |
231 | + unsigned char cmd[] = {0x34, 0x00, 0x00, 0x00, 0x00}; | |
232 | + unsigned char rcv[6]; | |
233 | + setlong(cmd + 1, bitrate); | |
234 | + send(p, cmd, sizeof(cmd), SOH, ETX); | |
235 | + if (receive(p, rcv) != 0x34) | |
236 | + return 0; | |
237 | + | |
238 | + if (p->setbaud) { | |
239 | + if (!p->setbaud(bitrate / 100)) | |
240 | + return 0; | |
241 | + | |
242 | + } | |
243 | + usleep(10000); | |
244 | + return 1; | |
245 | +} | |
246 | + | |
247 | +#define C_MULNO 0 | |
248 | +#define P_MULNO 1 | |
249 | +#define C_FREQNO 0 | |
250 | +#define P_FREQNO 1 | |
251 | + | |
252 | +/* change communicate bitrate */ | |
253 | +static int change_bitrate(struct port_t *p, int peripheral_freq) | |
254 | +{ | |
255 | + int rate; | |
256 | + | |
257 | + | |
258 | + /* select bitrate from peripheral cock*/ | |
259 | + rate = adjust_bitrate(peripheral_freq); | |
260 | + if (rate == 0) | |
261 | + return 0; | |
262 | + | |
263 | + VERBOSE_PRINT("bitrate %d bps\n",rate); | |
264 | + | |
265 | + /* setup host/target bitrate */ | |
266 | + return set_bitrate(p, rate); | |
267 | +} | |
268 | + | |
269 | +static int syncro(struct port_t *p) | |
270 | +{ | |
271 | + unsigned char cmd[] = {0x00}; | |
272 | + unsigned char rcv[6]; | |
273 | + send(p, cmd, sizeof(cmd), SOH, ETX); | |
274 | + return receive(p, rcv) == 0x00; | |
275 | +} | |
276 | + | |
277 | +struct raw_signature_t { | |
278 | + uint8_t sod; | |
279 | + uint16_t len; | |
280 | + uint8_t res; | |
281 | + uint8_t dev[16]; | |
282 | + struct { | |
283 | + uint8_t type; | |
284 | + uint32_t size; | |
285 | + uint16_t num; | |
286 | + } __attribute__((packed,aligned(1))) bank[6] ; | |
287 | + uint8_t sum; | |
288 | + uint8_t etx; | |
289 | +} __attribute__((packed,aligned(1))); | |
290 | + | |
291 | +/* get target rom mapping */ | |
292 | +static struct arealist_t *get_arealist(struct port_t *p, enum mat_t mat) | |
293 | +{ | |
294 | + unsigned char cmd[] = {0x3a}; | |
295 | + struct raw_signature_t raw_sig; | |
296 | + unsigned int id[] = {0x00, 0x02}; | |
297 | + int numarea; | |
298 | + int i; | |
299 | + unsigned int addr = 0; | |
300 | + struct arealist_t *arealist; | |
301 | + | |
302 | + send(p, cmd, 1, SOH, ETX); | |
303 | + if (receive(p, (unsigned char *)&raw_sig) < 0) | |
304 | + return NULL; | |
305 | + send(p, cmd, 1, SOD, ETX); | |
306 | + if (receive(p, (unsigned char *)&raw_sig) < 0) | |
307 | + return NULL; | |
308 | + | |
309 | + /* lookup area */ | |
310 | + for(numarea = 0, i = 0; i < 6; i++) { | |
311 | + if (raw_sig.bank[i].type == id[mat]) | |
312 | + numarea += getword(&raw_sig.bank[i].num); | |
313 | + } | |
314 | + arealist = (struct arealist_t *)malloc(sizeof(struct arealist_t) + | |
315 | + sizeof(struct area_t) * numarea); | |
316 | + if (arealist == NULL) | |
317 | + return NULL; | |
318 | + | |
319 | + arealist->areas = numarea; | |
320 | + /* setup area list*/ | |
321 | + for(numarea = 0, i = 0; i < 6; i++) { | |
322 | + if (raw_sig.bank[i].type == id[mat]) { | |
323 | + unsigned int sz; | |
324 | + int j; | |
325 | + sz = getlong(&raw_sig.bank[i].size); | |
326 | + for(j = 0; j < getword(&raw_sig.bank[i].num); j++) { | |
327 | + arealist->area[numarea].start = addr - sz; | |
328 | + arealist->area[numarea].end = addr - 1; | |
329 | + arealist->area[numarea].size = sz; | |
330 | + if (!(arealist->area[numarea].image = malloc(sz))) | |
331 | + return NULL; | |
332 | + memset(arealist->area[numarea].image, 0xff, arealist->area[numarea].size); | |
333 | + addr -= sz; | |
334 | + numarea++; | |
335 | + } | |
336 | + } | |
337 | + } | |
338 | + return arealist; | |
339 | +} | |
340 | + | |
341 | +/* check blank page */ | |
342 | +static int skipcheck(unsigned char *data, unsigned short size) | |
343 | +{ | |
344 | + unsigned char r = 0xff; | |
345 | + int c; | |
346 | + for (c = 0; c < size; c++) | |
347 | + r &= *data++; | |
348 | + return (r == 0xff); | |
349 | +} | |
350 | + | |
351 | +/* write rom image */ | |
352 | +static int write_rom(struct port_t *port, struct arealist_t *arealist, enum mat_t mat) | |
353 | +{ | |
354 | + uint8_t erase[] = {0x12, 0x00, 0x00, 0x00, 0x00}; | |
355 | + uint8_t write[] = {0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
356 | + uint8_t data[257]; | |
357 | + unsigned char rcv[8]; | |
358 | + unsigned int wsize, total; | |
359 | + int i, j, r; | |
360 | + struct area_t *area; | |
361 | + for (total = 0, i = 0; i < arealist->areas; i++) { | |
362 | + total += arealist->area[i].size; | |
363 | + } | |
364 | + /* writing loop */ | |
365 | + for (wsize = 0, i = 0; i < arealist->areas; i++) { | |
366 | + area = &arealist->area[i]; | |
367 | + if (skipcheck(area->image, area->size)) { | |
368 | + wsize += area->size; | |
369 | + if (verbose) | |
370 | + printf("skip - %08x\n",area->start); | |
371 | + else { | |
372 | + printf("writing %d/%d byte\r", | |
373 | + wsize, | |
374 | + total); | |
375 | + fflush(stdout); | |
376 | + } | |
377 | + continue; | |
378 | + } | |
379 | + setlong(erase + 1, area->start); | |
380 | + send(port, erase, sizeof(erase), SOH, ETX); | |
381 | + if ((r=receive(port, rcv)) > 0x80) { | |
382 | + return -1; | |
383 | + } | |
384 | + setlong(write + 1, area->start); | |
385 | + setlong(write + 5, area->end); | |
386 | + send(port, write, sizeof(write), SOH, ETX); | |
387 | + if (receive(port, rcv) > 0x80) | |
388 | + return -1; | |
389 | + for(j = 0; j < area->size / 256; j++) { | |
390 | + data[0] = 0x13; | |
391 | + memcpy(&data[1], | |
392 | + area->image + j * (sizeof(data) - 1), | |
393 | + sizeof(data) -1); | |
394 | + if (j < (area->size / 256 -1)) | |
395 | + send(port, data, sizeof(data), SOD, ETB); | |
396 | + else | |
397 | + send(port, data, sizeof(data), SOD, ETX); | |
398 | + if ((r = receive(port, rcv)) > 0x80) { | |
399 | + return -1; | |
400 | + } | |
401 | + } | |
402 | + wsize += area->size; | |
403 | + if (verbose) | |
404 | + printf("write - %08x\n", area->start); | |
405 | + else { | |
406 | + printf("writing %d/%d byte\r", | |
407 | + wsize, | |
408 | + total); | |
409 | + fflush(stdout); | |
410 | + } | |
411 | + } | |
412 | + if (!verbose) | |
413 | + putc('\n', stdout); | |
414 | + | |
415 | + return 0; | |
416 | +} | |
417 | + | |
418 | +/* connect to target chip */ | |
419 | +static int setup_connection(struct port_t *p, int input_freq, char endian) | |
420 | +{ | |
421 | + struct devtype_t dt; | |
422 | + int e = -1; | |
423 | + int pf; | |
424 | + | |
425 | + input_freq *= 10000; | |
426 | + if(get_devtype(p, &dt) < 0) { | |
427 | + fputs("device type failed", stderr); | |
428 | + return -1; | |
429 | + } | |
430 | + switch(toupper(endian)) { | |
431 | + case 'L': | |
432 | + e = 1; | |
433 | + break; | |
434 | + case 'B': | |
435 | + e = 0; | |
436 | + break; | |
437 | + } | |
438 | + if (e == -1 || set_endian(p, e) < 0) { | |
439 | + fputs("endian setup failed", stderr); | |
440 | + return -1; | |
441 | + } | |
442 | + | |
443 | + pf = set_frequency(p, input_freq, dt.cpa); | |
444 | + if (pf < 0) { | |
445 | + fputs("frequency setup failed", stderr); | |
446 | + return -1; | |
447 | + } | |
448 | + | |
449 | + /* set writeing bitrate */ | |
450 | + if (!change_bitrate(p, pf)) { | |
451 | + fputs("set bitrate failed\n",stderr); | |
452 | + return -1; | |
453 | + } | |
454 | + | |
455 | + if (!syncro(p)) { | |
456 | + fputs("sync failed\n",stderr); | |
457 | + return -1; | |
458 | + } | |
459 | + | |
460 | + return 0; | |
461 | +} | |
462 | + | |
463 | +static void dump_configs(struct port_t *p) | |
464 | +{ | |
465 | + struct devtype_t dt; | |
466 | + | |
467 | + if(get_devtype(p, &dt) < 0) { | |
468 | + fputs("device type failed", stderr); | |
469 | + return; | |
470 | + } | |
471 | + printf("type code: %016llx\n", dt.typ); | |
472 | + printf("input max: %dHz\n", dt.osa); | |
473 | + printf("input min: %dHz\n", dt.osi); | |
474 | + printf("sys max: %dHz\n", dt.cpa); | |
475 | + printf("sys min: %dHz\n", dt.cpi); | |
476 | +} | |
477 | + | |
478 | +static struct comm_t v2 = { | |
479 | + .get_arealist = get_arealist, | |
480 | + .write_rom = write_rom, | |
481 | + .setup_connection = setup_connection, | |
482 | + .dump_configs = dump_configs, | |
483 | +}; | |
484 | + | |
485 | +struct comm_t *comm_v2(void) | |
486 | +{ | |
487 | + return &v2; | |
488 | +} |
@@ -31,75 +31,13 @@ | ||
31 | 31 | #define PROGNAME "h8flash" |
32 | 32 | #define VERBOSE_PRINT(...) do { if (verbose) printf(__VA_ARGS__); } while(0) |
33 | 33 | |
34 | -#define ACK 0x06 | |
35 | - | |
36 | -#define QUERY_DEVICE 0x20 | |
37 | -#define QUERY_DEVICE_RES 0x30 | |
38 | -#define QUERY_CLOCKMODE 0x21 | |
39 | -#define QUERY_CLOCKMODE_RES 0x31 | |
40 | -#define QUERY_MULTIRATE 0x22 | |
41 | -#define QUERY_MULTIRATE_RES 0x32 | |
42 | -#define QUERY_FREQ 0x23 | |
43 | -#define QUERY_FREQ_RES 0x33 | |
44 | -#define QUERY_BOOT_AREA 0x24 | |
45 | -#define QUERY_BOOT_AREA_RES 0x34 | |
46 | -#define QUERY_USER_AREA 0x25 | |
47 | -#define QUERY_USER_AREA_RES 0x35 | |
48 | -#define QUERY_WRITESIZE 0x27 | |
49 | -#define QUERY_WRITESIZE_RES 0x37 | |
50 | - | |
51 | -#define SELECT_DEVICE 0x10 | |
52 | -#define SET_CLOCKMODE 0x11 | |
53 | - | |
54 | -#define SET_BITRATE 0x3f | |
55 | - | |
56 | -#define WRITEMODE 0x40 | |
57 | -#define WRITE_USERBOOT 0x42 | |
58 | -#define WRITE_USER 0x43 | |
59 | -#define BLANKCHECK_USERBOOT 0x4c | |
60 | -#define BLANKCHECK_USER 0x4d | |
61 | -#define WRITE 0x50 | |
62 | - | |
63 | 34 | enum mat_t {user, userboot}; |
64 | 35 | |
65 | -struct devinfo_t { | |
66 | - char code[4]; | |
67 | - char name[256]; | |
68 | -}; | |
69 | - | |
70 | -struct devicelist_t { | |
71 | - int numdevs; | |
72 | - struct devinfo_t devs[0]; | |
73 | -}; | |
74 | - | |
75 | -struct clockmode_t { | |
76 | - int nummode; | |
77 | - int mode[0]; | |
78 | -}; | |
79 | - | |
80 | -struct multirate_t { | |
81 | - int numrate; | |
82 | - int rate[0]; | |
83 | -}; | |
84 | - | |
85 | -struct multilist_t { | |
86 | - int nummulti; | |
87 | - struct multirate_t *muls[0]; | |
88 | -}; | |
89 | - | |
90 | -struct freq_t { | |
91 | - int min; | |
92 | - int max; | |
93 | -}; | |
94 | - | |
95 | -struct freqlist_t { | |
96 | - int numfreq; | |
97 | - struct freq_t freq[0]; | |
98 | -}; | |
99 | - | |
100 | 36 | struct area_t { |
101 | 37 | unsigned int start; |
102 | 38 | unsigned int end; |
39 | + int size; | |
40 | + char *image; | |
103 | 41 | }; |
104 | 42 | |
105 | 43 | struct arealist_t { |
@@ -107,12 +45,6 @@ struct arealist_t { | ||
107 | 45 | struct area_t area[0]; |
108 | 46 | }; |
109 | 47 | |
110 | -struct writeinfo_t { | |
111 | - enum mat_t mat; | |
112 | - struct area_t area; | |
113 | - int size; | |
114 | -}; | |
115 | - | |
116 | 48 | enum port_type {serial, usb}; |
117 | 49 | |
118 | 50 | struct port_t { |
@@ -125,19 +57,17 @@ struct port_t { | ||
125 | 57 | void (*close)(void); |
126 | 58 | }; |
127 | 59 | |
60 | +struct comm_t { | |
61 | + struct arealist_t *(*get_arealist)(struct port_t *port, enum mat_t mat); | |
62 | + int (*write_rom)(struct port_t *port, struct arealist_t *arealist, | |
63 | + enum mat_t mat); | |
64 | + int (*setup_connection)(struct port_t *port, int input_freq, char endian); | |
65 | + void (*dump_configs)(struct port_t *p); | |
66 | +}; | |
67 | + | |
128 | 68 | struct port_t *open_serial(char *portname); |
129 | 69 | struct port_t *open_usb(unsigned short vid, unsigned short pid); |
130 | -struct devicelist_t *get_devicelist(struct port_t *port); | |
131 | -struct clockmode_t *get_clockmode(struct port_t *port); | |
132 | -struct multilist_t *get_multirate(struct port_t *port); | |
133 | -struct freqlist_t *get_freqlist(struct port_t *port); | |
134 | -struct arealist_t *get_arealist(struct port_t *port, enum mat_t mat); | |
135 | -int get_writesize(struct port_t *port); | |
136 | -int select_device(struct port_t *port, const char *code); | |
137 | -int set_clockmode(struct port_t *port, int mode); | |
138 | -int write_rom(struct port_t *port, const unsigned char *romimage, | |
139 | - struct writeinfo_t *writeinfo); | |
140 | -int setup_connection(struct port_t *port, int input_freq); | |
141 | -void dump_configs(struct port_t *p); | |
70 | +struct comm_t *comm_v1(); | |
71 | +struct comm_t *comm_v2(); | |
142 | 72 | |
143 | 73 | extern int verbose; |
@@ -38,6 +38,7 @@ const static struct option long_options[] = { | ||
38 | 38 | {"binary", no_argument, NULL, 'b'}, |
39 | 39 | {"verbose", no_argument, NULL, 'V'}, |
40 | 40 | {"list", no_argument, NULL, 'l'}, |
41 | + {"endian", required_argument, NULL, 'e'}, | |
41 | 42 | {0, 0, 0, 0} |
42 | 43 | }; |
43 | 44 |
@@ -47,40 +48,59 @@ static void usage(void) | ||
47 | 48 | "[-b][--userboot][-l][-V] filename"); |
48 | 49 | } |
49 | 50 | |
51 | +static struct area_t *lookup_area(struct arealist_t *arealist, | |
52 | + unsigned int addr) | |
53 | +{ | |
54 | + int i; | |
55 | + for (i = 0; i < arealist->areas; i++) { | |
56 | + if (arealist->area[i].start <= addr && | |
57 | + arealist->area[i].end >= addr) | |
58 | + return &arealist->area[i]; | |
59 | + } | |
60 | + return NULL; | |
61 | +} | |
62 | + | |
50 | 63 | /* read raw binary */ |
51 | -static int write_binary(FILE *fp, struct writeinfo_t *writeinfo, | |
52 | - struct port_t *p) | |
64 | +static int write_binary(FILE *fp, struct comm_t *com, | |
65 | + struct port_t *p, struct arealist_t *arealist, | |
66 | + enum mat_t mat) | |
53 | 67 | { |
54 | 68 | int fno; |
55 | 69 | struct stat bin_st; |
56 | - unsigned char *bin_buf; | |
57 | - unsigned long bin_len; | |
70 | + size_t bin_len, len; | |
71 | + unsigned int addr; | |
72 | + struct area_t *area; | |
58 | 73 | |
59 | 74 | fno = fileno(fp); |
60 | 75 | |
61 | 76 | fstat(fno, &bin_st); |
62 | 77 | bin_len = bin_st.st_size; |
63 | - | |
64 | - if ((bin_buf = (unsigned char *)mmap(NULL, bin_len, PROT_READ, | |
65 | - MAP_SHARED, fno, 0)) == MAP_FAILED) | |
66 | - goto error_perror; | |
67 | - writeinfo->area.end = bin_len - 1; | |
68 | - if (!write_rom(p, bin_buf, writeinfo)) | |
78 | + addr = arealist->area[0].start; | |
79 | + | |
80 | + while(bin_len > 0) { | |
81 | + area = lookup_area(arealist, addr); | |
82 | + len = bin_len < (area->end - area->start)? | |
83 | + bin_len:(area->end - area->start); | |
84 | + if (len > read(area->image, len, fno)) | |
85 | + goto error_perror; | |
86 | + bin_len -= len; | |
87 | + addr += len; | |
88 | + } | |
89 | + if (!com->write_rom(p, arealist, mat)) | |
69 | 90 | goto error; |
70 | - munmap(bin_buf, bin_len); | |
71 | 91 | fclose(fp); |
72 | 92 | return bin_len; |
73 | 93 | error_perror: |
74 | 94 | perror(PROGNAME); |
75 | 95 | error: |
76 | - if (bin_buf) | |
77 | - munmap(bin_buf, bin_len); | |
78 | 96 | fclose(fp); |
79 | 97 | return 0; |
80 | 98 | } |
81 | 99 | |
82 | 100 | /* read srec binary */ |
83 | -static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, struct port_t *p) | |
101 | +static int write_srec(FILE *fp, struct comm_t *com, | |
102 | + struct port_t *p, struct arealist_t *arealist, | |
103 | + enum mat_t mat) | |
84 | 104 | { |
85 | 105 | unsigned char *romimage = NULL; |
86 | 106 | unsigned char *bufp; |
@@ -95,15 +115,7 @@ static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, struct port_t *p) | ||
95 | 115 | const static int address_len[]={0,4,6,8,0,0,0,8,6,4}; |
96 | 116 | int r = 0; |
97 | 117 | int l; |
98 | - unsigned int romsize; | |
99 | - | |
100 | - romsize = writeinfo->area.end - writeinfo->area.start + 1; | |
101 | - romimage = (unsigned char *)malloc(romsize); | |
102 | - if (!romimage) { | |
103 | - perror(PROGNAME); | |
104 | - goto error; | |
105 | - } | |
106 | - memset(romimage, 0xff, romsize); | |
118 | + struct area_t *area; | |
107 | 119 | |
108 | 120 | while (fgets(linebuf, sizeof(linebuf), fp)) { |
109 | 121 | /* check valid Srecord */ |
@@ -132,16 +144,12 @@ static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, struct port_t *p) | ||
132 | 144 | sum += strtoul(hexbuf, NULL, 16); |
133 | 145 | } |
134 | 146 | |
135 | - /* area check */ | |
136 | - if (addr < writeinfo->area.start || | |
137 | - (addr + len - 1) > writeinfo->area.end) { | |
138 | - fprintf(stderr, | |
139 | - "srec address %08x is out of rom\n", addr); | |
147 | + area = lookup_area(arealist, addr); | |
148 | + if (area == NULL) { | |
149 | + fprintf(stderr, "%08x is out of ROM.", addr); | |
140 | 150 | goto error; |
141 | 151 | } |
142 | - bufp = romimage + addr - writeinfo->area.start; | |
143 | - if (last_addr < (addr + len - 1)) | |
144 | - last_addr = (addr + len - 1); | |
152 | + bufp = area->image + addr - area->start; | |
145 | 153 | |
146 | 154 | /* parse body */ |
147 | 155 | for (; len > 1; --len, lp += 2, buff_size++) { |
@@ -163,36 +171,29 @@ static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, struct port_t *p) | ||
163 | 171 | goto error; |
164 | 172 | } |
165 | 173 | } |
166 | - writeinfo->area.end = last_addr; | |
167 | - r = write_rom(p, romimage, writeinfo); | |
174 | + r = com->write_rom(p, arealist, mat); | |
168 | 175 | error: |
169 | - free(romimage); | |
170 | 176 | fclose(fp); |
171 | 177 | return r; |
172 | 178 | } |
173 | 179 | |
174 | 180 | #ifdef HAVE_GELF_H |
175 | -static int write_elf(FILE *fp, struct writeinfo_t *writeinfo, | |
176 | - struct port_t *p) | |
181 | +static int write_elf(FILE *fp, struct comm_t *com, | |
182 | + struct port_t *p, struct arealist_t *arealist, | |
183 | + enum mat_t mat) | |
177 | 184 | { |
178 | 185 | unsigned char *romimage = NULL; |
179 | 186 | unsigned int romsize; |
180 | 187 | int fd; |
181 | 188 | size_t n; |
182 | - int i; | |
189 | + int i,j; | |
183 | 190 | Elf *elf = NULL; |
184 | 191 | GElf_Phdr phdr; |
185 | - unsigned long last_addr = 0; | |
192 | + unsigned long top, last_addr = 0; | |
186 | 193 | int ret = -1; |
187 | - size_t sz; | |
188 | - | |
189 | - romsize = writeinfo->area.end - writeinfo->area.start + 1; | |
190 | - romimage = (unsigned char *)malloc(romsize); | |
191 | - if (!romimage) { | |
192 | - perror(PROGNAME); | |
193 | - goto error; | |
194 | - } | |
195 | - memset(romimage, 0xff, romsize); | |
194 | + size_t sz, remain; | |
195 | + struct area_t *area; | |
196 | + | |
196 | 197 | elf_version(EV_CURRENT); |
197 | 198 | fd = fileno(fp); |
198 | 199 | elf = elf_begin(fd, ELF_C_READ, NULL); |
@@ -219,37 +220,42 @@ static int write_elf(FILE *fp, struct writeinfo_t *writeinfo, | ||
219 | 220 | } |
220 | 221 | if (phdr.p_filesz == 0) |
221 | 222 | continue ; |
222 | - if (phdr.p_paddr < writeinfo->area.start || | |
223 | - (phdr.p_paddr + phdr.p_filesz) > writeinfo->area.end) { | |
224 | - fprintf(stderr, "%08lx - %08lx is out of rom\n", | |
225 | - (unsigned long)phdr.p_paddr, | |
226 | - (unsigned long)(phdr.p_paddr + phdr.p_filesz)); | |
227 | - goto error; | |
228 | - } | |
229 | 223 | lseek(fd, phdr.p_offset, SEEK_SET); |
230 | - sz = read(fd, romimage + (phdr.p_paddr - writeinfo->area.start), | |
231 | - phdr.p_filesz); | |
232 | - if (sz != phdr.p_filesz) { | |
233 | - fputs("File read error", stderr); | |
234 | - goto error; | |
224 | + remain = phdr.p_filesz; | |
225 | + top = phdr.p_paddr; | |
226 | + while(remain > 0) { | |
227 | + area = lookup_area(arealist, top); | |
228 | + if (area == NULL) { | |
229 | + fprintf(stderr, "%08x - %08x is out of ROM", | |
230 | + top, top + remain); | |
231 | + goto error; | |
232 | + } | |
233 | + j = remain < (area->end - area->start)? | |
234 | + remain:(area->size); | |
235 | + sz = read(fd, area->image + top - area->start, j); | |
236 | + if (sz != j) { | |
237 | + perror(PROGNAME); | |
238 | + goto error; | |
239 | + } | |
240 | + remain -= j; | |
241 | + top += j; | |
235 | 242 | } |
236 | - if (last_addr < (phdr.p_paddr + phdr.p_filesz)) | |
237 | - last_addr = phdr.p_paddr + phdr.p_filesz; | |
238 | 243 | } |
239 | - writeinfo->area.end = last_addr; | |
240 | - ret = write_rom(p, romimage, writeinfo); | |
244 | + ret = com->write_rom(p, arealist, mat); | |
241 | 245 | error: |
242 | 246 | if (elf) |
243 | 247 | elf_end(elf); |
244 | 248 | fclose(fp); |
245 | - free(romimage); | |
246 | 249 | return ret; |
247 | 250 | } |
248 | 251 | #endif |
249 | 252 | |
250 | 253 | /* read rom writing data */ |
251 | -static int writefile_to_rom(char *fn, int force_binary, struct writeinfo_t *writeinfo, | |
252 | - struct port_t *port) | |
254 | +static int writefile_to_rom(char *fn, int force_binary, | |
255 | + struct comm_t *com, | |
256 | + struct port_t *port, | |
257 | + struct arealist_t *arealist, | |
258 | + enum mat_t mat) | |
253 | 259 | { |
254 | 260 | FILE *fp = NULL; |
255 | 261 | static char linebuf[SREC_MAXLEN + 1]; |
@@ -276,13 +282,13 @@ static int writefile_to_rom(char *fn, int force_binary, struct writeinfo_t *writ | ||
276 | 282 | #ifdef HAVE_GELF_H |
277 | 283 | /* check ELF */ |
278 | 284 | if (!force_binary && memcmp(linebuf, ELFMAG, SELFMAG) == 0) |
279 | - return write_elf(fp, writeinfo, port); | |
285 | + return write_elf(fp, com, port, arealist, mat); | |
280 | 286 | #endif |
281 | 287 | /* check 'S??' */ |
282 | 288 | if (force_binary || |
283 | 289 | linebuf[0] != 'S' || |
284 | 290 | isdigit(linebuf[1]) == 0) |
285 | - return write_binary(fp, writeinfo, port); | |
291 | + return write_binary(fp, com, port, arealist, mat); | |
286 | 292 | |
287 | 293 | /* check body (calcurate checksum) */ |
288 | 294 | memcpy(hexbuf, &linebuf[2], 2); |
@@ -293,53 +299,43 @@ static int writefile_to_rom(char *fn, int force_binary, struct writeinfo_t *writ | ||
293 | 299 | } |
294 | 300 | if ((sum & 0xff) == 0xff) |
295 | 301 | /* checksum ok is Srecord format */ |
296 | - return write_srec(fp, writeinfo, port); | |
302 | + return write_srec(fp, com, port, arealist, mat); | |
297 | 303 | else |
298 | - return write_binary(fp, writeinfo, port); | |
304 | + return write_binary(fp, com, port, arealist, mat); | |
299 | 305 | } |
300 | 306 | |
301 | 307 | /* get target rommap */ |
302 | -static int get_rominfo(struct port_t *port, struct writeinfo_t *writeinfo) | |
308 | +static struct arealist_t *get_rominfo(struct comm_t *com, struct port_t *port, | |
309 | + enum mat_t mat) | |
303 | 310 | { |
304 | 311 | struct arealist_t *arealist = NULL; |
305 | 312 | int c; |
306 | 313 | |
307 | 314 | /* get target rommap list */ |
308 | - arealist = get_arealist(port, writeinfo->mat); | |
315 | + arealist = com->get_arealist(port, mat); | |
309 | 316 | if (arealist == NULL) { |
310 | 317 | if (errno != 0) |
311 | 318 | perror(PROGNAME); |
312 | 319 | else |
313 | - fputs("area list error\n",stderr); | |
314 | - return 0; | |
320 | + fputs("area list error\n", stderr); | |
321 | + return NULL; | |
315 | 322 | } |
316 | 323 | if (verbose) { |
317 | 324 | printf("area map\n"); |
318 | 325 | for (c = 0; c < arealist->areas; c++) |
319 | - printf("%08x - %08x\n", arealist->area[c].start, | |
320 | - arealist->area[c].end); | |
326 | + printf("%08x - %08x %08xbyte\n", | |
327 | + arealist->area[c].start, | |
328 | + arealist->area[c].end, | |
329 | + arealist->area[c].size); | |
321 | 330 | } |
322 | 331 | |
323 | 332 | /* check write area info */ |
324 | - if (arealist->areas < SELAREA) { | |
333 | + if (arealist->areas < 0) { | |
325 | 334 | fputs("illigal areamap\n", stderr); |
326 | 335 | free(arealist); |
327 | - return 0; | |
336 | + return NULL; | |
328 | 337 | } |
329 | - writeinfo->area = arealist->area[SELAREA]; | |
330 | - free(arealist); | |
331 | - | |
332 | - /* get writeing size */ | |
333 | - writeinfo->size = get_writesize(port); | |
334 | - if (writeinfo->size < 0) { | |
335 | - if (errno != 0) | |
336 | - perror(PROGNAME); | |
337 | - else | |
338 | - fputs("writesize error\n", stderr); | |
339 | - return 0; | |
340 | - } | |
341 | - VERBOSE_PRINT("writesize %d byte\n", writeinfo->size); | |
342 | - return 1; | |
338 | + return arealist; | |
343 | 339 | } |
344 | 340 | |
345 | 341 | static int get_freq_num(const char *arg) |
@@ -372,24 +368,22 @@ int main(int argc, char *argv[]) | ||
372 | 368 | char port[FILENAME_MAX] = DEFAULT_SERIAL; |
373 | 369 | int c; |
374 | 370 | int long_index; |
375 | - int input_freq; | |
376 | - int force_binary; | |
377 | - int config_list; | |
371 | + int input_freq = 0; | |
372 | + int force_binary = 0; | |
373 | + int config_list = 0; | |
378 | 374 | int r; |
379 | - struct writeinfo_t writeinfo; | |
380 | 375 | struct port_t *p = NULL; |
381 | - | |
382 | - writeinfo.mat = user; | |
383 | - force_binary = 0; | |
384 | - input_freq = 0; | |
385 | - config_list = 0; | |
376 | + struct comm_t *com = NULL; | |
377 | + struct arealist_t *arealist; | |
378 | + enum mat_t mat = user; | |
379 | + char endian='l'; | |
386 | 380 | |
387 | 381 | /* parse argment */ |
388 | - while ((c = getopt_long(argc, argv, "p:f:bVl", | |
382 | + while ((c = getopt_long(argc, argv, "p:f:bVle:", | |
389 | 383 | long_options, &long_index)) >= 0) { |
390 | 384 | switch (c) { |
391 | 385 | case 'u': |
392 | - writeinfo.mat = userboot; | |
386 | + mat = userboot; | |
393 | 387 | break ; |
394 | 388 | case 'p': |
395 | 389 | strncpy(port, optarg, sizeof(port)); |
@@ -407,6 +401,13 @@ int main(int argc, char *argv[]) | ||
407 | 401 | case 'l': |
408 | 402 | config_list = 1; |
409 | 403 | break; |
404 | + case 'e': | |
405 | + endian = optarg[0]; | |
406 | + if (endian != 'l' && endian !='b') { | |
407 | + usage(); | |
408 | + return 1; | |
409 | + } | |
410 | + break; | |
410 | 411 | case '?': |
411 | 412 | usage(); |
412 | 413 | return 1; |
@@ -438,25 +439,38 @@ int main(int argc, char *argv[]) | ||
438 | 439 | if (p == NULL) |
439 | 440 | goto error; |
440 | 441 | |
442 | + switch (p->connect_target(port)) { | |
443 | + case 0xff: | |
444 | + r = -1; | |
445 | + goto error; | |
446 | + case 0xe6: | |
447 | + VERBOSE_PRINT("Detect old protocol\n"); | |
448 | + com = comm_v1(); | |
449 | + break; | |
450 | + case 0xc1: | |
451 | + VERBOSE_PRINT("Detect new protocol\n"); | |
452 | + com = comm_v2(); | |
453 | + break; | |
454 | + default: | |
455 | + fputs("unknown_target", stderr); | |
456 | + goto error; | |
457 | + } | |
458 | + | |
441 | 459 | if (config_list) { |
442 | - dump_configs(p); | |
460 | + com->dump_configs(p); | |
443 | 461 | p->close(); |
444 | 462 | return 0; |
445 | 463 | } |
446 | 464 | |
447 | - if (setup_connection(p, input_freq) < 0) | |
465 | + if (com->setup_connection(p, input_freq, endian) < 0) | |
448 | 466 | goto error; |
449 | 467 | puts("Connect target"); |
450 | 468 | |
451 | - if (!get_rominfo(p, &writeinfo)) | |
469 | + if (!(arealist = get_rominfo(com, p, mat))) | |
452 | 470 | goto error; |
453 | 471 | |
454 | - if (writefile_to_rom(argv[optind], force_binary, | |
455 | - &writeinfo, p)) { | |
456 | - VERBOSE_PRINT("write %08x - %08x ", writeinfo.area.start, | |
457 | - writeinfo.area.end); | |
458 | - r = 0; | |
459 | - } | |
472 | + r = writefile_to_rom(argv[optind], force_binary, | |
473 | + com, p, arealist, mat); | |
460 | 474 | error: |
461 | 475 | puts((r==0)?"done":"write failed"); |
462 | 476 | if (p) |
@@ -44,12 +44,12 @@ static int receive_byte(unsigned char *data) | ||
44 | 44 | fd_set fdset; |
45 | 45 | |
46 | 46 | *data = 0; |
47 | - tv.tv_sec = 60; | |
47 | + tv.tv_sec = 10; | |
48 | 48 | tv.tv_usec = 0; |
49 | 49 | FD_ZERO(&fdset); |
50 | 50 | FD_SET(ser_fd, &fdset); |
51 | 51 | r = select(ser_fd + 1, &fdset, NULL, NULL, &tv); |
52 | - if (r == -1) | |
52 | + if (r < 1) | |
53 | 53 | return -1; |
54 | 54 | return read(ser_fd, data, 1); |
55 | 55 | } |
@@ -110,15 +110,16 @@ static int connect_target(char *port) | ||
110 | 110 | } |
111 | 111 | } |
112 | 112 | putchar('\n'); |
113 | - return 0; | |
114 | - connect: | |
113 | + return 0xff; | |
114 | +connect: | |
115 | + putchar('\n'); | |
115 | 116 | /* connect done */ |
116 | 117 | buf[0] = 0x55; |
117 | 118 | write(ser_fd, buf, 1); |
118 | - if ((receive_byte(buf) == 1) && (buf[0] == 0xe6)) | |
119 | - return 1; /* ok */ | |
119 | + if (receive_byte(buf) == 1) | |
120 | + return buf[0]; /* ok */ | |
120 | 121 | else |
121 | - return 0; /* ng */ | |
122 | + return 0xff; /* ng */ | |
122 | 123 | } |
123 | 124 | |
124 | 125 | static void port_close(void) |