]> git.sur5r.net Git - u-boot/blobdiff - net/tftp.c
net/: Remove obsolete references to CONFIG_COMMANDS
[u-boot] / net / tftp.c
index 1154cb9120b97acf462b3dc1b6a455fe66542829..c188243ef5e2647f7acdfb29c649cdd6e5c9eeb5 100644 (file)
 
 #undef ET_DEBUG
 
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
 
 #define WELL_KNOWN_PORT        69              /* Well known TFTP port #               */
-#define TIMEOUT                2               /* Seconds to timeout for a lost pkt    */
+#define TIMEOUT                5               /* Seconds to timeout for a lost pkt    */
 #ifndef        CONFIG_NET_RETRY_COUNT
 # define TIMEOUT_COUNT 10              /* # of timeouts before giving up  */
 #else
 #define TFTP_DATA      3
 #define TFTP_ACK       4
 #define TFTP_ERROR     5
+#define TFTP_OACK      6
 
 
 static int     TftpServerPort;         /* The UDP port at their end            */
 static int     TftpOurPort;            /* The UDP port at our end              */
 static int     TftpTimeoutCount;
-static unsigned        TftpBlock;
-static unsigned        TftpLastBlock;
+static ulong   TftpBlock;              /* packet sequence number               */
+static ulong   TftpLastBlock;          /* last packet sequence number received */
+static ulong   TftpBlockWrap;          /* count of sequence number wraparounds */
+static ulong   TftpBlockWrapOffset;    /* memory offset due to wrapping        */
 static int     TftpState;
+
 #define STATE_RRQ      1
 #define STATE_DATA     2
 #define STATE_TOO_LARGE        3
 #define STATE_BAD_MAGIC        4
+#define STATE_OACK     5
+
+#define TFTP_BLOCK_SIZE                512                 /* default TFTP block size  */
+#define TFTP_SEQUENCE_SIZE     ((ulong)(1<<16))    /* sequence number is 16 bit */
 
 #define DEFAULT_NAME_LEN       (8 + 4 + 1)
 static char default_filename[DEFAULT_NAME_LEN];
 static char *tftp_filename;
 
 #ifdef CFG_DIRECT_FLASH_TFTP
-extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+extern flash_info_t flash_info[];
 #endif
 
 static __inline__ void
 store_block (unsigned block, uchar * src, unsigned len)
 {
-       ulong offset = block * 512, newsize = offset + len;
+       ulong offset = block * TFTP_BLOCK_SIZE + TftpBlockWrapOffset;
+       ulong newsize = offset + len;
 #ifdef CFG_DIRECT_FLASH_TFTP
        int i, rc = 0;
 
@@ -69,7 +78,7 @@ store_block (unsigned block, uchar * src, unsigned len)
        }
 
        if (rc) { /* Flash is destination for this packet */
-               rc = flash_write ((uchar *)src, (ulong)(load_addr+offset), len);
+               rc = flash_write ((char *)src, (ulong)(load_addr+offset), len);
                if (rc) {
                        flash_perror (rc);
                        NetState = NETLOOP_FAIL;
@@ -97,36 +106,51 @@ TftpSend (void)
        volatile uchar *        pkt;
        volatile uchar *        xp;
        int                     len = 0;
+       volatile ushort *s;
 
        /*
         *      We will always be sending some sort of packet, so
         *      cobble together the packet headers now.
         */
-       pkt = NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE;
+       pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
 
        switch (TftpState) {
 
        case STATE_RRQ:
                xp = pkt;
-               *((ushort *)pkt)++ = htons(TFTP_RRQ);
+               s = (ushort *)pkt;
+               *s++ = htons(TFTP_RRQ);
+               pkt = (uchar *)s;
                strcpy ((char *)pkt, tftp_filename);
                pkt += strlen(tftp_filename) + 1;
                strcpy ((char *)pkt, "octet");
                pkt += 5 /*strlen("octet")*/ + 1;
+               strcpy ((char *)pkt, "timeout");
+               pkt += 7 /*strlen("timeout")*/ + 1;
+               sprintf((char *)pkt, "%d", TIMEOUT);
+#ifdef ET_DEBUG
+               printf("send option \"timeout %s\"\n", (char *)pkt);
+#endif
+               pkt += strlen((char *)pkt) + 1;
                len = pkt - xp;
                break;
 
        case STATE_DATA:
+       case STATE_OACK:
                xp = pkt;
-               *((ushort *)pkt)++ = htons(TFTP_ACK);
-               *((ushort *)pkt)++ = htons(TftpBlock);
+               s = (ushort *)pkt;
+               *s++ = htons(TFTP_ACK);
+               *s++ = htons(TftpBlock);
+               pkt = (uchar *)s;
                len = pkt - xp;
                break;
 
        case STATE_TOO_LARGE:
                xp = pkt;
-               *((ushort *)pkt)++ = htons(TFTP_ERROR);
-               *((ushort *)pkt)++ = htons(3);
+               s = (ushort *)pkt;
+               *s++ = htons(TFTP_ERROR);
+               *s++ = htons(3);
+               pkt = (uchar *)s;
                strcpy ((char *)pkt, "File too large");
                pkt += 14 /*strlen("File too large")*/ + 1;
                len = pkt - xp;
@@ -134,8 +158,10 @@ TftpSend (void)
 
        case STATE_BAD_MAGIC:
                xp = pkt;
-               *((ushort *)pkt)++ = htons(TFTP_ERROR);
-               *((ushort *)pkt)++ = htons(2);
+               s = (ushort *)pkt;
+               *s++ = htons(TFTP_ERROR);
+               *s++ = htons(2);
+               pkt = (uchar *)s;
                strcpy ((char *)pkt, "File has bad magic");
                pkt += 18 /*strlen("File has bad magic")*/ + 1;
                len = pkt - xp;
@@ -150,6 +176,7 @@ static void
 TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
 {
        ushort proto;
+       ushort *s;
 
        if (dest != TftpOurPort) {
                return;
@@ -163,7 +190,9 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
        }
        len -= 2;
        /* warning: don't use increment (++) in ntohs() macros!! */
-       proto = *((ushort *)pkt)++;
+       s = (ushort *)pkt;
+       proto = *s++;
+       pkt = (uchar *)s;
        switch (ntohs(proto)) {
 
        case TFTP_RRQ:
@@ -173,25 +202,55 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
        default:
                break;
 
+       case TFTP_OACK:
+#ifdef ET_DEBUG
+               printf("Got OACK: %s %s\n", pkt, pkt+strlen(pkt)+1);
+#endif
+               TftpState = STATE_OACK;
+               TftpServerPort = src;
+               TftpSend (); /* Send ACK */
+               break;
        case TFTP_DATA:
                if (len < 2)
                        return;
                len -= 2;
                TftpBlock = ntohs(*(ushort *)pkt);
-               if (((TftpBlock - 1) % 10) == 0) {
-                       putc ('#');
-               } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
-                       puts ("\n\t ");
+
+               /*
+                * RFC1350 specifies that the first data packet will
+                * have sequence number 1. If we receive a sequence
+                * number of 0 this means that there was a wrap
+                * around of the (16 bit) counter.
+                */
+               if (TftpBlock == 0) {
+                       TftpBlockWrap++;
+                       TftpBlockWrapOffset += TFTP_BLOCK_SIZE * TFTP_SEQUENCE_SIZE;
+                       printf ("\n\t %lu MB received\n\t ", TftpBlockWrapOffset>>20);
+               } else {
+                       if (((TftpBlock - 1) % 10) == 0) {
+                               putc ('#');
+                       } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
+                               puts ("\n\t ");
+                       }
                }
 
+#ifdef ET_DEBUG
                if (TftpState == STATE_RRQ) {
+                       puts ("Server did not acknowledge timeout option!\n");
+               }
+#endif
+
+               if (TftpState == STATE_RRQ || TftpState == STATE_OACK) {
+                       /* first block received */
                        TftpState = STATE_DATA;
                        TftpServerPort = src;
                        TftpLastBlock = 0;
+                       TftpBlockWrap = 0;
+                       TftpBlockWrapOffset = 0;
 
                        if (TftpBlock != 1) {   /* Assertion */
                                printf ("\nTFTP error: "
-                                       "First block is not block 1 (%d)\n"
+                                       "First block is not block 1 (%ld)\n"
                                        "Starting again\n\n",
                                        TftpBlock);
                                NetStartAgain ();
@@ -217,7 +276,7 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
                 */
                TftpSend ();
 
-               if (len < 512) {
+               if (len < TFTP_BLOCK_SIZE) {
                        /*
                         *      We received the whole thing.  Try to
                         *      run it.
@@ -254,14 +313,16 @@ TftpTimeout (void)
 void
 TftpStart (void)
 {
-       if (BootFile[0] == '\0') {
-               IPaddr_t OurIP = ntohl(NetOurIP);
+#ifdef CONFIG_TFTP_PORT
+       char *ep;             /* Environment pointer */
+#endif
 
+       if (BootFile[0] == '\0') {
                sprintf(default_filename, "%02lX%02lX%02lX%02lX.img",
-                       OurIP & 0xFF,
-                       (OurIP >>  8) & 0xFF,
-                       (OurIP >> 16) & 0xFF,
-                       (OurIP >> 24) & 0xFF    );
+                       NetOurIP & 0xFF,
+                       (NetOurIP >>  8) & 0xFF,
+                       (NetOurIP >> 16) & 0xFF,
+                       (NetOurIP >> 24) & 0xFF );
                tftp_filename = default_filename;
 
                printf ("*** Warning: no boot file name; using '%s'\n",
@@ -270,6 +331,9 @@ TftpStart (void)
                tftp_filename = BootFile;
        }
 
+#if defined(CONFIG_NET_MULTI)
+       printf ("Using %s device\n", eth_get_name());
+#endif
        puts ("TFTP from server ");     print_IPaddr (NetServerIP);
        puts ("; our IP address is ");  print_IPaddr (NetOurIP);
 
@@ -304,7 +368,17 @@ TftpStart (void)
        TftpServerPort = WELL_KNOWN_PORT;
        TftpTimeoutCount = 0;
        TftpState = STATE_RRQ;
+       /* Use a pseudo-random port unless a specific port is set */
        TftpOurPort = 1024 + (get_timer(0) % 3072);
+#ifdef CONFIG_TFTP_PORT
+       if ((ep = getenv("tftpdstp")) != NULL) {
+               TftpServerPort = simple_strtol(ep, NULL, 10);
+       }
+       if ((ep = getenv("tftpsrcp")) != NULL) {
+               TftpOurPort= simple_strtol(ep, NULL, 10);
+       }
+#endif
+       TftpBlock = 0;
 
        /* zero out server ether in case the server ip has changed */
        memset(NetServerEther, 0, 6);