callback addr as u32 not a void ptr
[my-code/arm.git] / betty / lpcload.c
1 /*
2  * lpcload.c - load firmware into ram of lpc2220 via uart0
3  *
4  * author: hackbard@hackdaworld.org, rolf.anders@physik.uni-augsburg.de
5  *
6  * build: make
7  * usage: sudo ./lpcload -d /dev/ttyS0 -f firmware.hex -D0 fw0.bin [-v]
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <termios.h>
18
19 #define VERBOSE                 (1<<0)
20 #define FIRMWARE                (1<<1)
21 #define BANK0                   (1<<2)
22 #define BANK2                   (1<<3)
23 #define BL                      (1<<4)
24 #define FLASHFW                 (1<<5)
25 #define BINARY                  (1<<6)
26
27 #define BANK0_ADDR              0x80000000
28 #define BANK2_ADDR              0x82000000
29 #define BANK_SIZE               0x00100000
30 #define BL_ADDR                 0x7fffe000
31 #define BL_SIZE                 0x00002000
32
33 #define CMD_READ                'R'             // stay compatible to fwflash!
34 #define CMD_WRITE               'W'
35 #define CMD_CHIP_ERASE          'E'
36
37 #define TXRX_TYPE_SYNC          0x00
38 #define TXRX_TYPE_CKSM          0x00
39 #define TXRX_TYPE_BAUD          0x01
40 #define TXRX_TYPE_CMD           0x02
41 #define TXRX_TYPE_DATA          0x03
42 #define TXRX_TYPE_GO            0x04
43
44 #define CMD_SUCCESS             "0\r\n"
45 #define INVALID_COMMAND         "1\r\n"
46 #define SRC_ADDR_ERROR          "2\r\n"
47 #define DST_ADDR_ERROR          "3\r\n"
48 #define SRC_ADDR_NOT_MAPPED     "4\r\n"
49 #define DST_ADDR_NOT_MAPPED     "5\r\n"
50 #define COUNT_ERROR             "6\r\n"
51 #define COMPARE_ERROR           "10\r\n"
52 #define BUSY                    "11\r\n"
53 #define PARAM_ERROR             "12\r\n"
54 #define ADDR_ERROR              "13\r\n"
55 #define ADDR_NOT_MAPPED         "14\r\n"
56 #define CMD_LOCKED              "15\r\n"
57 #define INVALID_CODE            "16\r\n"
58 #define INVALID_BAUD_RATE       "17\r\n"
59 #define INVALID_STOP_BIT        "18\r\n"
60
61 #define RAM                     0x01
62 #define FLASH                   0x02
63
64 #define CRYSTFREQ               "10000"
65 #define RAMOFFSET               0x40000200
66
67 #define BUFSIZE                 128
68
69 typedef unsigned char u8;
70 typedef unsigned short u16;
71 typedef unsigned int u32;
72
73 typedef struct s_lpc {
74         int sfd;                /* serial fd */
75         char sdev[128];         /* seriel device */
76         int fwfd;               /* fimrware fd */
77         char fwfile[128];       /* firmware file */
78         u32 info;               /* info/mode */
79         char freq[8];           /* frequency */
80         char bank0[127];        /* flash dump bank0 */
81         int b0fd;               /* dumpfile fd bank0 */
82         char bank2[127];        /* flash dump bank2 */
83         int b2fd;               /* dumpfile fd bank0 */
84         char bl[127];           /* flash dump bootloader */
85         int blfd;               /* dumpfile fd bootloader */
86         char ffwfile[127];      /* file with firmware to be flashed */
87         int ffwfd;              /* fd of the above */
88         u32 roff;               /* ram offset of uc */
89         u32 jaddr;              /* addr for the jump */
90 } t_lpc;
91
92 void usage(void) {
93
94         printf("possible argv:\n");
95         printf("  -d  <serial device>\n");
96         printf("  -f  <firmware>\n");
97         printf("  -c  <crystal freq>\n");
98         printf("  -Dx <filename>\n");
99         printf("      x=0: bank0, x=2: bank2, x=b: bootloader\n");
100         printf("  -w <firmware which goes to flash>\n");
101         printf("  -b (if firmware for flash is a binary)\n");
102         printf("  -v\n");
103
104 }
105
106 int open_serial_device(t_lpc *lpc) {
107
108         struct termios term;
109
110         //memset(&term,0,sizeof(struct termios));
111
112         /* open serial device */
113
114         lpc->sfd=open(lpc->sdev,O_RDWR);
115         if(lpc->sfd<0) {
116                 perror("tts open");
117                 return lpc->sfd;
118         }
119
120         /* configure the serial device */
121
122         tcgetattr(lpc->sfd,&term);
123
124         // input/output baudrate
125
126         cfsetispeed(&term,B38400);
127         cfsetospeed(&term,B38400);
128
129         // control options -> 8n1
130
131         term.c_cflag&=~PARENB;  // no parity
132         term.c_cflag&=~CSTOPB;  // only 1 stop bit
133         term.c_cflag&=~CSIZE;   // no bit mask for data bits
134         term.c_cflag|=CS8;      // 8 data bits
135
136         // line options -> raw input
137         
138         term.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);
139
140         // input options -> enable flow control
141         
142         term.c_iflag&=~(INLCR|ICRNL|IXANY);
143         term.c_iflag|=(IXON|IXOFF);
144         
145         // output options
146
147         term.c_oflag=0;
148
149         // more control options -> timeout / flow control
150         
151         term.c_cc[VMIN]=0;
152         term.c_cc[VTIME]=20;    // 2 seconds timeout
153         //term.c_cc[VSTART]=0x11;
154         //term.c_cc[VSTOP]=0x13;
155
156         tcsetattr(lpc->sfd,TCSANOW,&term);
157
158         return lpc->sfd;
159 }
160
161 int reconfig_serial_device(t_lpc *lpc) {
162
163         struct termios term;
164         int ret;
165
166         /* reconfigure the serial device for our lousy loader tool */
167
168         tcgetattr(lpc->sfd,&term);
169
170         // disable flow control
171         
172         term.c_iflag&=~(IXON|IXOFF|IXANY|INLCR|ICRNL);
173
174         // change baudrate
175
176         cfsetispeed(&term,B115200);
177         cfsetospeed(&term,B115200);
178
179         // timeouts
180         
181         term.c_cc[VMIN]=0;
182         term.c_cc[VTIME]=100;   // 10 seconds timeout
183
184         ret=tcsetattr(lpc->sfd,TCSANOW,&term);
185
186         return ret;
187 }
188
189 int open_firmware(t_lpc *lpc) {
190
191         /* open firmware file */
192
193         lpc->fwfd=open(lpc->fwfile,O_RDONLY);
194
195         if(lpc->fwfd<0) {
196                 perror("fw open");
197                 return lpc->fwfd;
198         }
199
200         if(lpc->info&FLASHFW) {
201                 lpc->ffwfd=open(lpc->ffwfile,O_RDONLY);
202                 if(lpc->ffwfd<0) {
203                         perror("ffw open");
204                         return lpc->ffwfd;
205                 }
206         }
207
208         return lpc->fwfd;
209 }
210
211 int open_dumpfiles(t_lpc *lpc) {
212
213         /* open dumpfiles */
214
215         if(lpc->info&BANK0) {
216                 lpc->b0fd=open(lpc->bank0,O_WRONLY|O_CREAT);
217                 if(lpc->b0fd<0) {
218                         perror("bank0 dump file open");
219                         return lpc->b0fd;
220                 }
221         }
222
223         if(lpc->info&BANK2) {
224                 lpc->b2fd=open(lpc->bank2,O_WRONLY|O_CREAT);
225                 if(lpc->b2fd<0) {
226                         perror("bank2 dump file open");
227                         return lpc->b2fd;
228                 }
229         }
230
231         if(lpc->info&BL) {
232                 lpc->blfd=open(lpc->bl,O_WRONLY|O_CREAT);
233                 if(lpc->blfd<0) {
234                         perror("bootloader dump file open");
235                         return lpc->blfd;
236                 }
237         }
238
239         return 0;
240
241 }
242 int txrx(t_lpc *lpc,char *buf,int len,u8 type) {
243
244         int ret,cnt;
245         int i;
246
247         /* write */
248
249         if(lpc->info&VERBOSE)
250                 printf("  >> ");
251         cnt=0;
252         while(len) {
253                 ret=write(lpc->sfd,buf+cnt,len);
254                 if(ret<0) {
255                         perror("txrx write");
256                         return ret;
257                 }
258                 if(lpc->info&VERBOSE)
259                         for(i=0;i<ret;i++)
260                                 printf("%c",
261                                        ((buf[cnt+i]>0x19)&(buf[cnt+i]<0x7f))?
262                                        buf[cnt+i]:'.');
263                 len-=ret;
264                 cnt+=ret;
265         }
266         if(lpc->info&VERBOSE) {
267                 printf(" | ");
268                 for(i=0;i<cnt;i++)
269                         printf("%02x ",buf[i]);
270                 printf("| (%d)\n",cnt);
271         }
272
273
274
275         /* cut the echo if not of type auto baud */
276
277         if(type!=TXRX_TYPE_BAUD) {
278                 while(cnt) {
279                         ret=read(lpc->sfd,buf,cnt);
280                         if(ret<0) {
281                                 perror("txrx echo cut");
282                                 return ret;
283                         }
284                         cnt-=ret;
285                 }
286         }
287
288         /* return if type is go */
289
290         if(type==TXRX_TYPE_GO)
291                 return cnt;
292
293         /* return here if type is data */
294
295         if(type==TXRX_TYPE_DATA)
296                 return cnt;
297
298         /* read */
299
300         ret=read(lpc->sfd,buf,1);
301         if(ret<0) {
302                 perror("txrx read (first byte)");
303                 return ret;
304         }
305                 
306         switch(buf[0]) {
307                 case 'S':
308                         cnt=13;
309                         break;
310                 case 'O':
311                         cnt=3;
312                         break;
313                 case 'R':
314                         cnt=7;
315                         break;
316                 case '0':
317                         cnt=2;
318                         break;
319                 default:
320                         printf("txrx read: bad return byte '%02x'\n",buf[0]);
321                         break;
322         }
323
324         ret=1;
325         i=cnt;
326         while(i) {
327                 ret=read(lpc->sfd,buf+1+cnt-i,i);
328                 if(ret<0) {
329                         perror("txrx read (next bytes)");
330                         return ret;
331                 }
332                 i-=ret;
333         }
334         if(lpc->info&VERBOSE) {
335                 printf("  << ");
336                 for(i=0;i<cnt+1;i++)
337                         printf("%c",((buf[i]>0x19)&(buf[i]<0x7f))?
338                                     buf[i]:'.');
339                 printf(" | ");
340                 for(i=0;i<cnt+1;i++)
341                         printf("%02x ",buf[i]);
342                 printf("| (%d)\n",cnt+1);
343         }
344         buf[cnt+1]='\0';
345
346         /* check/strip return code if type is cmd */
347
348         if(type==TXRX_TYPE_CMD) {
349                 ret=strlen(CMD_SUCCESS);
350                 if(!strncmp(buf,CMD_SUCCESS,ret)) {
351                         for(i=ret;i<cnt;i++)
352                                 buf[i-ret]=buf[i];
353                         buf[cnt]='\0';
354                 }
355                 else {
356                         printf("txrx bad return code!\n");
357                         return -1;
358                 }
359         }
360
361         return cnt;
362 }
363
364 int bl_init(t_lpc *lpc) {
365
366         char buf[BUFSIZE];
367         int len;
368
369         /* auto baud sequence */
370         buf[0]='?';
371         txrx(lpc,buf,1,TXRX_TYPE_BAUD);
372         if(strncmp(buf,"Synchronized\r\n",14)) {
373                 printf("auto baud detection failed\n");
374                 return -1;
375         }
376
377         /* tell bl that we are synchronized (it's allready in buf) */
378         txrx(lpc,buf,14,TXRX_TYPE_SYNC);
379         if(strncmp(buf,"OK\r\n",4)) {
380                 printf("sync failed\n");
381                 return -1;
382         }
383
384         /* tell bl the crystal frequency */
385         len=strlen(lpc->freq)+2;
386         strncpy(buf,lpc->freq,BUFSIZE);
387         buf[len-2]='\r';
388         buf[len-1]='\n';
389         txrx(lpc,buf,len,TXRX_TYPE_SYNC);
390         if(strncmp(buf,"OK\r\n",4)) {
391                 printf("freq set failed\n");
392                 return -1;
393         }
394
395         return 0;
396 }
397
398 int unlock_go(t_lpc *lpc) {
399
400         char buf[BUFSIZE];
401         int ret;
402
403         memcpy(buf,"U 23130\r\n",9);
404         ret=txrx(lpc,buf,9,TXRX_TYPE_CMD);
405
406         return ret;
407 }
408
409 int go(t_lpc *lpc) {
410
411         char buf[BUFSIZE];
412         int ret,len;
413
414         snprintf(buf,BUFSIZE,"G %d A\r\n",lpc->jaddr);
415         len=strlen(buf);
416         ret=txrx(lpc,buf,len,TXRX_TYPE_GO);
417
418         return ret;
419 }
420
421 int uuencode(u8 *in,u8 *out,int len) {
422
423         out[0]=0x20+len;
424         out[1]=0x20+((in[0]>>2)&0x3f);
425         out[2]=0x20+(((in[0]<<4)|(in[1]>>4))&0x3f);
426         out[3]=0x20+(((in[1]<<2)|(in[2]>>6))&0x3f);
427         out[4]=0x20+(in[2]&0x3f);
428
429         return 0;
430 }
431
432 int write_to_ram(t_lpc *lpc,char *buf,u32 addr,int len) {
433
434         int lcount;
435         u32 checksum;
436         char txrxbuf[BUFSIZE];
437         int count,bcnt;
438         int nlen,slen;
439         int i;
440
441         /* check length */
442         if(len%4) {
443                 printf("ram write: not a multiple of 4\n");
444                 return -1;
445         }
446
447         /* make it a multiple of 3 (reason: uuencode) */
448         nlen=(!(len%3))?len:((len/3+1)*3);
449         if(nlen>BUFSIZE) {
450                 printf("ram write: too much data\n");
451                 return -1;
452         }
453         for(i=len;i<nlen;i++) buf[i]=0;
454
455         /* prepare addr */
456         addr+=lpc->roff;
457
458         /* prepare write command */
459         if(lpc->info&VERBOSE)
460                 printf("writing 0x%02x bytes to 0x%08x\n",len,addr);
461         snprintf(txrxbuf,BUFSIZE,"W %d %d\r\n",addr,len);
462         slen=strlen(txrxbuf);
463
464         /* send command and check return code */
465         txrx(lpc,txrxbuf,slen,TXRX_TYPE_CMD);
466
467         /* send data */
468         lcount=0;
469         bcnt=0;
470         count=0;
471         checksum=0;
472         while(bcnt<nlen) {
473
474                 /* uuencode / prepare data bytes */
475                 uuencode((u8 *)(buf+bcnt),(u8 *)(txrxbuf),
476                          (bcnt==nlen-3)?(len%3?len%3:3):3);
477                 txrxbuf[5]='\r';
478                 txrxbuf[6]='\n';
479
480                 /* checksum */
481                 checksum+=((u8)buf[bcnt]+(u8)buf[bcnt+1]+(u8)buf[bcnt+2]);
482
483                 /* send a data line */
484                 txrx(lpc,txrxbuf,7,TXRX_TYPE_DATA);
485
486                 /* increase counters */
487                 lcount+=1;
488                 bcnt+=3;
489                 count+=3;
490
491                 /* checksum */
492                 if((!(lcount%20))|(bcnt==nlen)) {
493                         /* send backtick */
494                         memcpy(txrxbuf,"`\r\n",3);
495                         //txrx(lpc,txrxbuf,3,TXRX_TYPE_DATA);
496                         /* send checksum */
497                         snprintf(txrxbuf,BUFSIZE,"%d\r\n",checksum);
498                         slen=strlen(txrxbuf);
499                         txrx(lpc,txrxbuf,slen,TXRX_TYPE_CKSM);
500                         if(!strncmp(txrxbuf,"RESE",4)) {
501                                 read(lpc->sfd,txrxbuf+4,4);
502                                 printf("ram write: resending ...\n");
503                                 bcnt-=count;
504                         }
505                         if(strncmp(txrxbuf,"OK\r\n",4)) {
506                                 printf("ram write: bad response\n");
507                                 return -1;
508                         }
509                         /* reset checksum & counter */
510                         checksum=0;
511                         count=0;
512                 }
513
514         }
515
516         return 0;
517 }
518
519 int send_cmd(int sfd,u32 addr,u32 len,u8 cmd) {
520
521         int ret,i,cnt,size;
522         int as,ls;
523         u8 send[9];
524
525         switch(cmd) {
526                 case CMD_READ:
527                 case CMD_WRITE:
528                         as=4;
529                         ls=4;
530                         break;
531                 case CMD_CHIP_ERASE:
532                         as=0;
533                         ls=1;
534                         break;
535                 default:
536                         printf("send cmd: cmd '%02x' not supported\n",cmd);
537                         return -1;
538         }
539
540         size=1+as+ls;
541         send[0]=cmd;
542
543         for(i=0;i<as;i++)
544                 send[1+i]=(addr>>((as-1-i)*8))&0xff;
545         for(i=0;i<ls;i++)
546                 send[1+i+as]=(len>>((ls-1-i)*8))&0xff;
547
548         cnt=0;
549         while(size) {
550                 ret=write(sfd,send+cnt,size);
551                 if(ret<0) {
552                         perror("dump file: send cmd ");
553                         return ret;
554                 }
555                 size-=ret;
556                 cnt+=ret;
557         }
558
559         /* flush  */
560         tcflush(sfd,TCIOFLUSH);
561
562         return 0;
563 }
564
565 int write_to_flash(t_lpc *lpc,u8 *buf,u32 addr,int len) {
566
567         int cnt,ret;
568         u8 cksml,cksmr;
569         int i;
570
571         /* prepare addr */
572         addr+=lpc->roff;
573
574         /* send cmd */
575         send_cmd(lpc->sfd,addr,len,CMD_WRITE);
576
577         /* transfer data */
578         cnt=0;
579         cksml=0;
580         while(len) {
581                 ret=write(lpc->sfd,buf+cnt,len);
582                 if(ret<0) {
583                         perror("transmit flash content (w)");
584                         return ret;
585                 }
586                 for(i=cnt;i<cnt+ret;i++)
587                         cksml+=buf[i];
588                 len-=ret;
589                 cnt+=ret;
590         }
591
592
593         /* check ack */
594         while(1) {
595                 ret=read(lpc->sfd,&cksmr,1);
596                 if(ret<0) {
597                         perror("write to flash: read cksm");
598                         return ret;
599                 }
600                 if(ret==1) break;
601         }
602         if(cksml!=cksmr) {
603                 printf("FATAL: wrong checksum or failure in flash write!\n");
604                 if(cksml+1==cksmr)
605                         printf(" -> most probably due to flash write!\n");
606                 else
607                         printf(" -> most probably failure in transfer!\n");
608                 printf(" addr:0x%08x l:%02x r:%02x\n",addr,cksml,cksmr);
609         }
610
611         return 0;
612 }
613
614 int firmware_to_mem(t_lpc *lpc,u8 memtype) {
615
616         char buf[BUFSIZE];
617         u32 addr,len,type;
618         int ret,temp;
619         int fd;
620
621         /* prepare for memory type */
622         if(memtype==RAM)
623                 fd=lpc->fwfd;
624         else if(memtype==FLASH)
625                 fd=lpc->ffwfd;
626         else
627                 return -1;
628
629         /* another evil hack to support binary format */
630         if((lpc->info&BINARY)&&(memtype==FLASH)) {
631                 addr=0;
632                 ret=1;
633                 while(ret) {
634                         ret=read(fd,buf,16);
635                         if(ret!=16) {
636                                 printf("D'OH ...\n");
637                                 return -1;
638                         }
639                         buf[16]='s'; // skip
640                         for(temp=0;temp<16;temp++)
641                                 if((u8)buf[temp]!=0xff)
642                                         buf[16]='w'; // write
643                         printf("addr:%08x\r",addr+lpc->roff);
644                         fflush(stdout);
645                         if(buf[16]=='w') 
646                                 write_to_flash(lpc,(u8 *)buf,addr,16);
647                         addr+=16;
648                 }
649                 return 0;
650         }
651
652         /* read a line */
653         ret=1;
654         while(ret) {
655                 /* sync line */
656                 ret=read(fd,buf,1);
657                 switch(buf[0]) {
658                         case '\r':
659                                 continue;
660                         case '\n':
661                                 continue;
662                         case ':':
663                                 /* start code */
664                                 break;
665                         default:
666                                 printf("fw to mem: no ihex format\n");
667                                 return -1;
668                 }
669                 /* read len */
670                 ret=read(fd,buf,2);
671                 sscanf(buf,"%02x",&len);
672                 /* read addr */
673                 ret=read(fd,buf,4);
674                 sscanf(buf,"%04x",&addr);
675                 /* read type */
676                 ret=read(fd,buf,2);
677                 sscanf(buf,"%02x",&type);
678                 /* successfull return if type is end of file */
679                 if(type==0x01)
680                         return 0;
681                 /* read data (and cksum) */
682                 ret=read(fd,buf,2*(len+1));
683                 if(ret!=(2*(len+1))) {
684                         printf("fw to mem: data missing\n");
685                                 return -1;
686                 }
687                 for(ret=0;ret<len;ret++) {
688                         sscanf(buf+2*ret,"%02x",&temp);
689                         buf[ret]=temp;
690                 }
691                 /* act according to type */
692                 switch(type) {
693                         //case 0x03:
694                         //      /* get cs and ip */
695                         //      break;
696                         case 0x00:
697                                 if(len%4) {
698                                         printf("fw to mem: invalid len\n");
699                                         return -1;
700                                 }
701                                 if(memtype==RAM)
702                                         write_to_ram(lpc,buf,addr,len);
703                                 else
704                                         write_to_flash(lpc,(u8 *)buf,addr,len);
705                                 break;
706                         case 0x04:
707                                 lpc->roff=((buf[0]<<24)|(buf[1]<<16));
708                                 break;
709                         case 0x05:
710                                 lpc->jaddr=((buf[0]<<24)|(buf[1]<<16));
711                                 lpc->jaddr|=((buf[2]<<8)|buf[3]);
712                                 break;
713                         default:
714                                 printf("fw to mem: unknown type %02x\n",type);
715                                 return -1;
716                 }
717         }
718
719         return 0;
720 }
721
722 int lpc_txbuf_flush(t_lpc *lpc) {
723
724         int i,ret;
725         u8 buf[16];
726
727         ret=1;
728         printf("flushing lpc tx buffer: ");
729         while(ret) {
730                 ret=read(lpc->sfd,buf,16);
731                 for(i=0;i<ret;i++)
732                         printf("%02x ",buf[i]);
733         }
734         printf("\n");
735
736         return 0;
737 }
738
739 int dump_files(int sfd,int dfd,u32 addr,u32 len) {
740
741         int ret;
742         int size;
743         int cnt;
744         u8 buf[16];
745
746         printf("dumping content (addr=0x%08x, len=0x%08x) ...\n",addr,len);
747
748         /* send the cmd */
749         send_cmd(sfd,addr,len,CMD_READ);
750
751         /* receive data and dump it to file */
752         ret=1;
753         cnt=0;
754         printf("  receiving data ...\n");
755         while(ret) {
756                 ret=read(sfd,buf,16);
757                 if(ret<0) {
758                         perror("dump file: read data");
759                         return ret;
760                 }
761                 size=ret;
762                 cnt=0;
763                 while(size) {
764                         ret=write(dfd,buf+cnt,size-cnt);
765                         if(ret<0) {
766                                 perror("dump file: write data");
767                                 return ret;
768                         }
769                         cnt+=ret;
770                         size-=ret;
771                 }
772         }
773
774         return 0;
775 }
776
777 int main(int argc,char **argv) {
778
779         t_lpc lpc;
780         int i;
781         int ret;
782
783         /*
784          * initial ... 
785          */
786
787         memset(&lpc,0,sizeof(t_lpc));
788         strncpy(lpc.freq,CRYSTFREQ,7);
789         lpc.roff=RAMOFFSET;
790         lpc.jaddr=RAMOFFSET;
791
792         /* parse argv */
793
794         for(i=1;i<argc;i++) {
795
796                 if(argv[i][0]!='-') {
797                         usage();
798                         return -1;
799                 }
800
801                 switch(argv[i][1]) {
802                         case 'd':
803                                 strncpy(lpc.sdev,argv[++i],127);
804                                 break;
805                         case 'f':
806                                 strncpy(lpc.fwfile,argv[++i],127);
807                                 lpc.info|=FIRMWARE;
808                                 break;
809                         case 'v':
810                                 lpc.info|=VERBOSE;
811                                 break;
812                         case 'c':
813                                 strncpy(lpc.freq,argv[++i],7);
814                                 break;
815                         case 'D':
816                                 if(argv[i][2]=='0') {
817                                         lpc.info|=BANK0;
818                                         strncpy(lpc.bank0,argv[++i],127);
819                                         break;
820                                 }
821                                 else if(argv[i][2]=='2') {
822                                         lpc.info|=BANK2;
823                                         strncpy(lpc.bank2,argv[++i],127);
824                                         break;
825                                 }
826                                 else if(argv[i][2]=='b') {
827                                         lpc.info|=BL;
828                                         strncpy(lpc.bl,argv[++i],127);
829                                         break;
830                                 }
831                                 else {
832                                         usage();
833                                         return -1;
834                                 }
835                         case 'w':
836                                 strncpy(lpc.ffwfile,argv[++i],127);
837                                 lpc.info|=FLASHFW;
838                                 break;
839                         case 'b':
840                                 lpc.info|=BINARY;
841                                 break;
842                         default:
843                                 usage();
844                                 return -1;
845                 }
846
847         }
848
849         /* open serial port */
850         if(open_serial_device(&lpc)<0)
851                 goto end;
852
853         /* boot loader init */
854         printf("boot loader init ...\n");
855         if(bl_init(&lpc)<0)
856                 return -1;
857
858         /* quit if there is no hex file to process */
859         if(!(lpc.info&FIRMWARE)) {
860                 printf("no firmware -> aborting\n");
861                 goto end;
862         }
863
864         /* open firmware file */
865         if(open_firmware(&lpc)<0)
866                 goto end;
867
868         /* open dump files */
869         if(open_dumpfiles(&lpc)<0)
870                 goto end;
871
872         /* parse intel hex file and write to ram */
873         printf("write firmware to ram ...\n");
874         firmware_to_mem(&lpc,RAM);
875
876         /* unlock go cmd */
877         printf("unlock go command ...\n");
878         unlock_go(&lpc);
879
880         /* go! */
881         printf("go ...\n");
882         ret=go(&lpc);
883
884         /* flush the lpc2220 tx buf */
885         lpc_txbuf_flush(&lpc);
886
887         /* reconfigure the serial port */
888         if(reconfig_serial_device(&lpc)<0)
889                 goto end;
890
891         /* download flash/bootloader content */
892         if(lpc.info&BANK0)
893                 dump_files(lpc.sfd,lpc.b0fd,BANK0_ADDR,BANK_SIZE);
894         if(lpc.info&BANK2)
895                 dump_files(lpc.sfd,lpc.b2fd,BANK2_ADDR,BANK_SIZE);
896         if(lpc.info&BL)
897                 dump_files(lpc.sfd,lpc.blfd,BL_ADDR,BL_SIZE);
898
899         /* write a firmware to the lpc flash */
900         if(lpc.info&FLASHFW) {
901                 printf("writing firmware to flash ...\n");
902                 send_cmd(lpc.sfd,0,'0',CMD_CHIP_ERASE);
903                 /* ack */
904                 ret=0;
905                 while(!ret)
906                         read(lpc.sfd,&ret,1);
907                 lpc.roff=BANK0_ADDR;
908                 firmware_to_mem(&lpc,FLASH);
909         }
910
911 end:
912         if(lpc.sfd)
913                 close(lpc.sfd);
914         if(lpc.fwfd)
915                 close(lpc.fwfd);
916         if(lpc.b0fd)
917                 close(lpc.b0fd);
918         if(lpc.b2fd)
919                 close(lpc.b2fd);
920         if(lpc.blfd)
921                 close(lpc.blfd);
922         if(lpc.ffwfd)
923                 close(lpc.ffwfd);
924
925         return 0;
926 }
927