⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xymodem.c

📁 strongarm的bootloader
💻 C
字号:
/****************************************************************************//* Copyright 2000 Compaq Computer Corporation.                              *//*                                           .                              *//* Copying or modifying this code for any purpose is permitted,             *//* provided that this copyright notice is preserved in its entirety         *//* in all copies or modifications.  COMPAQ COMPUTER CORPORATION             *//* MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, AS TO THE USEFULNESS          *//* OR CORRECTNESS OF THIS CODE OR ITS FITNESS FOR ANY PARTICULAR            *//* PURPOSE.                                                                 *//****************************************************************************//* * xymodem.c - an implementation of the xmodem protocol from the spec. * * George France <france@crl.dec.com> * based on the code of Edwin Foo <efoo@crl.dec.com> * *  WARNING: - This code has mixed coding styles.  */#include "bootconfig.h"#include "bootldr.h"#ifdef CONFIG_BITSY#include "sa1100.h"#endif/* XMODEM  parameters */#define RETRIES		  10               /* maximum number of retries */#define GET_BYTE_TIMEOUT  200000           /* efoo's magic number because I                                             do not know the real number 					     i.e. - how many times = 1 sec. *//* Line control codes */#define SOH			0x01	/* start of header */#define ACK			0x06	/* Acknowledge */#define NAK			0x15	/* Negative acknowledge */#define CAN			0x18	/* Cancel */#define EOT			0x04	/* end of text *//* Return Codes - I know non-negitive error codes */enum {     xyOK = 0,            /* OK - no error */     xyMalfunctioned,     /* Malfunctioned - recoverable error */     xyFailed,            /* Failed - unrecoverable error */     xyBadPacket,     xyEOT,               /* End of Text */     xyEndOfSession,     xyTimeout,     xyTransmission,     xySerial,             /* problem with the serial port */     xyBuffer,             /* buffer overflow */     xyNumErrorCodes};static int errorCounts[xyNumErrorCodes];#define XYERROR(code) (((xy.err == code) || errorCounts[code]++), xy.err = code)#define XY_COUNT_PACKET() (errorCounts[xyOK]++)struct xyModem {     int        crc,           /* Does the sender support CRC? */	        longPacket,    /* Does the sender support 1K Packets? */	        batch,         /* Does the sender support batch? */                g;             /* Does the sender support 'G' */     int        timeout;       /* Timeout in number of seconds */     int        retries;       /* Number of times to retry a packet */     int        userAbort;     /* Does the user want to Abort? */      int        packetNumber;  /* Current Packet Number */     char      *filename;           long       fileLength;          long       transferred;   /* Number of bytes transferred */     int        check_value;   /* one byte checksum or two byte crc */     int        err;           /* error code */} xy;/************************************************************************ * *   Global Vars. * ************************************************************************//************************************************************************ * *   Debugging Routines * ***********************************************************************/#define xyDisplayMsg()  xyDsplyMsg()  /* change to (err) for no 					       debugging mesages       */void xyDsplyMsg(void) {     switch (xy.err)     {     case xyOK:                                                  break;     case xyMalfunctioned: putstr("Malfunctioned\r\n");          break;     case xyFailed:        putstr("Failed\r\n");                 break;     case xyBadPacket:     putstr("BadPacket\r\n");              break;     case xyEOT:           putstr("End of Text\r\n");            break;     case xyEndOfSession:  putstr("End of Session\r\n");         break;     case xyTimeout:       putstr("Timed Out\r\n");              break;     case xyTransmission:  putstr("Transmission Breakdown\r\n"); break;     case xyBuffer:        putstr("Buffer Overflow");            break;     default:              putstr("Unknown Error\r\n ");          break;     }     return;}/************************************************************************ * *   Utility Routines * *   init_crc_16 pre-computes a table of constants, using the bitwise *               algorithm with the x^16+x^12+x^5+1 polynomial = 0x11021 *               binary. The leading term is implied.  ************************************************************************/unsigned int crc_table[256];void InitCRC16(void){     unsigned i, j, crc;     for (i=0; i<256; i++) {	  crc = (i << 8);	  for (j=0; j<8; j++) 	       crc = (crc << 1) ^ ((crc & 0x8000) ? 0x1021 : 0);	  crc_table[i] = crc & 0xffff;     }}/************************************************************************* * *  Interface to Serial Port * *************************************************************************/byte getBytesWithTimeout(){   byte c = 0, rxstat;      dword i;   xy.err = 0; /* reset errno */   if (xy.userAbort ) {      XYERROR(xyFailed);      return(c);   }   i = xy.timeout;#ifdef CONFIG_SKIFF   while (((CSR_READ_BYTE(UARTFLG_REG) & UART_RX_FIFO_EMPTY)) && i)     i--;#else    {       while ((!((*(volatile long *)SA1100_UART3_UTSR1) & SA1100_UTSR1_RNE)) && i)          i--;    }#endif   if (i) {#ifdef CONFIG_SKIFF     /* must read UARTDR before RXSTAT */     c =  CSR_READ_BYTE(UARTDR_REG);     rxstat = CSR_READ_BYTE(RXSTAT_REG);#else     c = *(volatile long *)SA1100_UART3_UTDR;     rxstat = (*(volatile long *)SA1100_UART3_UTSR1) & SA1100_UTSR1_ERROR_MASK;#endif     if (rxstat) {             /* i do not know the values of rxstat				  - just following Edwin */       XYERROR(xySerial);     }   } else {       XYERROR(xyTimeout);   }   return(c);}/***************************************************************************** *   Subroutines *      xyReceivePacket         --  gets a packet *      xyReceivePacketReliable --  retries bad packets *      xyReceiveFile           --  gets the file *      xyReceiveFallback       --  Fallback to the next lower protocol *      xySendHandshake         --  Sends a handshake to the sender *      xyReadBytesWithCheck    --  Reads a Packet and verifies Check Sum *      xyReadBytesWithCRC      --  Reads a Packet and verifies CRC 16 *      xyGobble                --  Eats bytes from the serial port * ***************************************************************************/void xyGobble(void) {   int  i;   int junkLength = 64;   byte c;   do {       for (i=0; i < junkLength; i++ )          c = getBytesWithTimeout();       if (xy.err == xySerial)  /* ignore framing errors */          xy.err = xyOK;   } while ( xy.err == xyOK );   if ( xy.err == xyTimeout)      xy.err = xyOK;   return;}void xyReadBytesWithCheck( byte *pBuffer, int buf_length ) {   int i;   byte c;   xy.check_value = 0;   for (i=0; i < buf_length; i++) {     c = getBytesWithTimeout();     if (xy.err != xyOK )         return;     *(byte *)(pBuffer+i) = c;     xy.check_value += c;   }   c = getBytesWithTimeout();   if (xy.err != xyOK )       return;   if ( (xy.check_value & 0xFF) != c )      XYERROR(xyBadPacket);   return;}void xyReadBytesWithCRC( byte *pBuffer, int buf_length ) {   int i,       received_crc;   byte c;   xy.check_value = 0;   for (i=0; i < buf_length; i++) {     c = getBytesWithTimeout();     if (xy.err != xyOK )         return;     *(byte *)(pBuffer+i) = c;     xy.check_value = crc_table[((xy.check_value >> 8 ) ^ c)                      & 0xFF] ^ (xy.check_value << 8);   }   xy.check_value &= 0xFFFF;   c = getBytesWithTimeout();   if (xy.err != xyOK )       return;   received_crc = ( c & 0xFF ) << 8;   c = getBytesWithTimeout();   if (xy.err != xyOK )       return;   received_crc |= ( c & 0xFF );      if ( xy.check_value != received_crc )      XYERROR(xyBadPacket);   return;}void xyReceiveFallback(void) {    if (xy.g) {       xy.g = 0;       return;    }    if (xy.crc) {       xy.crc = xy.batch = xy.longPacket = 0;       return;    }    /* xy.g = xy.crc = xy.batch = xy.longPacket = -1; */    return;}void xySendHandshake(void){   if (xy.g) {      putc('G');      return;   }   if (xy.crc) {      putc('C');      return;   }   putc(NAK);   return;}void xyReceivePacket(byte *pBuffer, int *packetNumber, int *pLength) {   byte startOfPacket = 0;   byte packet = 0;   byte packetCheck = 0;   int  packetLength=0;    packetCheck = getBytesWithTimeout();   if ( xy.err != xyOK )      return;   if (packetCheck == EOT ) {      XYERROR(xyEOT);       return;   }   do {      startOfPacket = packet;      packet = packetCheck;      if ((packetCheck == CAN) && (packet == CAN)) {         XYERROR(xyFailed);         return;      }      packetCheck = getBytesWithTimeout();      if ( xy.err != xyOK )         return;    } while ( ( ( startOfPacket != SOH ) && (startOfPacket != 0x02) ) || ( ( (packet ^ packetCheck) & 0xFF) != 0xFF) );   /* a vaild start of packet */   if (startOfPacket == SOH)      packetLength = 128;   else      packetLength = 1024;      *packetNumber = packet;   *pLength = packetLength;   if (xy.crc) {        xyReadBytesWithCRC( pBuffer, packetLength);   }   else {       xyReadBytesWithCheck( pBuffer, packetLength);    }   return;}void xyReceivePacketReliable(byte *pBuffer, int *packetNumber, int *pLength) {   int retries = xy.retries;   int eotCount = 0;     do {        xyReceivePacket( pBuffer, packetNumber, pLength );        if (xy.err == xyEOT) {  	     if ( xy.g) {                xy.err = xyEOT;                return;	     }             eotCount += 3;             if ( eotCount >= 6) {                xy.err = xyEOT;                return;             }	} else if ((xy.err == xyTimeout) && (eotCount > 0 )) {                  eotCount++;		  if (eotCount >= 6) {                     xy.err = xyEOT;                     return;		  }	} else {  /* Data packet or timeout seen */             eotCount = 0;             if ((xy.err == xyBadPacket) && ( xy.err != xyTimeout))                return;             else if (xy.g) {                     XYERROR(xyMalfunctioned);                     return;	     }	}        putc(NAK);     } while (retries-- > 0 );     XYERROR(xyMalfunctioned);     return;}void xyReceiveFile(dword dldaddr, dword img_size) {   int retries = xy.retries / 2 + 1;   int totalRetries = ( xy.retries * 3 ) / 2 + 1;   int packetNumber, packetLength;   byte *pBuffer;   /* Try different handshakes until we get the first packet */   xy.err = xyOK;   pBuffer = (byte *)dldaddr;   do {      if (--retries == 0 ) {	 xyReceiveFallback();         retries = xy.retries / 3;      }      if (totalRetries-- == 0) {         XYERROR(xyFailed);          return;      }      xySendHandshake();      xyReceivePacketReliable( pBuffer, &packetNumber, &packetLength);      if ((xy.err == xyEOT) || (xy.err == xyBadPacket)) {         xyGobble();      }   } while ( (xy.err == xyTimeout)   ||             (xy.err == xyBadPacket) ||             (xy.err == xyMalfunctioned) ||             (xy.err == xyEOT) );   if ( ( packetNumber != 0 ) && ( packetNumber != 1 ) ) {      XYERROR(xyFailed);      return;   }   /* the first packet tells if the sender is in batch mode */   if ( packetNumber == 0 ) {      xy.batch = -1;      putc(ACK);      XY_COUNT_PACKET();      xySendHandshake();  /* get next packet */      xyReceivePacketReliable( pBuffer, &packetNumber, &packetLength );   } else {      xy.batch = 0;      xy.g = 0;      /* g is always batch */   }           xy.packetNumber = 1;   xy.transferred  = 0;	    /* we have the first packet and the correct protocol */   /* Now we get the remaining packets */   while (xy.err == xyOK) {      if (packetNumber == ( xy.packetNumber & 0xFF )) {         xy.packetNumber++;         xy.transferred += packetLength;         if (!xy.g) {            putc(ACK);       /* ACK correct packet */            XY_COUNT_PACKET();         }      } else if (packetNumber == (xy.packetNumber - 1) & 0xFF) {         putc(ACK);  /* ACK repeat of previous packet */      }      pBuffer += packetLength;      if (pBuffer >= (byte *)(dldaddr + img_size - 1024)) {         XYERROR(xyBuffer);         return;      }      xyReceivePacketReliable( pBuffer, &packetNumber, &packetLength );   }   /* ACK the EOT.  */   if (xy.err == xyEOT) {      putc(ACK);      XY_COUNT_PACKET();   }   return;    }/***************************************************************************** * *   Main Program - main  entry is xmodem_dld *                  abort entry is xyModemAbort * ****************************************************************************/int xyModemAbort(void) {  xy.userAbort = -1;};int init_xmodem_dld(void) {     InitCRC16();  /* init the CRC 16 table */          /* non of these are certain yet,	each of these setting implies a lower	protocol       */#ifdef CONFIG_XYMODEM_CRC     xy.crc = -1;#else     xy.crc = 0;#endif#ifdef CONFIG_XYMODEM_CRC     xy.longPacket = -1;#else     xy.longPacket = 0;#endif     xy.batch = 0;#ifdef CONFIG_XYMODEM_G     xy.g = -1;#else     xy.g = 0;#endif     xy.timeout = GET_BYTE_TIMEOUT;     xy.retries = RETRIES;     xy.userAbort = 0;     xy.packetNumber = 0;     xy.fileLength = 0;     xy.transferred = 0;     xy.err = xyOK;     memset(errorCounts, 0, sizeof(errorCounts));     return ( xyOK );}void cleanup_xmodem_dld(void) {}dword xymodem_receive(dword dldaddr, dword img_size){     if (init_xmodem_dld() == xyOK) { /* do the init stuff */         putstr("ready for xmodem download..\r\n");          xyReceiveFile(dldaddr, img_size);         if (xy.err ==  xyOK) {            putstr("Download Successful\r\n");         } else {            putstr("\r\n");            putstr("Download Failed!\r\n");            xyDisplayMsg();            putLabeledWord("Packets=", errorCounts[xyOK]);            putLabeledWord("Malfunctions=", errorCounts[xyMalfunctioned]);            putLabeledWord("Failed=", errorCounts[xyFailed]);            putLabeledWord("BadPackets=", errorCounts[xyBadPacket]);            putLabeledWord("EndOfText=", errorCounts[xyEOT]);            putLabeledWord("EndOfSession=", errorCounts[xyEndOfSession]);            putLabeledWord("Timeout=", errorCounts[xyTimeout]);            putLabeledWord("Transmissions=", errorCounts[xyTransmission]);            putLabeledWord("SerialErrors=", errorCounts[xySerial]);            putLabeledWord("BufferOverflows=", errorCounts[xyBuffer]);            xy.transferred = 0;  /* return failure */        }        cleanup_xmodem_dld(); /* do the cleanup stuff */     }     return xy.transferred;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -