📄 ian_xmodem.c
字号:
printf("%s\n", xerr_msg(XERR_NOFILE)); return(CMD_FAILURE); } memcpy((char *)(xif.dataddr), TFS_BASE(tfp), tfp->filsize);#endif } r = Xdown(&xif, XMODEM); if (size) { /* override size by user specified value */ xif.size = size; } printf("\n"); if ( r < 0 ) { printf("%s\n", xerr_msg(r)); return(CMD_FAILURE); } if ( ! xif.verify ) {#if INCLUDE_TFS if (xif.size > 0 && fname && fname[0]) { /* save file to TFS */ r = tfsadd(fname, info, flags, (uchar *)xif.dataddr, xif.size); if (r != TFS_OKAY) { printf("%s: %s: %s\n", xerr_msg(XERR_TFS), fname, (char *)tfsctrl(TFS_ERRMSG,r,0)); return(CMD_FAILURE); } }#endif } printf("Rcvd 1 file.\n"); if ( xif.verify ) { printf(" %s: %ld bytes, %d blocks, %d errors, " "first err @ 0x%08lx\n", fname[0] ? fname : "<noname>", xif.size, xif.pktcnt, xif.errcnt, xif.firsterrat); } else { printf(" %s: %ld bytes, %d blocks, @ 0x%08lx\n", fname[0] ? fname : "<no-name>", xif.size, xif.pktcnt, xif.dataddr); } }#if INCLUDE_FLASH /* whether it is an X or a Y modem download, if newboot is set, the (last) downloaded file will be written to the boot-sector */ if (xif.size > 0 && newboot) { extern int FlashProtectWindow; char *bb; ulong bootbase; bb = getenv("BOOTROMBASE"); if (bb) bootbase = strtoul(bb,0,0); else bootbase = BOOTROM_BASE; FlashProtectWindow = 1; printf("Reprogramming boot @ 0x%lx from 0x%lx, %ld bytes.\n", bootbase, xif.dataddr, xif.size); if (askuser("OK?")) { if (flashewrite(&FlashBank[0], (char *)bootbase, (char *)xif.dataddr, xif.size) == -1) { /* flashewrite should never return */ printf("failed\n"); return(CMD_FAILURE); } } }#endif } else { /* Neither Upload nor Download */ return(CMD_PARAM_ERROR); } return(CMD_SUCCESS);}/***************************************************************************/static char*xerr_msg (int code){ return (code >= 0) ? xerr_msgs[0] : xerr_msgs[-code];}/***************************************************************************/static voiddoCAN (void) { waitclear(); /* send eight CANs */ rputchar(CAN); rputchar(CAN); rputchar(CAN); rputchar(CAN); rputchar(CAN); rputchar(CAN); rputchar(CAN); rputchar(CAN); /* send eight backspaces */ rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); waitclear();}/*************************************************************************** * DOWNLOAD STUFF **************************************************************************//* getPacket(): * Used by Xdown to retrieve packets. */static intgetPacket(uchar *pkt, int len, int usecrc){ int i; uchar seq[2]; /* s: Get and check the frame sequence number */ if ( waitbytes(seq, 2, CHAR_TMO) < 0 ) { Mtrace("T<seq>"); return -1; } if ( seq[0] != (uchar)(~seq[1]) ) { Mtrace("~<%02x != %02x>", seq[0], seq[1]); return -1; } Mtrace("s"); /* d: Get the frame's data */ if ( waitbytes(pkt, len, CHAR_TMO) < 0 ) { Mtrace("T<data>"); return -1; } Mtrace("d"); /* d: Get the frame's CRC or checksum */ if ( usecrc ) { int c; ushort crc, xcrc; c = waitchar(CHAR_TMO); if ( c < 0 ) { Mtrace("T<crc>"); return -1; } crc = (ushort)c << 8; c = (uchar)waitchar(CHAR_TMO); if ( c < 0 ) { Mtrace("T<crc>"); return -1; } crc |= (ushort)c; xcrc = xcrc16((uchar *)pkt,(ulong)(len)); if (crc != xcrc) { Mtrace("C<%04x != %04x>", crc, xcrc); return -1; } } else { uchar csum; int xcsum; xcsum = waitchar(CHAR_TMO); if ( xcsum < 0 ) { Mtrace("T<xcsum>"); return -1; } csum = 0; for(i=0; i < len; i++) csum += *pkt++; if (csum != xcsum) { Mtrace("c<%02x != %02x>",csum,xcsum); return -1; } } Mtrace("c"); return seq[0];}/***************************************************************************//* * waitPacket * * Receive a X or Y modem packet. Step the reception state-machine. * * Acknowledge the previous frame (or 'kick' the transmiter with a 'C' * or NAK if this is the first frame), and receive the next-one. Also * handle frame retransmitions. * * Arguments: * - pb - packet (frame) buffer. Write the packet-data here. * - *len - packet's size in bytes will be written here * - sno - packet sequence number to wait for. * - usercrc - if non-zero, user 16-bit CRC instread of 8-bit checksum. * * Returns: * 0 - if packet was received successfully * 1 - if an EOT was received instead of a packet * Something negative on fatal error: * XERR_SYNC : Synchronization lost * XERR_CAN : Operation canceled * XERR_UCAN : Operation canceled by user */static intwaitPacket (uchar *pb, int *len, ulong lsno, int usecrc){ char nak; int done, rval; int c, r, sno, psize; if ( usecrc ) { nak = 'C'; } else { nak = NAK; } if ( (lsno == 0 || lsno == 1) ) { /* if it is the first frame of a X or Y modem session, 'kick' the transmiter by sending a NAK or a 'C' */ rputchar(nak); } else { /* if it is not the first frame of an X or Y modem session, acknowledge the previous frame */ rputchar(ACK); } sno = lsno % 0x100; /* loop exitst with: done = 1: packet received succesfully done = 2: EOT received and acknowledged done < 0: Fatal error. 'done' holds error code. */ do { done = 0; c = waitchar(FRAME_TMO); switch ( c ) { case STX: case SOH: /* ok, its a block */ Mtrace("P["); *len = psize = (c == STX) ? 1024 : 128; r = getPacket(pb, psize, usecrc); Mtrace("]"); if (r < 0) { /* block reception not ok. request retransmission */ waitclear(); rputchar(nak); break; } if ( r != sno ) { /* block sequence number is not quite right, but it might still do */ if ( (lsno == 0) || ( sno - r != 1 && r - sno != 0xff ) ) { /* shit! desperately out of sync. CAN the whole thing */ Mtrace("S<%02x != %02x>", r, sno); doCAN(); done = XERR_SYNC; } else { /* no worries, it's just a retransmission */ Mtrace("S"); rputchar(ACK); if (lsno == 1) { Mtrace("0"); rputchar(nak); } } } else { /* seq. number just fine */ Mtrace("s"); if ( lsno == 0 ) { Mtrace("0"); rputchar(ACK); } done = 1; } break; case CAN: Mtrace("C"); /* wait for a second CAN */ c = (char)waitchar(CHAR_TMO); if (c != CAN) { Mtrace("<%02x>", c); waitclear(); rputchar(nak); } else { Mtrace("C"); done = XERR_CAN; } break; case ESC: /* User-invoked abort */ Mtrace("X"); /* wait for a second ESC */ c = (char)waitchar(CHAR_TMO); if (c != ESC) { waitclear(); rputchar(nak); done = 0; } else { done = XERR_UCAN; } break; case EOT: Mtrace("E"); /* first make sure that this is really an EOT, and not a corrupted start-frame; use the fact that self-respecting EOTs always come alone, not followed by other characters. */ c = waitchar(CHAR_TMO); if ( c >= 0 ) { /* probably not an EOT, request retransmission */ Mtrace("<%02x>", c); waitclear(); rputchar(nak); break; } /* ok it is probably a true EOT, send an ACK */ rputchar(ACK); Mtrace("a", c); if (lsno != 0) { done = 2; } break; default: /* request retransmission */ Mtrace("?<%02x>",(uchar)c); waitclear(); rputchar(nak); break; } } while (!done); if (done == 1) { rval = 0; } else if (done == 2) { rval = 1; } else { rval = done; } return rval;}/***************************************************************************//* Xdown(): * * Download, or verify a file using the XMODEM protocol * * Arguments: * - xip - structure containing transfer info: * usecrc IN - use 16bit-CRC instead of 8bit-checksum. * verify IN - operate in verification mode. * dataddr: IN - downloaded file will be stored starting from here. * in verification mode, downloaded file will be * compared with data starting from here. * size: OUT - size of received file in bytes. * pktcnt: OUT - number of frames transfered. * errcnt: OUT - number of errors, if mode is verification. * firsterrat: OUT - address of first error, if mode is verification. * - proto - protocol type (y-modem or x-modem); Used to make very small * adjustment to the operation of the function. * * Returns: * On success: something non-negative. * On error: something negative. * XERR_GEN : General error * XERR_TOUT : Timeout * XERR_SYNC : Lost synchronization * XERR_CAN : Operation canceled * XERR_UCAN : Operation canceled by user */static intXdown(struct xinfo *xip, int proto){ int i, r; ulong sno; int psize; char *tmppkt, *dataddr; Mtrace("--XD--"); dataddr = (char *)(xip->dataddr); if ( xip->verify ) { tmppkt = pktbuff; } else { tmppkt = (char *)(xip->dataddr); } sno = 1; xip->pktcnt = 0; xip->errcnt = 0; xip->firsterrat = 0; xip->size = 0; do { r = waitPacket(tmppkt, &psize, sno, xip->usecrc); if ( r == 0 ) { sno++; xip->pktcnt++; xip->size += psize; if ( xip->verify ) { for (i = 0; i < psize; i++, dataddr++) { if (tmppkt[i] != *dataddr) { if (xip->errcnt++ == 0) xip->firsterrat = (ulong)dataddr; } } } else { tmppkt += psize; } } } while ( ! r ); if ( r == 1 && proto == XMODEM ) { /* send a couple more ACKs to make sure that at least one reaches its destination */ rputchar(ACK); rputchar(ACK); rputchar(ACK); rputchar(ACK); rputchar(ACK); rputchar(ACK); /* send backspaces in-case ACKs have reached the user's terminal */ rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); } if (proto == XMODEM) { /* trash any final garbage send by the transmiter */ waitclear(); } return r;}/***************************************************************************//* Ydown(): * * Download (uMon <-- Host) a file using the YMODEM protocol * * Arguments: * - yip - structure containing transfer info: * usecrc IN - use 16bit CRC instead of 8bit checksum. * onek x * verify IN - verify the downloaded file against stored data. * baseaddr: IN - download the first file here. * flags IN - TFS flags to use when writing to TFS. * info IN - TFS info to use when writing to TFS. * filecnt OUT - Number of files successfully downloaded. * fname[i] OUT - Name of the i'th file downloaded. * size[i]: OUT - size of the i'th file downloaded in bytes. * pktcnt[i]: OUT - nr of frames transfered when downloading i'th file. * errcnt[i]: OUT - number of errors detected when verifying i'th file. * firsterrat[i]: OUT - address of the first error of the i'th file. * * Returns: * On success: something non-negative. * On error: something negative. * XERR_GEN : General error * XERR_TOUT : Timeout * XERR_NOFILE : File not found (verification mode) * XERR_TFS : TFS error * XERR_SYNC : Synchronization error * XERR_CAN : Operation canceled * XERR_UCAN : Operation canceled by user */static intYdown(struct yinfo *yip){ TFILE *tfp; int rval, r, psize; char *tmppkt; ulong dataddr; char *fname, *basename, *s1, *fsize; rval = 0; yip->filecnt = 0; tmppkt = pktbuff; dataddr = yip->baseaddr; do { yip->dataddr[yip->filecnt] = dataddr; yip->size[yip->filecnt] = 0; yip->pktcnt[yip->filecnt] = 0; yip->errcnt[yip->filecnt] = 0; yip->firsterrat[yip->filecnt] = 0; /* * receive and parse the header-block */ r = waitPacket(tmppkt, &psize, 0, 1); if ( r < 0 ) { rval = r; break; } /* first comes the file-name */ fname = (char *)(tmppkt); /* buggy ymodems delimit fields with SP instead of NULL. Cope. */ s1 = strchr(fname,' '); if (s1) *s1 = '\0'; /* if file-name contains path, cut it off and just keep the stem */ basename = strrchr(fname,'/'); if (! basename) basename = fname; /* after the file-name comes the file-size */ fsize = basename + strlen(basename) + 1; /* buggy ymodems delimit fields with SP instead of NULL. cope. */ s1 = strchr(fsize,' '); if (s1) *s1 = '\0'; /* copy info to xip fields */ yip->size[yip->filecnt] = atoi(fsize); strcpy(yip->fname[yip->filecnt], basename); Mtrace("<f=%s>",yip->fname[yip->filecnt]); Mtrace("<z=%d>",yip->size[yip->filecnt]); Mtrace("]"); if ( ! yip->fname[yip->filecnt][0] )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -