]> rtime.felk.cvut.cz Git - sysless.git/blob - arch/h8300/generic/tools/tohit/tohit_fn.c
h8300: Make bloader work with ELF toolchain
[sysless.git] / arch / h8300 / generic / tools / tohit / tohit_fn.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <termios.h>
5 #include <sys/time.h>
6 #include <sys/types.h>
7 #include <sys/ioctl.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include "tohit_fn.h"
11 #include <boot_fn.h>
12
13 #define DEBUG 0
14 #define DEBUG_COUNT 0
15
16 int tohit_verbosity;
17
18 #define verbose(level, ...) \
19         do { if (tohit_verbosity >= (level)) { printf("tohit: " __VA_ARGS__); } } while (0)
20
21 //#define WITHOUT_CFSETSPEED
22
23 #ifdef WITHOUT_CFSETSPEED
24
25
26 struct rs232_speed_struct
27 {
28   speed_t value;
29   speed_t internal;
30 };
31
32 static const struct rs232_speed_struct rs232_speeds[] =
33   {
34 #ifdef B0
35     { 0, B0 },
36 #endif
37 #ifdef B50
38     { 50, B50 },
39 #endif
40 #ifdef B75
41     { 75, B75 },
42 #endif
43 #ifdef B110
44     { 110, B110 },
45 #endif
46 #ifdef B134
47     { 134, B134 },
48 #endif
49 #ifdef B150
50     { 150, B150 },
51 #endif
52 #ifdef B200
53     { 200, B200 },
54 #endif
55 #ifdef B300
56     { 300, B300 },
57 #endif
58 #ifdef B600
59     { 600, B600 },
60 #endif
61 #ifdef B1200
62     { 1200, B1200 },
63 #endif
64 #ifdef B1200
65     { 1200, B1200 },
66 #endif
67 #ifdef B1800
68     { 1800, B1800 },
69 #endif
70 #ifdef B2400
71     { 2400, B2400 },
72 #endif
73 #ifdef B4800
74     { 4800, B4800 },
75 #endif
76 #ifdef B9600
77     { 9600, B9600 },
78 #endif
79 #ifdef B19200
80     { 19200, B19200 },
81 #endif
82 #ifdef B38400
83     { 38400, B38400 },
84 #endif
85 #ifdef B57600
86     { 57600, B57600 },
87 #endif
88 #ifdef B76800
89     { 76800, B76800 },
90 #endif
91 #ifdef B115200
92     { 115200, B115200 },
93 #endif
94 #ifdef B153600
95     { 153600, B153600 },
96 #endif
97 #ifdef B230400
98     { 230400, B230400 },
99 #endif
100 #ifdef B307200
101     { 307200, B307200 },
102 #endif
103 #ifdef B460800
104     { 460800, B460800 },
105 #endif
106   };
107
108 /* Set both the input and output baud rates stored in *TERMIOS_P to SPEED.  */
109 int
110 rs232_cfsetspeed (struct termios *termios_p, speed_t speed)
111 {
112   size_t cnt;
113
114   for (cnt = 0; cnt < sizeof (rs232_speeds) / sizeof (rs232_speeds[0]); ++cnt)
115     if (speed == rs232_speeds[cnt].internal)
116       {
117         cfsetispeed (termios_p, speed);
118         cfsetospeed (termios_p, speed);
119         return 0;
120       }
121     else if (speed == rs232_speeds[cnt].value)
122       {
123         cfsetispeed (termios_p, rs232_speeds[cnt].internal);
124         cfsetospeed (termios_p, rs232_speeds[cnt].internal);
125         return 0;
126       }
127   /*__set_errno (EINVAL);*/
128
129   return -1;
130 }
131
132 #endif /* WITHOUT_CFSETSPEED */
133
134 /* Set right mode and speed for RS232 interface */
135 /*   baud can be either speed in character per second or special Bxxxx constant */
136 int rs232_setmode(int fd, int baud, int mode, int flowc)
137 {
138   struct termios ts;
139
140   /* Flush input and output queues. */
141   if (tcflush(fd, TCIOFLUSH) != 0) {
142     fprintf(stderr,"Error in tcflush\n");
143     return -1;
144   }     
145
146   /* Fetch the current terminal parameters. */
147   if (tcgetattr(fd, &ts) != 0) {
148     fprintf(stderr,"Error in tcgetattr\n");
149     return -1;
150   }     
151
152   /* Sets hardware control flags:                              */
153   /* 8 data bits                                               */
154   /* Enable receiver                                           */
155   /* Ignore CD (local connection)                              */
156   ts.c_cflag = CS8 | CREAD | CLOCAL;
157   if(flowc&1){
158     /* Use RTS/CTS flow control */
159     ts.c_cflag |= CRTSCTS; /* CCTS_OFLOW | CRTS_IFLOW */
160   }
161   ts.c_iflag = 0;
162   ts.c_oflag = NL0 | CR0 | TAB0 | BS0 | VT0 | FF0;
163   ts.c_lflag = 0;
164
165   /* set right ispeed and ospeed */
166  #ifdef WITHOUT_CFSETSPEED
167   if(rs232_cfsetspeed(&ts,baud)<0){
168     fprintf(stderr,"Error in rs232_cfsetspeed\n");
169     return -1;
170   }
171  #else /* WITHOUT_CFSETSPEED */
172   if(cfsetspeed(&ts,baud)<0){
173     fprintf(stderr,"Error in cfsetspeed\n");
174     return -1;
175   }
176  #endif /* WITHOUT_CFSETSPEED */
177
178   ts.c_cc[VINTR]    = '\0';
179   ts.c_cc[VQUIT]    = '\0';
180   ts.c_cc[VERASE]   = '\0';
181   ts.c_cc[VKILL]    = '\0';
182   ts.c_cc[VEOF]     = '\0';
183   ts.c_cc[VTIME]    = '\0';
184   ts.c_cc[VMIN]     = 1;
185   ts.c_cc[VSWTC]    = '\0';
186   ts.c_cc[VSTART]   = '\0';
187   ts.c_cc[VSTOP]    = '\0';
188   ts.c_cc[VSUSP]    = '\0';
189   ts.c_cc[VEOL]     = '\0';
190   ts.c_cc[VREPRINT] = '\0';
191   ts.c_cc[VDISCARD] = '\0';
192   ts.c_cc[VWERASE]  = '\0';
193   ts.c_cc[VLNEXT]   = '\0';
194   ts.c_cc[VEOL2]    = '\0';
195
196   /* Sets the new terminal parameters. */
197   if (tcsetattr(fd, TCSANOW, &ts) != 0) {
198     fprintf(stderr,"Error in tcsetattr\n");
199     return -1;
200   }     
201
202   return 0;
203 }
204
205 int rs232_sendch(int fd,unsigned char c)
206 {
207   verbose(3, " > sending 0x%02X\n", c);
208   if(write(fd, &c, 1) != 1){
209     fprintf(stderr,"Error in rs232_sendch\n");
210     return -1;
211   }     
212
213   return c;
214 }
215
216 int rs232_recch(int fd)
217
218   unsigned char c;
219   int trycount=10;
220 /*  const char *message; */
221   int recieved;
222   do{
223     recieved=read(fd, &c, 1); 
224
225   }while(trycount-- && (recieved==-1) && ((errno==EINTR)||(errno==EAGAIN)));
226   
227   if (trycount <= 0){
228     fprintf(stderr,"Timeout in rs232_recch\n");
229     return -1;
230   }     
231   if (recieved != 1){
232     fprintf(stderr,"Error in rs232_recch errno = %d\n", errno);
233     perror("rs232_recch");
234     printf("Read 0x%02X a recieved:%d \n",c,recieved);
235     return -1;
236   }     
237
238   verbose(3, " < read 0x%02X \n",c);
239
240   return c;
241 }
242
243 int rs232_test(int fd,int time)
244 {
245   struct timeval tv;
246   fd_set rfds;
247   int x;
248
249   if(time<tohit_waitrep)
250     time=tohit_waitrep;
251   tv.tv_sec = 0;
252   tv.tv_usec = time;
253   FD_ZERO(&rfds);
254   FD_SET(fd, &rfds);
255   x=select(fd + 1, &rfds, NULL, NULL, &tv);
256  #if DEBUG
257   printf("rs232_test %d ",x);
258  #endif
259   return x;
260 }
261
262 void tohit_sendi(int fd,long a, int bytes)
263 {
264   while(bytes--){
265     rs232_sendch(fd,(a>>(8*bytes)) & 0xFF);
266   }
267 }
268
269 long tohit_reci(int fd, int bytes)
270 {
271   unsigned long x=0;
272   unsigned long c;
273   while(bytes--){
274     rs232_test(fd,500000);
275     c=rs232_recch(fd);
276     if(c==-1) return -1;
277     x|=c<<(8*bytes);
278   }
279   return x;     
280 }       
281
282 int tohit_sendichk(int fd,long a, int bytes)
283 {
284   tohit_sendi(fd,a,bytes);
285   rs232_test(fd,500000);
286   if(tohit_reci(fd,bytes)!=a)
287     return -1;
288   return 0;
289 }
290
291 /* Synchronize with target */
292 int tohit_synchronize(int fd)
293 {
294   int i;
295   unsigned char c;
296   verbose(1, "Synchronizing with target\n");
297   i=10;
298   do{
299     c=0;
300     rs232_sendch(fd,c);
301
302     if(rs232_test(fd,500000)>0){
303       c=rs232_recch(fd);
304       if(c==0) break;
305     } 
306     i--;
307    #if DEBUG
308     printf("\n");
309    #endif
310   }while (i>0);
311
312   if (i==0){
313     printf("Error timeout\n");
314     return -3;
315   }     
316
317   /* Run 55=>AA synchronization */
318  #if DEBUG
319   printf("\n");
320  #endif
321   rs232_sendch(fd,0x55);
322   rs232_test(fd,500000);
323   c=rs232_recch(fd);
324  #if DEBUG
325   printf("\n");
326  #endif
327   if (c!=0xAA) {
328     printf("Error in AA reply\n");
329     return -4;
330   }     
331   return 0;
332 }
333
334 const char *cmd_name[] = {
335         [1+TOHIT_WRITEBB] = "WRITEBB",
336         [1+TOHIT_WRITE] = "WRITE",
337         [1+TOHIT_WRITEFL] = "WRITEFL",
338         [1+TOHIT_READ] = "READ",
339         [1+TOHIT_ERASEBL] = "ERASEBL",
340         [1+TOHIT_ERASEREG] = "ERASEREG",
341         [1+TOHIT_GOTO] = "GOTO",
342         [1+TOHIT_RESET] = "RESET"
343 };
344
345 const char *boot_err[] = {
346         [EBOOT_PROG_FAILURE] = "Flash programming failure (damaged flash?)",
347         [EBOOT_EXT_FLASH_VERIFY] = "External flash verify failed",
348         [EBOOT_FLASH_VERIFY] = "Flash verify failed",
349         [EBOOT_ROW_NOT_ERASED] = "Flash row was not erased",
350         [EBOOT_NO_FWE] = "Flash write not enabled (FWE pin)",
351         [EBOOT_ROW_BEGIN] = "Programming starts in the middle of a row",
352         [EBOOT_BLOCKADDR] = "Wrong flash block start/end address",
353         [EBOOT_BLNUM_HIGH] = "Flash block number to high",
354         [EBOOT_BLNUM_LOW] = "Flash block number to low (negative)",
355         [EBOOT_FLASH_ERROR] = "Flash error indicated",
356         [EBOOT_ERASE_FAILURE] = "Flash erase failure"
357 };
358
359 #define ARR_SIZE(x) (sizeof(x)/sizeof(x[0]))
360
361
362 int tohit_open4cmd(char *sdev, int baud, int cmd)
363 {
364   int fd;
365   int c;
366   
367   /* Open RS232 device */
368   if ((fd = open(sdev, O_RDWR | O_NONBLOCK)) == -1) {
369     printf("Error openning %s\n",sdev);
370     return -1;
371   }     
372
373   /* Set RS232 device mode and speed */
374   if(rs232_setmode(fd,baud,0,0)<0){
375     printf("Error in rs232_setmode\n");
376     return -1;
377   }
378
379   /* Synchronize with target */
380   if(tohit_synchronize(fd)<0){
381     printf("Error in tohit_synchronize\n");
382     return -1;
383   }
384   
385   if(cmd!=-1){
386     /* send cmd */
387           verbose(1, "Sending command 0x%02X (%s)\n", cmd, cmd_name[1+cmd]);
388     c=cmd | ((cmd ^ 7) << 3);
389     rs232_sendch(fd,c);
390     rs232_test(fd,500000);
391     if ((c | 0x80)!=rs232_recch(fd)) {
392       printf("Error in cmd reply\n");
393       return -4;
394     }   
395   }
396   return fd;
397 }
398
399 int tohit_cmdrepchk(int fd)
400 {
401   int res;
402   verbose(2, "Waiting for end reply\n");
403   rs232_test(fd,3000000);
404   res=rs232_recch(fd);
405   if(res<0){
406     printf("Error no end reply\n");
407     return -6;
408   }     
409   if (res!=0xAA && res!=0x5a) {
410           int err = (int)(signed char)res;
411           printf("Error in end reply - received 0x%02X == %d (%s)\n",
412                  res, err,
413                  (err < 0 && -err < ARR_SIZE(boot_err)) ? boot_err[-err] : NULL);
414     return -6;
415   }
416   return 0;
417 }
418
419 #define BLEN 0x40000
420
421 char *tohit_sdev="/dev/ttyS1";
422 int tohit_baud=4800;
423
424
425 int tohit_goto(unsigned long adr)
426 {
427   int fd;
428   if((fd=tohit_open4cmd(tohit_sdev, tohit_baud, TOHIT_GOTO))<0)
429   {
430     printf("Error in tohit_open4cmd\n");
431     close(fd);
432     return -1;
433   }
434
435   verbose(2, "Sending go address 0x%08lx\n", adr);
436   if (tohit_sendichk(fd,adr,4)<0) {
437     printf("Error in goto adr send and reply\n");
438     close(fd);
439     return -4;
440   }     
441   
442   close(fd);
443   return 1;
444 }
445
446 void print_flash_error(int err)
447 {
448   printf("Flash error: %s\n",
449          (err >= 0 && err < ARR_SIZE(boot_err)) ? boot_err[err] : "unknown error");
450 }
451
452 int tohit_writemem(int cmd, const unsigned char *buf, 
453                    unsigned long adr, unsigned long size, int blockmode)
454 {
455   int fd;
456   int count;
457   unsigned long i;
458   int j, k;
459   int c;
460   unsigned char rbuf[128];
461   
462   if((blockmode==1)||(blockmode>128)) blockmode=128;
463   
464   if((fd=tohit_open4cmd(tohit_sdev, tohit_baud, cmd))<0)
465   {
466     printf("Error in tohit_open4cmd\n");
467     close(fd);
468     return -1;
469   }
470   if(cmd==TOHIT_WRITEBB){
471     verbose(2, "Sending size 0x%04lx\n", size);
472     if (tohit_sendichk(fd,size,2)<0) {
473       printf("Error in start adr send and reply\n");
474       close(fd);
475       return -4;
476     }   
477   }else{
478     verbose(2, "Sending address 0x%08lx\n", adr);
479     if (tohit_sendichk(fd,adr,4)<0) {
480       printf("Error in start adr send and reply\n");
481       close(fd);
482       return -4;
483     }   
484     verbose(2, "Sending size 0x%08lx\n", size);
485     if (tohit_sendichk(fd,size,4)<0) {
486       printf("Error in size send and reply\n");
487       close(fd);
488       return -4;
489     }   
490   }
491
492  #if DEBUG
493   printf("Data send\n");
494  #endif /* DEBUG */
495   if(!blockmode){
496     verbose(2, "Writing in single byte mode\n");
497     for(i=0;i<size;i++){
498       rs232_sendch(fd,buf[i]);
499       rs232_test(fd,500000);
500       c=rs232_recch(fd);
501       if (c!=buf[i]) {
502         if (i % FLASH_ROW == FLASH_ROW-1) {
503           print_flash_error(rbuf[i]);
504         } else {
505           printf("Error in data reply (expected 0x%02x, received 0x%02x)\n", buf[i], c);
506         }
507         close(fd);
508         return -5;
509       } 
510       if((i%128)==0){
511         printf(".");
512         fflush(stdout);
513       }
514      #if DEBUG
515       printf("\n");
516      #endif
517     }
518   }else{        /*TOHIT_WRITEFL*/
519     i=0;
520     verbose(2, "Writing in block mode (block size=%d)\n", blockmode);
521     count=blockmode-(adr&(blockmode-1));
522     while(i<size){
523       if(count>(size-i)) count=size-i;
524       
525       verbose(3, " writing %d bytes\n",count);
526
527       j=0;
528       while(j<count){
529         k=write(fd, buf+i+j, count-j);
530         j+=k;
531         if((k<=0)||(j>count)){
532           perror("write");
533           printf("Error in blk write (%d,%d)\n",j,k);
534           close(fd);
535           return -2;
536         }
537       }
538
539       verbose(3, " reading %d bytes\n",count);
540       j=0;
541       do{
542         if ((i+j) % FLASH_ROW == FLASH_ROW - 1) {
543           verbose(3, " waiting for flashing a row\n");
544           rs232_test(fd,2/*sec*/*1000000);
545         } else {
546           rs232_test(fd,500000);
547         }
548         k=read(fd, rbuf+j, count-j);
549         if(k>=0) {
550           j+=k;
551         } else {
552           perror("read");
553           printf("Error in blk write - no reply (%d,%d)\n",j,k);
554           close(fd);
555           return -2;
556         }
557       }while(j<count);
558       if (tohit_verbosity < 3) {
559               printf(".");
560               fflush(stdout);
561       }
562       for(j=0;j<count;j++){
563         if (rbuf[j]!=buf[i+j]) {
564           if (i+j % FLASH_ROW == FLASH_ROW-1) {
565             print_flash_error(rbuf[j]);
566           } else {
567             printf("Error in data reply at position %d\n", j);
568
569             printf("Sent:    ");
570             for (k=j; k < count && k < j+8; k++)
571               printf(" 0x%02x", rbuf[j+k]);
572             printf("\nReceived:");
573             for (k=j; k < count && k < j+8; k++)
574               printf(" 0x%02x", buf[i+j+k]);
575             printf("\n");
576           }
577           close(fd);
578           return -5;
579         }       
580       }
581       i+=count;
582       count=blockmode;
583     }
584     printf("\n");
585   }     
586
587   if(tohit_cmdrepchk(fd)<0){
588     printf("Error no end reply\n");
589     close(fd);
590     return -4;
591   }     
592   close(fd);
593   return 1;
594 }
595
596 int tohit_readmem(int cmd, unsigned char *buf, 
597                   unsigned long adr, unsigned long size, int blockmode)
598 {
599   int fd;
600   unsigned long i;
601   int c,k,ret;
602   
603   if((fd=tohit_open4cmd(tohit_sdev, tohit_baud, cmd))<0)
604   {
605     printf("Error in tohit_open4cmd\n");
606     close(fd);
607     return -1;
608   }
609   verbose(2, "Sending address 0x%08lx\n", adr);
610   if (tohit_sendichk(fd,adr,4)<0) {
611     printf("Error in start adr send and reply\n");
612     close(fd);
613     return -4;
614   }     
615   verbose(2, "Sending size 0x%08lx\n", size);
616   if (tohit_sendichk(fd,size,4)<0) {
617     printf("Error in size send and reply\n");
618     close(fd);
619     return -4;
620   }
621   if(!blockmode){
622     /* Read memory by single byte */
623     for(i=0;i<size;i++){
624       rs232_test(fd,500000);
625       if((c=rs232_recch(fd))<0){
626         printf("Error in receive char\n");
627         close(fd);
628         return -4;
629       }
630       buf[i]=c;
631       rs232_sendch(fd,c);
632       if((i%128)==0){
633         printf(".");
634         fflush(stdout);
635       }
636      #if DEBUG
637       printf("\n");
638      #endif
639     }
640     printf("\n");
641
642     if(tohit_cmdrepchk(fd)<0){
643       printf("Error no end reply\n");
644       close(fd);
645       return -4;
646     }   
647   }else{
648     /* Read memory by blocks */
649     for(i=0;i<size;){
650       if(size-i>blockmode) c=blockmode;
651       else c=size-i;
652       for(k=0;k<c;k++)
653         while(rs232_sendch(fd,0)<0);
654       for(k=0;k<c;){
655         rs232_test(fd,500000);
656         ret=read(fd,buf+i+k,c-k);
657         if(ret<0){
658           printf("Error in block receive\n");
659           close(fd);
660           return -4;
661         }
662         k+=ret;
663       }
664       printf(".");
665       fflush(stdout);
666       i+=c;
667     }
668     if(rs232_recch(fd)!=0xff){
669       printf("Error no end reply\n");
670       close(fd);
671       return -4;
672     }   
673   }
674   close(fd);
675   return 1;
676 }
677
678 int tohit_blockerase(int block)
679 {
680   int fd;
681   
682   if((fd=tohit_open4cmd(tohit_sdev, tohit_baud, TOHIT_ERASEBL))<0)
683   {
684     printf("Error in tohit_open4cmd\n");
685     close(fd);
686     return -1;
687   }
688
689   verbose(2, "Sending block number: %d\n", block);
690   rs232_sendch(fd,block);
691   rs232_test(fd,2000000);
692   rs232_test(fd,2000000);
693
694   if(tohit_cmdrepchk(fd)<0){
695     printf("Error no end reply\n");
696     close(fd);
697     return -4;
698   }     
699   close(fd);
700   return 1;
701 }
702
703 int tohit_regerase(unsigned long adr, unsigned long size)
704 {
705   int fd;
706   
707   if((fd=tohit_open4cmd(tohit_sdev, tohit_baud, TOHIT_ERASEREG))<0)
708   {
709     printf("Error in tohit_open4cmd\n");
710     close(fd);
711     return -1;
712   }
713   verbose(2, "Sending start address 0x%08lx\n", adr);
714   if (tohit_sendichk(fd,adr,4)<0) {
715     printf("Error in start adr send and reply\n");
716     close(fd);
717     return -4;
718   }     
719   verbose(2, "Sending size 0x%08lx\n", size);
720   if (tohit_sendichk(fd,size,4)<0) {
721     printf("Error in size send and reply\n");
722     close(fd);
723     return -4;
724   }     
725
726   printf("\n");
727
728   if(tohit_cmdrepchk(fd)<0){
729     printf("Error no end reply\n");
730     close(fd);
731     return -4;
732   }     
733   close(fd);
734   return 1;
735 }
736
737 int tohit_reset(void)
738 {
739   int fd;
740   if((fd=tohit_open4cmd(tohit_sdev, tohit_baud, TOHIT_RESET))<0)
741   {
742     printf("Error in tohit_open4cmd\n");
743     close(fd);
744     return -1;
745   }
746   close(fd);
747   return 1;
748 }
749
750 int tohit_break(void)
751 {
752   int fd;
753   int i;
754   char c=0;
755
756   /* Open RS232 device */
757   if ((fd = open(tohit_sdev, O_RDWR | O_NONBLOCK)) == -1) {
758     printf("Error openning %s\n",tohit_sdev);
759     return -1;
760   }
761
762   if(rs232_setmode(fd,tohit_baud/2,0,0)<0)
763   {
764     close(fd);
765     return -1;
766   }
767   
768   verbose(1, "Sending break chars \n");
769
770   for(i=100;i--;)
771     write(fd,&c,1);
772   
773   close(fd);
774   return 1;
775 }