]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - net/tftp.c
net: tftpput: Add support for receiving ICMP packets
[karo-tx-uboot.git] / net / tftp.c
index a52f54c3d20e3f6f42dafb3c69176aba88717292..da8eeaa58de179195e1151f95361269859cc9101 100644 (file)
@@ -2,6 +2,8 @@
  * Copyright 1994, 1995, 2000 Neil Russell.
  * (See License)
  * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
+ * Copyright 2011 Comelit Group SpA,
+ *                Luca Ceresoli <luca.ceresoli@comelit.it>
  */
 
 #include <common.h>
@@ -58,9 +60,9 @@ enum {
        TFTP_ERR_FILE_ALREADY_EXISTS = 6,
 };
 
-static IPaddr_t TftpServerIP;
+static IPaddr_t TftpRemoteIP;
 /* The UDP port at their end */
-static int     TftpServerPort;
+static int     TftpRemotePort;
 /* The UDP port at our end */
 static int     TftpOurPort;
 static int     TftpTimeoutCount;
@@ -80,11 +82,12 @@ static int  TftpTsize;
 static short   TftpNumchars;
 #endif
 
-#define STATE_RRQ      1
+#define STATE_SEND_RRQ 1
 #define STATE_DATA     2
 #define STATE_TOO_LARGE        3
 #define STATE_BAD_MAGIC        4
 #define STATE_OACK     5
+#define STATE_RECV_WRQ 6
 
 /* default TFTP block size */
 #define TFTP_BLOCK_SIZE                512
@@ -125,8 +128,8 @@ static unsigned short TftpBlkSizeOption = TFTP_MTU_BLOCKSIZE;
 #define MTFTP_BITMAPSIZE       0x1000
 static unsigned *Bitmap;
 static int PrevBitmapHole, Mapsize = MTFTP_BITMAPSIZE;
-static uchar ProhibitMcast = 0, MasterClient = 0;
-static uchar Multicast = 0;
+static uchar ProhibitMcast, MasterClient;
+static uchar Multicast;
 extern IPaddr_t Mcast_addr;
 static int Mcast_port;
 static ulong TftpEndingBlock; /* can get 'last' block before done..*/
@@ -215,7 +218,7 @@ TftpSend(void)
 
        switch (TftpState) {
 
-       case STATE_RRQ:
+       case STATE_SEND_RRQ:
                xp = pkt;
                s = (ushort *)pkt;
                *s++ = htons(TFTP_RRQ);
@@ -257,6 +260,8 @@ TftpSend(void)
                                                            (Mapsize*8), 0);
                /*..falling..*/
 #endif
+
+       case STATE_RECV_WRQ:
        case STATE_DATA:
                xp = pkt;
                s = (ushort *)pkt;
@@ -289,7 +294,7 @@ TftpSend(void)
                break;
        }
 
-       NetSendUDPPacket(NetServerEther, TftpServerIP, TftpServerPort,
+       NetSendUDPPacket(NetServerEther, TftpRemoteIP, TftpRemotePort,
                         TftpOurPort, len);
 }
 
@@ -309,7 +314,8 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 #endif
                        return;
        }
-       if (TftpState != STATE_RRQ && src != TftpServerPort)
+       if (TftpState != STATE_SEND_RRQ && src != TftpRemotePort &&
+           TftpState != STATE_RECV_WRQ)
                return;
 
        if (len < 2)
@@ -322,18 +328,30 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
        switch (ntohs(proto)) {
 
        case TFTP_RRQ:
-       case TFTP_WRQ:
        case TFTP_ACK:
                break;
        default:
                break;
 
+#ifdef CONFIG_CMD_TFTPSRV
+       case TFTP_WRQ:
+               debug("Got WRQ\n");
+               TftpRemoteIP = sip;
+               TftpRemotePort = src;
+               TftpOurPort = 1024 + (get_timer(0) % 3072);
+               TftpLastBlock = 0;
+               TftpBlockWrap = 0;
+               TftpBlockWrapOffset = 0;
+               TftpSend(); /* Send ACK(0) */
+               break;
+#endif
+
        case TFTP_OACK:
                debug("Got OACK: %s %s\n",
                        pkt,
                        pkt + strlen((char *)pkt) + 1);
                TftpState = STATE_OACK;
-               TftpServerPort = src;
+               TftpRemotePort = src;
                /*
                 * Check for 'blksize' option.
                 * Careful: "i" is signed, "len" is unsigned, thus
@@ -399,13 +417,14 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
                                puts("\n\t ");
                }
 
-               if (TftpState == STATE_RRQ)
+               if (TftpState == STATE_SEND_RRQ)
                        debug("Server did not acknowledge timeout option!\n");
 
-               if (TftpState == STATE_RRQ || TftpState == STATE_OACK) {
+               if (TftpState == STATE_SEND_RRQ || TftpState == STATE_OACK ||
+                   TftpState == STATE_RECV_WRQ) {
                        /* first block received */
                        TftpState = STATE_DATA;
-                       TftpServerPort = src;
+                       TftpRemotePort = src;
                        TftpLastBlock = 0;
                        TftpBlockWrap = 0;
                        TftpBlockWrapOffset = 0;
@@ -439,8 +458,8 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
                store_block(TftpBlock - 1, pkt + 2, len);
 
                /*
-                *      Acknoledge the block just received, which will prompt
-                *      the server for the next one.
+                *      Acknowledge the block just received, which will prompt
+                *      the remote for the next one.
                 */
 #ifdef CONFIG_MCAST_TFTP
                /* if I am the MasterClient, actively calculate what my next
@@ -537,7 +556,8 @@ TftpTimeout(void)
        } else {
                puts("T ");
                NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
-               TftpSend();
+               if (TftpState != STATE_RECV_WRQ)
+                       TftpSend();
        }
 }
 
@@ -569,7 +589,7 @@ TftpStart(void)
        debug("TFTP blocksize = %i, timeout = %ld ms\n",
                TftpBlkSizeOption, TftpTimeoutMSecs);
 
-       TftpServerIP = NetServerIP;
+       TftpRemoteIP = NetServerIP;
        if (BootFile[0] == '\0') {
                sprintf(default_filename, "%02lX%02lX%02lX%02lX.img",
                        NetOurIP & 0xFF,
@@ -589,24 +609,22 @@ TftpStart(void)
                        strncpy(tftp_filename, BootFile, MAX_LEN);
                        tftp_filename[MAX_LEN-1] = 0;
                } else {
-                       TftpServerIP = string_to_ip(BootFile);
+                       TftpRemoteIP = string_to_ip(BootFile);
                        strncpy(tftp_filename, p + 1, MAX_LEN);
                        tftp_filename[MAX_LEN-1] = 0;
                }
        }
 
-#if defined(CONFIG_NET_MULTI)
        printf("Using %s device\n", eth_get_name());
-#endif
        printf("TFTP from server %pI4"
-               "; our IP address is %pI4", &TftpServerIP, &NetOurIP);
+               "; our IP address is %pI4", &TftpRemoteIP, &NetOurIP);
 
        /* Check if we need to send across this subnet */
        if (NetOurGatewayIP && NetOurSubnetMask) {
                IPaddr_t OurNet = NetOurIP    & NetOurSubnetMask;
-               IPaddr_t ServerNet      = TftpServerIP & NetOurSubnetMask;
+               IPaddr_t RemoteNet      = TftpRemoteIP & NetOurSubnetMask;
 
-               if (OurNet != ServerNet)
+               if (OurNet != RemoteNet)
                        printf("; sending through gateway %pI4",
                               &NetOurGatewayIP);
        }
@@ -630,16 +648,16 @@ TftpStart(void)
        NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
        NetSetHandler(TftpHandler);
 
-       TftpServerPort = WELL_KNOWN_PORT;
+       TftpRemotePort = WELL_KNOWN_PORT;
        TftpTimeoutCount = 0;
-       TftpState = STATE_RRQ;
+       TftpState = STATE_SEND_RRQ;
        /* Use a pseudo-random port unless a specific port is set */
        TftpOurPort = 1024 + (get_timer(0) % 3072);
 
 #ifdef CONFIG_TFTP_PORT
        ep = getenv("tftpdstp");
        if (ep != NULL)
-               TftpServerPort = simple_strtol(ep, NULL, 10);
+               TftpRemotePort = simple_strtol(ep, NULL, 10);
        ep = getenv("tftpsrcp");
        if (ep != NULL)
                TftpOurPort = simple_strtol(ep, NULL, 10);
@@ -661,6 +679,38 @@ TftpStart(void)
        TftpSend();
 }
 
+#ifdef CONFIG_CMD_TFTPSRV
+void
+TftpStartServer(void)
+{
+       tftp_filename[0] = 0;
+
+       printf("Using %s device\n", eth_get_name());
+       printf("Listening for TFTP transfer on %pI4\n", &NetOurIP);
+       printf("Load address: 0x%lx\n", load_addr);
+
+       puts("Loading: *\b");
+
+       TftpTimeoutCountMax = TIMEOUT_COUNT;
+       TftpTimeoutCount = 0;
+       TftpTimeoutMSecs = TIMEOUT;
+       NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
+
+       /* Revert TftpBlkSize to dflt */
+       TftpBlkSize = TFTP_BLOCK_SIZE;
+       TftpBlock = 0;
+       TftpOurPort = WELL_KNOWN_PORT;
+
+#ifdef CONFIG_TFTP_TSIZE
+       TftpTsize = 0;
+       TftpNumchars = 0;
+#endif
+
+       TftpState = STATE_RECV_WRQ;
+       NetSetHandler(TftpHandler);
+}
+#endif /* CONFIG_CMD_TFTPSRV */
+
 #ifdef CONFIG_MCAST_TFTP
 /* Credits: atftp project.
  */