diff options
Diffstat (limited to 'main/common/xmodem.c')
-rw-r--r-- | main/common/xmodem.c | 1300 |
1 files changed, 665 insertions, 635 deletions
diff --git a/main/common/xmodem.c b/main/common/xmodem.c index af1ac3f..70be83c 100644 --- a/main/common/xmodem.c +++ b/main/common/xmodem.c @@ -1,7 +1,7 @@ /************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent - * + * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the @@ -27,12 +27,12 @@ * information about the file being downloaded (in partiuclar, the name). * YMODEM also supports BATCH downloads (multiple files downloaded in one * transaction). This code supports incoming BATCH downloads (not tested - * because I can't find any terminal emulators that do it), but not for + * because I can't find any terminal emulators that do it), but not for * uploads. * Minicom notes: * Minicom is the terminal emulation program that comes with Linux. - * For some reason I had to make some adjustments to the xmodem.c + * For some reason I had to make some adjustments to the xmodem.c * to accommodate Minicom... * - Minicom sends an initial 0x1a (EOF). Not sure why, so I just absorb * that now. @@ -51,7 +51,7 @@ * NAKs buffered up on the TTY. The end result is that if too many * NAKs have been queued up in the TTY's buffer, Minicom chokes on * them at startup. - * Adding the ability to slow down the NAK send rate keeps uMon from + * Adding the ability to slow down the NAK send rate keeps uMon from * sending too many NAKs prior to Minicom actually starting up its * side of the protocol; hence, Minicom doesn't choke and the transfer * works ok. @@ -89,47 +89,47 @@ * support functions (Xup, Xdown, etc..) for reference and update. */ struct xinfo { - uchar sno; /* Sequence number. */ - uchar pad; /* Unused, padding. */ - int xfertot; /* Running total of transfer. */ - int pktlen; /* Length of packet (128 or 1024). */ - int pktcnt; /* Running tally of number of packets processed. */ - int filcnt; /* Number of files transferred by ymodem. */ - long size; /* Size of upload. */ - ulong flags; /* Storage for various runtime flags. */ - ulong base; /* Starting address for data transfer. */ - ulong dataddr; /* Running address for data transfer. */ - int errcnt; /* Keep track of errors (used in verify mode). */ - int nakresend; /* Time between each NAK sent at Xdown startup. */ - char *firsterrat; /* Pointer to location of error detected when */ - /* transfer is in verify mode. */ - char fname[TFSNAMESIZE]; + uchar sno; /* Sequence number. */ + uchar pad; /* Unused, padding. */ + int xfertot; /* Running total of transfer. */ + int pktlen; /* Length of packet (128 or 1024). */ + int pktcnt; /* Running tally of number of packets processed. */ + int filcnt; /* Number of files transferred by ymodem. */ + long size; /* Size of upload. */ + ulong flags; /* Storage for various runtime flags. */ + ulong base; /* Starting address for data transfer. */ + ulong dataddr; /* Running address for data transfer. */ + int errcnt; /* Keep track of errors (used in verify mode). */ + int nakresend; /* Time between each NAK sent at Xdown startup. */ + char *firsterrat; /* Pointer to location of error detected when */ + /* transfer is in verify mode. */ + char fname[TFSNAMESIZE]; }; /* Runtime flags: */ -#define USECRC (1<<0) -#define VERIFY (1<<1) -#define YMODEM (1<<2) +#define USECRC (1<<0) +#define VERIFY (1<<1) +#define YMODEM (1<<2) /* Current xmodem operation: */ -#define XNULL 0 -#define XUP 1 -#define XDOWN 2 +#define XNULL 0 +#define XUP 1 +#define XDOWN 2 /* X/Ymodem protocol: */ -#define SOH 0x01 -#define STX 0x02 -#define EOT 0x04 -#define ACK 0x06 -#define NAK 0x15 -#define CAN 0x18 -#define EOF 0x1a -#define ESC 0x1b +#define SOH 0x01 +#define STX 0x02 +#define EOT 0x04 +#define ACK 0x06 +#define NAK 0x15 +#define CAN 0x18 +#define EOF 0x1a +#define ESC 0x1b -#define PKTLEN_128 128 -#define PKTLEN_1K 1024 +#define PKTLEN_128 128 +#define PKTLEN_1K 1024 -#define BYTE_TIMEOUT 1000 +#define BYTE_TIMEOUT 1000 static int Xup(struct xinfo *); static int Xdown(struct xinfo *); @@ -137,244 +137,252 @@ static int getPacket(uchar *,struct xinfo *); static int putPacket(uchar *,struct xinfo *); char *XmodemHelp[] = { - "Xmodem file transfer", - "-[a:BcdF:f:i:ks:uvy]", + "Xmodem file transfer", + "-[a:BcdF:f:i:ks:uvy]", #if INCLUDE_VERBOSEHELP - "Options:", - " -a{##} address (overrides default of APPRAMBASE)", + "Options:", + " -a{##} address (overrides default of APPRAMBASE)", #if INCLUDE_FLASH - " -B boot sector reload", + " -B boot sector reload", #endif - " -c use crc (default = checksum)", - " -d download", + " -c use crc (default = checksum)", + " -d download", #if INCLUDE_TFS - " -F{name} filename", - " -f{flags} file flags (see tfs)", - " -i{info} file info (see tfs)", + " -F{name} filename", + " -f{flags} file flags (see tfs)", + " -i{info} file info (see tfs)", #endif - " -k force packet length to 1K", - " -s{##} size (overrides computed size)", - " -u upload", - " -v verify only", + " -k force packet length to 1K", + " -s{##} size (overrides computed size)", + " -u upload", + " -v verify only", #if INCLUDE_TFS - " -y use Ymodem extensions", + " -y use Ymodem extensions", #endif - "Notes:", - " * Either -d or -u must be specified (-B implies -d).", - " * Each additional 'd' option cuts the nak-resend rate in half.", - " * XMODEM forces a 128-byte modulo on file size. The -s option", - " can be used to override this when transferring a file to TFS.", - " * File upload requires no address or size (size will be mod 128).", - " * When using -B, it should be the ONLY command line option,", - " it's purpose is to reprogram the boot sector, so be careful!", + "Notes:", + " * Either -d or -u must be specified (-B implies -d).", + " * Each additional 'd' option cuts the nak-resend rate in half.", + " * XMODEM forces a 128-byte modulo on file size. The -s option", + " can be used to override this when transferring a file to TFS.", + " * File upload requires no address or size (size will be mod 128).", + " * When using -B, it should be the ONLY command line option,", + " it's purpose is to reprogram the boot sector, so be careful!", #endif - (char *)0, + (char *)0, }; int Xmodem(int argc,char *argv[]) { - int opt, xop; - struct xinfo xi; + int opt, xop; + struct xinfo xi; #if INCLUDE_TFS - char *info = (char *)0; + char *info = (char *)0; char *flags = (char *)0; - TFILE *tfp; + TFILE *tfp; #endif #if INCLUDE_FLASH - int newboot = 0; + int newboot = 0; #endif #if INCLUDE_ETHERNET - int eon; + int eon; #endif - xop = XNULL; - xi.fname[0] = 0; - xi.size = 0; - xi.flags = 0; - xi.filcnt = 0; - xi.nakresend = 2; - xi.pktlen = PKTLEN_128; - xi.base = xi.dataddr = getAppRamStart(); - while ((opt=getopt(argc,argv,"a:BcdF:f:i:ks:uvy")) != -1) { - switch(opt) { - case 'a': - xi.dataddr = xi.base = strtoul(optarg,(char **)0,0); - break; - case 'B': - xop = XDOWN; + xop = XNULL; + xi.fname[0] = 0; + xi.size = 0; + xi.flags = 0; + xi.filcnt = 0; + xi.nakresend = 2; + xi.pktlen = PKTLEN_128; + xi.base = xi.dataddr = getAppRamStart(); + while((opt=getopt(argc,argv,"a:BcdF:f:i:ks:uvy")) != -1) { + switch(opt) { + case 'a': + xi.dataddr = xi.base = strtoul(optarg,(char **)0,0); + break; + case 'B': + xop = XDOWN; #if INCLUDE_FLASH - newboot = 1; + newboot = 1; #endif - break; - case 'c': - xi.flags |= USECRC; - break; - case 'd': - xi.nakresend *= 2; /* -ddd increases Xdown() resend delay */ - xop = XDOWN; - break; + break; + case 'c': + xi.flags |= USECRC; + break; + case 'd': + xi.nakresend *= 2; /* -ddd increases Xdown() resend delay */ + xop = XDOWN; + break; #if INCLUDE_TFS - case 'F': - strncpy(xi.fname,optarg,TFSNAMESIZE); - break; - case 'f': - flags = optarg; - break; - case 'i': - info = optarg; - break; + case 'F': + strncpy(xi.fname,optarg,TFSNAMESIZE); + break; + case 'f': + flags = optarg; + break; + case 'i': + info = optarg; + break; #endif - case 'k': - xi.pktlen = PKTLEN_1K; - break; - case 's': - xi.size = strtol(optarg,(char **)0,0); - break; - case 'u': - xop = XUP; - break; - case 'v': - xi.flags |= VERIFY; - break; + case 'k': + xi.pktlen = PKTLEN_1K; + break; + case 's': + xi.size = strtol(optarg,(char **)0,0); + break; + case 'u': + xop = XUP; + break; + case 'v': + xi.flags |= VERIFY; + break; #if INCLUDE_TFS - case 'y': - xi.flags |= (YMODEM | USECRC); - xi.pktlen = PKTLEN_1K; - break; + case 'y': + xi.flags |= (YMODEM | USECRC); + xi.pktlen = PKTLEN_1K; + break; #endif - default: - return(CMD_PARAM_ERROR); - } - } - - /* There should be no arguments after the option list. */ - if (argc != optind) - return(CMD_PARAM_ERROR); - - if (xop == XUP) { - if ((xi.flags & YMODEM) && !(xi.fname[0])) - printf("Ymodem upload needs filename\n"); - else { - if (xi.fname[0]) { /* Causes -a and -s options to be ignored. */ + default: + return(CMD_PARAM_ERROR); + } + } + + /* There should be no arguments after the option list. */ + if(argc != optind) { + return(CMD_PARAM_ERROR); + } + + if(xop == XUP) { + if((xi.flags & YMODEM) && !(xi.fname[0])) { + printf("Ymodem upload needs filename\n"); + } else { + if(xi.fname[0]) { /* Causes -a and -s options to be ignored. */ #if INCLUDE_TFS - tfp = tfsstat(xi.fname); - if (!tfp) { - printf("%s: file not found\n",xi.fname); - return(CMD_FAILURE); - } - xi.base = xi.dataddr = (ulong)TFS_BASE(tfp); - xi.size = TFS_SIZE(tfp); + tfp = tfsstat(xi.fname); + if(!tfp) { + printf("%s: file not found\n",xi.fname); + return(CMD_FAILURE); + } + xi.base = xi.dataddr = (ulong)TFS_BASE(tfp); + xi.size = TFS_SIZE(tfp); #endif - } -#ifdef DONT_DISABLE_ENET_IN_XMODEM /* See note at top of file */ - Xup(&xi); + } +#ifdef DONT_DISABLE_ENET_IN_XMODEM /* See note at top of file */ + Xup(&xi); #else #if INCLUDE_ETHERNET - eon = DisableEthernet(); + eon = DisableEthernet(); #endif - Xup(&xi); + Xup(&xi); #if INCLUDE_ETHERNET - if (eon) - EthernetStartup(0,0); + if(eon) { + EthernetStartup(0,0); + } #endif #endif - } - } - else if (xop == XDOWN) { - long tmpsize; + } + } else if(xop == XDOWN) { + long tmpsize; - if ((xi.flags & YMODEM) && (xi.fname[0])) - printf("Ymodem download gets name from protocol, '%s' ignored\n", - xi.fname); + if((xi.flags & YMODEM) && (xi.fname[0])) + printf("Ymodem download gets name from protocol, '%s' ignored\n", + xi.fname); -#ifdef DONT_DISABLE_ENET_IN_XMODEM /* See note at top of file */ - tmpsize = (long)Xdown(&xi); +#ifdef DONT_DISABLE_ENET_IN_XMODEM /* See note at top of file */ + tmpsize = (long)Xdown(&xi); #else #if INCLUDE_ETHERNET - eon = DisableEthernet(); + eon = DisableEthernet(); #endif - tmpsize = (long)Xdown(&xi); + tmpsize = (long)Xdown(&xi); #if INCLUDE_ETHERNET - if (eon) - EthernetStartup(0,0); + if(eon) { + EthernetStartup(0,0); + } #endif #endif - if (tmpsize == -1) - return(CMD_FAILURE); - if ((!xi.size) || (tmpsize < 0)) - xi.size = tmpsize; + if(tmpsize == -1) { + return(CMD_FAILURE); + } + if((!xi.size) || (tmpsize < 0)) { + xi.size = tmpsize; + } #if INCLUDE_TFS - if ((xi.fname[0]) && (xi.size > 0)) { - int err; - - printf("Writing to file '%s'...\n",xi.fname); - err = tfsadd(xi.fname,info,flags,(uchar *)xi.base,xi.size); - if (err != TFS_OKAY) { - printf("%s: %s\n",xi.fname,(char *)tfsctrl(TFS_ERRMSG,err,0)); - return(CMD_FAILURE); - } - } + if((xi.fname[0]) && (xi.size > 0)) { + int err; + + printf("Writing to file '%s'...\n",xi.fname); + err = tfsadd(xi.fname,info,flags,(uchar *)xi.base,xi.size); + if(err != TFS_OKAY) { + printf("%s: %s\n",xi.fname,(char *)tfsctrl(TFS_ERRMSG,err,0)); + return(CMD_FAILURE); + } + } #if INCLUDE_FLASH - else + else #endif #endif #if INCLUDE_FLASH - if ((newboot) && (xi.size > 0)) { - extern int FlashProtectWindow; - int rc; - char *bb; - ulong bootbase; - - bb = getenv("BOOTROMBASE"); - if (bb) - bootbase = strtoul(bb,0,0); - else - bootbase = BOOTROM_BASE; + if((newboot) && (xi.size > 0)) { + extern int FlashProtectWindow; + int rc; + char *bb; + ulong bootbase; + + bb = getenv("BOOTROMBASE"); + if(bb) { + bootbase = strtoul(bb,0,0); + } else { + bootbase = BOOTROM_BASE; + } #ifdef TO_FLASH_ADDR - /* The address the program is linked to is not necessarily the - * physical address where flash operations can be performed on. - * A typical use could be that the program is linked to run in - * a cacheable region but writing to the flash can only be done - * in an uncached region. - * "config.h" is a good place to define the TO_FLASH_ADDR macro. - */ - bootbase = (ulong)TO_FLASH_ADDR(bootbase); + /* The address the program is linked to is not necessarily the + * physical address where flash operations can be performed on. + * A typical use could be that the program is linked to run in + * a cacheable region but writing to the flash can only be done + * in an uncached region. + * "config.h" is a good place to define the TO_FLASH_ADDR macro. + */ + bootbase = (ulong)TO_FLASH_ADDR(bootbase); #endif - printf("Reprogramming boot @ 0x%lx from 0x%lx, %ld bytes.\n", - bootbase,xi.base,xi.size); - if (askuser("OK?")) { - int first, last; - - /* If sector(s) need to be unlocked, do that now... - */ - if (addrtosector((uchar *)bootbase,&first,0,0) == -1) - return(CMD_FAILURE); - - if (addrtosector((uchar *)bootbase+xi.size-1,&last,0,0) == -1) - return(CMD_FAILURE); - - if (flashlock(first,FLASH_LOCKABLE) != -1) { - FlashProtectWindow = 1; - while(first < last) - flashlock(first++,FLASH_UNLOCK); - } - - FlashProtectWindow = 1; - rc = flashewrite((uchar *)bootbase,(uchar *)xi.base,xi.size); - if (rc == -1) { - printf("failed\n"); - return(CMD_FAILURE); - } - } - } + printf("Reprogramming boot @ 0x%lx from 0x%lx, %ld bytes.\n", + bootbase,xi.base,xi.size); + if(askuser("OK?")) { + int first, last; + + /* If sector(s) need to be unlocked, do that now... + */ + if(addrtosector((uchar *)bootbase,&first,0,0) == -1) { + return(CMD_FAILURE); + } + + if(addrtosector((uchar *)bootbase+xi.size-1,&last,0,0) == -1) { + return(CMD_FAILURE); + } + + if(flashlock(first,FLASH_LOCKABLE) != -1) { + FlashProtectWindow = 1; + while(first < last) { + flashlock(first++,FLASH_UNLOCK); + } + } + + FlashProtectWindow = 1; + rc = flashewrite((uchar *)bootbase,(uchar *)xi.base,xi.size); + if(rc == -1) { + printf("failed\n"); + return(CMD_FAILURE); + } + } + } #endif - } - else - return(CMD_PARAM_ERROR); - shell_sprintf("XMODEMGET","%ld",xi.size); - return(CMD_SUCCESS); + } else { + return(CMD_PARAM_ERROR); + } + shell_sprintf("XMODEMGET","%ld",xi.size); + return(CMD_SUCCESS); } /* xgetchar(): @@ -384,16 +392,16 @@ Xmodem(int argc,char *argv[]) int xgetchar(char *cp, int lno) { - struct elapsed_tmr tmr; - - startElapsedTimer(&tmr,5000); - while(!msecElapsed(&tmr) && !gotachar()); - if (!gotachar()) { - Mtrace("Xgetchar tmt %d",lno); - return(-1); - } - *cp = getchar(); - return(0); + struct elapsed_tmr tmr; + + startElapsedTimer(&tmr,5000); + while(!msecElapsed(&tmr) && !gotachar()); + if(!gotachar()) { + Mtrace("Xgetchar tmt %d",lno); + return(-1); + } + *cp = getchar(); + return(0); } /* putPacket(): @@ -402,49 +410,51 @@ xgetchar(char *cp, int lno) static int putPacket(uchar *tmppkt, struct xinfo *xip) { - char c; - int i; - ushort chksm; - - chksm = 0; - - if (xip->pktlen == PKTLEN_128) - PUTCHAR(SOH); - else - PUTCHAR(STX); - - PUTCHAR((char)(xip->sno)); - PUTCHAR((char)~(xip->sno)); - - if (xip->flags & USECRC) { - for(i=0;i<xip->pktlen;i++) { - PUTCHAR((char)*tmppkt); - chksm = (chksm<<8)^xcrc16tab[(chksm>>8)^*tmppkt++]; - } - /* An "endian independent way to extract the CRC bytes. */ - PUTCHAR((char)(chksm >> 8)); - PUTCHAR((char)chksm); - } - else { - for(i=0;i<xip->pktlen;i++) { - PUTCHAR((char)*tmppkt); - chksm = ((chksm+*tmppkt++)&0xff); - } - PUTCHAR((char)(chksm&0x00ff)); - } - - if (xgetchar(&c,__LINE__) == -1) /* Wait for ack */ - return(-1); - - /* If pktcnt == -1, then this is the first packet sent by - * YMODEM (filename) and we must wait for one additional - * character in the response. - */ - if (xip->pktcnt == -1) { - if (xgetchar(&c,__LINE__) == -1) - return(-1); - } - return((int)c); + char c; + int i; + ushort chksm; + + chksm = 0; + + if(xip->pktlen == PKTLEN_128) { + PUTCHAR(SOH); + } else { + PUTCHAR(STX); + } + + PUTCHAR((char)(xip->sno)); + PUTCHAR((char)~(xip->sno)); + + if(xip->flags & USECRC) { + for(i=0; i<xip->pktlen; i++) { + PUTCHAR((char)*tmppkt); + chksm = (chksm<<8)^xcrc16tab[(chksm>>8)^*tmppkt++]; + } + /* An "endian independent way to extract the CRC bytes. */ + PUTCHAR((char)(chksm >> 8)); + PUTCHAR((char)chksm); + } else { + for(i=0; i<xip->pktlen; i++) { + PUTCHAR((char)*tmppkt); + chksm = ((chksm+*tmppkt++)&0xff); + } + PUTCHAR((char)(chksm&0x00ff)); + } + + if(xgetchar(&c,__LINE__) == -1) { /* Wait for ack */ + return(-1); + } + + /* If pktcnt == -1, then this is the first packet sent by + * YMODEM (filename) and we must wait for one additional + * character in the response. + */ + if(xip->pktcnt == -1) { + if(xgetchar(&c,__LINE__) == -1) { + return(-1); + } + } + return((int)c); } /* getPacket(): @@ -453,144 +463,149 @@ putPacket(uchar *tmppkt, struct xinfo *xip) static int getPacket(uchar *tmppkt, struct xinfo *xip) { - char *pkt; - int i,rcvd; - uchar seq[2]; - - if ((rcvd = getbytes_t((char *)seq,2,BYTE_TIMEOUT)) != 2) { - PUTCHAR(NAK); - Mtrace("RCVD %d != 2",rcvd); - return(0); - } - - if (xip->flags & VERIFY) { - rcvd = getbytes_t((char *)tmppkt,xip->pktlen,BYTE_TIMEOUT); - if (rcvd != xip->pktlen) { - PUTCHAR(NAK); - Mtrace("RCVD %d != %d",rcvd,xip->pktlen); - return(0); - } - for(i=0;i<xip->pktlen;i++) { - if (tmppkt[i] != ((char *)xip->dataddr)[i]) { - if (xip->errcnt++ == 0) - xip->firsterrat = (char *)(xip->dataddr+i); - } - } - pkt = (char *)tmppkt; - } - else { - rcvd = getbytes_t((char *)xip->dataddr,xip->pktlen,BYTE_TIMEOUT); - if (rcvd != xip->pktlen) { - PUTCHAR(NAK); - Mtrace("RCVD %d != %d",rcvd,xip->pktlen); - return(0); - } - pkt = (char *)xip->dataddr; - } - - if (xip->flags & USECRC) { - char c; - ushort crc, xcrc; - - /* An "endian independent way to combine the CRC bytes. */ - if (xgetchar(&c,__LINE__) == -1) - return(0); - crc = (ushort)c; - crc <<= 8; - if (xgetchar(&c,__LINE__) == -1) - return(0); - crc += (ushort)c; - xcrc = xcrc16((uchar *)pkt,(ulong)(xip->pktlen)); - if (crc != xcrc) { - PUTCHAR(NAK); - Mtrace("CRC %04x != %04x",crc,xcrc); - return(0); - } - } - else { - uchar csum, xcsum; - - if (xgetchar((char *)&xcsum,__LINE__) == -1) - return(0); - csum = 0; - for(i=0;i<xip->pktlen;i++) - csum += *pkt++; - if (csum != xcsum) { - PUTCHAR(NAK); - Mtrace("CSUM %02x != %02x (%d)",csum,xcsum,xip->pktlen); - return(0); - } - Mtrace("CSUM %02x (%d)",csum,xip->pktlen); - } - - /* Test the sequence number compliment... - */ - if ((uchar)seq[0] != (uchar)~seq[1]) { - PUTCHAR(NAK); - Mtrace("SNOCMP %02x != %02x",(uchar)seq[0],(uchar)~(seq[1])); - return(0); - } - - /* Verify that the incoming sequence number is the expected value... - */ - if ((uchar)seq[0] != xip->sno) { - /* If the incoming sequence number is one less than the expected - * sequence number, then we assume that the sender did not recieve - * our previous ACK, and they are resending the previously received - * packet. In that case, we send ACK and don't process the - * incoming packet... - */ - if ((uchar)seq[0] == xip->sno-1) { - Mtrace("R_ACK"); - PUTCHAR(ACK); - return(0); - } - - /* Otherwise, something's messed up... - */ - PUTCHAR(CAN); - Mtrace("SNO: %02x != %02x",seq[0],xip->sno); - return(-1); - } - - /* First packet of YMODEM contains information about the transfer: - * FILENAME SP FILESIZE SP MOD_DATE SP FILEMODE SP FILE_SNO - * Only the FILENAME is required and if others are present, then none - * can be skipped. - */ - if ((xip->flags & YMODEM) && (xip->pktcnt == 0)) { - char *slash, *space, *fname; - - slash = strrchr((char *)(xip->dataddr),'/'); - space = strchr((char *)(xip->dataddr),' '); - if (slash) - fname = slash+1; - else - fname = (char *)(xip->dataddr); - Mtrace("<fname=%s>",fname); - if (space) { - *space = 0; - xip->size = atoi(space+1); - } - strcpy(xip->fname,fname); - if (fname[0]) - xip->filcnt++; - } - else - xip->dataddr += xip->pktlen; - xip->sno++; - xip->pktcnt++; - xip->xfertot += xip->pktlen; - Mtrace("ACK"); - PUTCHAR(ACK); - if (xip->flags & YMODEM) { - if (xip->fname[0] == 0) { - printf("\nRcvd %d file%c\n", - xip->filcnt,xip->filcnt > 1 ? 's' : ' '); - return(1); - } - } - return(0); + char *pkt; + int i,rcvd; + uchar seq[2]; + + if((rcvd = getbytes_t((char *)seq,2,BYTE_TIMEOUT)) != 2) { + PUTCHAR(NAK); + Mtrace("RCVD %d != 2",rcvd); + return(0); + } + + if(xip->flags & VERIFY) { + rcvd = getbytes_t((char *)tmppkt,xip->pktlen,BYTE_TIMEOUT); + if(rcvd != xip->pktlen) { + PUTCHAR(NAK); + Mtrace("RCVD %d != %d",rcvd,xip->pktlen); + return(0); + } + for(i=0; i<xip->pktlen; i++) { + if(tmppkt[i] != ((char *)xip->dataddr)[i]) { + if(xip->errcnt++ == 0) { + xip->firsterrat = (char *)(xip->dataddr+i); + } + } + } + pkt = (char *)tmppkt; + } else { + rcvd = getbytes_t((char *)xip->dataddr,xip->pktlen,BYTE_TIMEOUT); + if(rcvd != xip->pktlen) { + PUTCHAR(NAK); + Mtrace("RCVD %d != %d",rcvd,xip->pktlen); + return(0); + } + pkt = (char *)xip->dataddr; + } + + if(xip->flags & USECRC) { + char c; + ushort crc, xcrc; + + /* An "endian independent way to combine the CRC bytes. */ + if(xgetchar(&c,__LINE__) == -1) { + return(0); + } + crc = (ushort)c; + crc <<= 8; + if(xgetchar(&c,__LINE__) == -1) { + return(0); + } + crc += (ushort)c; + xcrc = xcrc16((uchar *)pkt,(ulong)(xip->pktlen)); + if(crc != xcrc) { + PUTCHAR(NAK); + Mtrace("CRC %04x != %04x",crc,xcrc); + return(0); + } + } else { + uchar csum, xcsum; + + if(xgetchar((char *)&xcsum,__LINE__) == -1) { + return(0); + } + csum = 0; + for(i=0; i<xip->pktlen; i++) { + csum += *pkt++; + } + if(csum != xcsum) { + PUTCHAR(NAK); + Mtrace("CSUM %02x != %02x (%d)",csum,xcsum,xip->pktlen); + return(0); + } + Mtrace("CSUM %02x (%d)",csum,xip->pktlen); + } + + /* Test the sequence number compliment... + */ + if((uchar)seq[0] != (uchar)~seq[1]) { + PUTCHAR(NAK); + Mtrace("SNOCMP %02x != %02x",(uchar)seq[0],(uchar)~(seq[1])); + return(0); + } + + /* Verify that the incoming sequence number is the expected value... + */ + if((uchar)seq[0] != xip->sno) { + /* If the incoming sequence number is one less than the expected + * sequence number, then we assume that the sender did not recieve + * our previous ACK, and they are resending the previously received + * packet. In that case, we send ACK and don't process the + * incoming packet... + */ + if((uchar)seq[0] == xip->sno-1) { + Mtrace("R_ACK"); + PUTCHAR(ACK); + return(0); + } + + /* Otherwise, something's messed up... + */ + PUTCHAR(CAN); + Mtrace("SNO: %02x != %02x",seq[0],xip->sno); + return(-1); + } + + /* First packet of YMODEM contains information about the transfer: + * FILENAME SP FILESIZE SP MOD_DATE SP FILEMODE SP FILE_SNO + * Only the FILENAME is required and if others are present, then none + * can be skipped. + */ + if((xip->flags & YMODEM) && (xip->pktcnt == 0)) { + char *slash, *space, *fname; + + slash = strrchr((char *)(xip->dataddr),'/'); + space = strchr((char *)(xip->dataddr),' '); + if(slash) { + fname = slash+1; + } else { + fname = (char *)(xip->dataddr); + } + Mtrace("<fname=%s>",fname); + if(space) { + *space = 0; + xip->size = atoi(space+1); + } + strcpy(xip->fname,fname); + if(fname[0]) { + xip->filcnt++; + } + } else { + xip->dataddr += xip->pktlen; + } + xip->sno++; + xip->pktcnt++; + xip->xfertot += xip->pktlen; + Mtrace("ACK"); + PUTCHAR(ACK); + if(xip->flags & YMODEM) { + if(xip->fname[0] == 0) { + printf("\nRcvd %d file%c\n", + xip->filcnt,xip->filcnt > 1 ? 's' : ' '); + return(1); + } + } + return(0); } /* Xup(): @@ -600,111 +615,116 @@ getPacket(uchar *tmppkt, struct xinfo *xip) static int Xup(struct xinfo *xip) { - uchar c, buf[PKTLEN_128]; - int tmp, done, pktlen; - - Mtrace("Xup starting"); - - if (xip->size & 0x7f) { - xip->size += 128; - xip->size &= 0xffffff80L; - } - - printf("Upload %ld bytes from 0x%lx\n",xip->size,(ulong)xip->base); - - /* Startup synchronization... */ - /* Wait to receive a NAK or 'C' from receiver. */ - done = 0; - while(!done) { - if (xgetchar((char *)&c,__LINE__) == -1) - return(0); - switch(c) { - case NAK: - done = 1; - Mtrace("CSM"); - break; - case 'C': - xip->flags |= USECRC; - done = 1; - Mtrace("CRC"); - break; - case 'q': /* ELS addition, not part of XMODEM spec. */ - return(0); - default: - break; - } - } - - rawon(); - - if (xip->flags & YMODEM) { - Mtrace("SNO_0"); - xip->sno = 0; - xip->pktcnt = -1; - memset((char *)buf,0,PKTLEN_128); - sprintf((char *)buf,"%s",xip->fname); - pktlen = xip->pktlen; - xip->pktlen = PKTLEN_128; - if (putPacket(buf,xip) == -1) - return(0); - xip->pktlen = pktlen; - } - - done = 0; - xip->sno = 1; - xip->pktcnt = 0; - while(!done) { - if ((tmp = putPacket((uchar *)(xip->dataddr),xip)) == -1) - return(0); - c = (uchar)tmp; - switch(c) { - case ACK: - xip->sno++; - xip->pktcnt++; - xip->size -= xip->pktlen; - xip->dataddr += xip->pktlen; - Mtrace("A"); - break; - case NAK: - Mtrace("N"); - break; - case CAN: - done = -1; - Mtrace("C"); - break; - case EOT: - done = -1; - Mtrace("E"); - break; - default: - done = -1; - Mtrace("<%02x>",c); - break; - } - if (xip->size <= 0) { - char tmp; - - PUTCHAR(EOT); - if (xgetchar(&tmp,__LINE__) == -1) /* Flush the ACK */ - return(0); - break; - } - Mtrace("!"); - } - - Mtrace("Xup_almost"); - if ((done != -1) && (xip->flags & YMODEM)) { - xip->sno = 0; - memset((char *)buf,0,PKTLEN_128); - pktlen = xip->pktlen; - xip->pktlen = PKTLEN_128; - if (putPacket(buf,xip) == -1) - return(0); - xip->pktlen = pktlen; - } - Mtrace("Xup_done."); - rawoff(); - return(0); + uchar c, buf[PKTLEN_128]; + int tmp, done, pktlen; + + Mtrace("Xup starting"); + + if(xip->size & 0x7f) { + xip->size += 128; + xip->size &= 0xffffff80L; + } + + printf("Upload %ld bytes from 0x%lx\n",xip->size,(ulong)xip->base); + + /* Startup synchronization... */ + /* Wait to receive a NAK or 'C' from receiver. */ + done = 0; + while(!done) { + if(xgetchar((char *)&c,__LINE__) == -1) { + return(0); + } + switch(c) { + case NAK: + done = 1; + Mtrace("CSM"); + break; + case 'C': + xip->flags |= USECRC; + done = 1; + Mtrace("CRC"); + break; + case 'q': /* ELS addition, not part of XMODEM spec. */ + return(0); + default: + break; + } + } + + rawon(); + + if(xip->flags & YMODEM) { + Mtrace("SNO_0"); + xip->sno = 0; + xip->pktcnt = -1; + memset((char *)buf,0,PKTLEN_128); + sprintf((char *)buf,"%s",xip->fname); + pktlen = xip->pktlen; + xip->pktlen = PKTLEN_128; + if(putPacket(buf,xip) == -1) { + return(0); + } + xip->pktlen = pktlen; + } + + done = 0; + xip->sno = 1; + xip->pktcnt = 0; + while(!done) { + if((tmp = putPacket((uchar *)(xip->dataddr),xip)) == -1) { + return(0); + } + c = (uchar)tmp; + switch(c) { + case ACK: + xip->sno++; + xip->pktcnt++; + xip->size -= xip->pktlen; + xip->dataddr += xip->pktlen; + Mtrace("A"); + break; + case NAK: + Mtrace("N"); + break; + case CAN: + done = -1; + Mtrace("C"); + break; + case EOT: + done = -1; + Mtrace("E"); + break; + default: + done = -1; + Mtrace("<%02x>",c); + break; + } + if(xip->size <= 0) { + char tmp; + + PUTCHAR(EOT); + if(xgetchar(&tmp,__LINE__) == -1) { /* Flush the ACK */ + return(0); + } + break; + } + Mtrace("!"); + } + + Mtrace("Xup_almost"); + if((done != -1) && (xip->flags & YMODEM)) { + xip->sno = 0; + memset((char *)buf,0,PKTLEN_128); + pktlen = xip->pktlen; + xip->pktlen = PKTLEN_128; + if(putPacket(buf,xip) == -1) { + return(0); + } + xip->pktlen = pktlen; + } + Mtrace("Xup_done."); + rawoff(); + return(0); } @@ -719,135 +739,145 @@ Xup(struct xinfo *xip) static int Xdown(struct xinfo *xip) { - struct elapsed_tmr tmr; - char c, *tmppkt; - int i, done; + struct elapsed_tmr tmr; + char c, *tmppkt; + int i, done; #if !INCLUDE_MALLOC - static char pkt[PKTLEN_128]; + static char pkt[PKTLEN_128]; - tmppkt = pkt; + tmppkt = pkt; #else - tmppkt = malloc(PKTLEN_1K); - if (!tmppkt) { - Mtrace("malloc failed"); - return(-1); - } + tmppkt = malloc(PKTLEN_1K); + if(!tmppkt) { + Mtrace("malloc failed"); + return(-1); + } #endif - rawon(); + rawon(); nextfile: - if (xip->flags & YMODEM) - xip->sno = 0x00; - else - xip->sno = 0x01; - xip->pktcnt = 0; - xip->errcnt = 0; - xip->xfertot = 0; - xip->firsterrat = 0; - - /* Startup synchronization... */ - /* Continuously send NAK or 'C' until sender responds. */ + if(xip->flags & YMODEM) { + xip->sno = 0x00; + } else { + xip->sno = 0x01; + } + xip->pktcnt = 0; + xip->errcnt = 0; + xip->xfertot = 0; + xip->firsterrat = 0; + + /* Startup synchronization... */ + /* Continuously send NAK or 'C' until sender responds. */ restart: - Mtrace("Xdown"); - for(i=0;i<32;i++) { - if (xip->flags & USECRC) - PUTCHAR('C'); - else - PUTCHAR(NAK); - - startElapsedTimer(&tmr,xip->nakresend * 1000); - while(!msecElapsed(&tmr) && !gotachar()); - if (gotachar()) - break; - } - if (i == 32) { - Mtrace("Giveup @ %d",__LINE__); - return(-1); - } - - done = 0; - Mtrace("Got response"); - while(done == 0) { - if (xgetchar(&c,__LINE__) == -1) - return(-1); - switch(c) { - case SOH: /* 128-byte incoming packet */ - Mtrace("O"); - xip->pktlen = 128; - done = getPacket((uchar *)tmppkt,xip); - if (done < 0) - Mtrace("GP_%d",done); - if (!done && (xip->pktcnt == 1) && (xip->flags & YMODEM)) - goto restart; - break; + Mtrace("Xdown"); + for(i=0; i<32; i++) { + if(xip->flags & USECRC) { + PUTCHAR('C'); + } else { + PUTCHAR(NAK); + } + + startElapsedTimer(&tmr,xip->nakresend * 1000); + while(!msecElapsed(&tmr) && !gotachar()); + if(gotachar()) { + break; + } + } + if(i == 32) { + Mtrace("Giveup @ %d",__LINE__); + return(-1); + } + + done = 0; + Mtrace("Got response"); + while(done == 0) { + if(xgetchar(&c,__LINE__) == -1) { + return(-1); + } + switch(c) { + case SOH: /* 128-byte incoming packet */ + Mtrace("O"); + xip->pktlen = 128; + done = getPacket((uchar *)tmppkt,xip); + if(done < 0) { + Mtrace("GP_%d",done); + } + if(!done && (xip->pktcnt == 1) && (xip->flags & YMODEM)) { + goto restart; + } + break; #if INCLUDE_MALLOC - case STX: /* 1024-byte incoming packet */ - Mtrace("T"); - xip->pktlen = 1024; - done = getPacket((uchar *)tmppkt,xip); - if (done < 0) - Mtrace("GP_%d",done); - if (!done && (xip->pktcnt == 1) && (xip->flags & YMODEM)) - goto restart; - break; + case STX: /* 1024-byte incoming packet */ + Mtrace("T"); + xip->pktlen = 1024; + done = getPacket((uchar *)tmppkt,xip); + if(done < 0) { + Mtrace("GP_%d",done); + } + if(!done && (xip->pktcnt == 1) && (xip->flags & YMODEM)) { + goto restart; + } + break; #endif - case CAN: - Mtrace("C"); - done = -1; - break; - case EOT: - Mtrace("E"); - PUTCHAR(ACK); - if (xip->flags & YMODEM) { + case CAN: + Mtrace("C"); + done = -1; + break; + case EOT: + Mtrace("E"); + PUTCHAR(ACK); + if(xip->flags & YMODEM) { #if INCLUDE_TFS - if (!xip->size) - xip->size = xip->pktcnt * xip->pktlen; - if (xip->fname[0]) - tfsadd(xip->fname,0,0,(uchar *)xip->base,xip->size); - xip->dataddr = xip->base; + if(!xip->size) { + xip->size = xip->pktcnt * xip->pktlen; + } + if(xip->fname[0]) { + tfsadd(xip->fname,0,0,(uchar *)xip->base,xip->size); + } + xip->dataddr = xip->base; #endif - goto nextfile; - } - else { - done = xip->xfertot; - rawoff(); - printf("\nRcvd %d pkt%c (%d bytes)\n",xip->pktcnt, - xip->pktcnt > 1 ? 's' : ' ',xip->xfertot); - - /* If the transfer is complete and no file add is to - * be done, then we flush d-cache and invalidate - * i-cache across the memory space that was just - * copied to. This is necessary in case the - * binary data that was just transferred is code. - */ - flushDcache((char *)xip->base,xip->xfertot); - invalidateIcache((char *)xip->base,xip->xfertot); - } - break; - case ESC: /* User-invoked abort */ - Mtrace("X"); - done = -1; - break; - case EOF: /* 0x1a sent by MiniCom, just ignore it. */ - break; - default: - Mtrace("<%02x>",c); - done = -1; - break; - } - Mtrace("!"); - } - rawoff(); - if (xip->flags & VERIFY) { - if (xip->errcnt) - printf("%d errors, first at 0x%lx\n", - xip->errcnt,(ulong)(xip->firsterrat)); - else - printf("verification passed\n"); - } - free(tmppkt); - return(done); + goto nextfile; + } else { + done = xip->xfertot; + rawoff(); + printf("\nRcvd %d pkt%c (%d bytes)\n",xip->pktcnt, + xip->pktcnt > 1 ? 's' : ' ',xip->xfertot); + + /* If the transfer is complete and no file add is to + * be done, then we flush d-cache and invalidate + * i-cache across the memory space that was just + * copied to. This is necessary in case the + * binary data that was just transferred is code. + */ + flushDcache((char *)xip->base,xip->xfertot); + invalidateIcache((char *)xip->base,xip->xfertot); + } + break; + case ESC: /* User-invoked abort */ + Mtrace("X"); + done = -1; + break; + case EOF: /* 0x1a sent by MiniCom, just ignore it. */ + break; + default: + Mtrace("<%02x>",c); + done = -1; + break; + } + Mtrace("!"); + } + rawoff(); + if(xip->flags & VERIFY) { + if(xip->errcnt) + printf("%d errors, first at 0x%lx\n", + xip->errcnt,(ulong)(xip->firsterrat)); + else { + printf("verification passed\n"); + } + } + free(tmppkt); + return(done); } |