X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=net%2Ftftp.c;h=ed559b71d57b5437e88b6c3f331dd324f0607ec9;hb=b944ad22b45cf46242451286e1c711f8e39b9003;hp=9aeecb8d37febb68fc1839d228ef0838ace15c50;hpb=53c987f51391c1a221b0468aa0f37a3a6ce9181a;p=u-boot diff --git a/net/tftp.c b/net/tftp.c index 9aeecb8d37..ed559b71d5 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -10,12 +10,8 @@ #include "tftp.h" #include "bootp.h" -#undef ET_DEBUG - -#if defined(CONFIG_CMD_NET) - #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */ -#define TIMEOUT 5UL /* Seconds to timeout for a lost pkt */ +#define TIMEOUT 5000UL /* Millisecs to timeout for lost pkt */ #ifndef CONFIG_NET_RETRY_COUNT # define TIMEOUT_COUNT 10 /* # of timeouts before giving up */ #else @@ -34,6 +30,31 @@ #define TFTP_ERROR 5 #define TFTP_OACK 6 +static ulong TftpTimeoutMSecs = TIMEOUT; +static int TftpTimeoutCountMax = TIMEOUT_COUNT; + +/* + * These globals govern the timeout behavior when attempting a connection to a + * TFTP server. TftpRRQTimeoutMSecs specifies the number of milliseconds to + * wait for the server to respond to initial connection. Second global, + * TftpRRQTimeoutCountMax, gives the number of such connection retries. + * TftpRRQTimeoutCountMax must be non-negative and TftpRRQTimeoutMSecs must be + * positive. The globals are meant to be set (and restored) by code needing + * non-standard timeout behavior when initiating a TFTP transfer. + */ +ulong TftpRRQTimeoutMSecs = TIMEOUT; +int TftpRRQTimeoutCountMax = TIMEOUT_COUNT; + +enum { + TFTP_ERR_UNDEFINED = 0, + TFTP_ERR_FILE_NOT_FOUND = 1, + TFTP_ERR_ACCESS_DENIED = 2, + TFTP_ERR_DISK_FULL = 3, + TFTP_ERR_UNEXPECTED_OPCODE = 4, + TFTP_ERR_UNKNOWN_TRANSFER_ID = 5, + TFTP_ERR_FILE_ALREADY_EXISTS = 6, +}; + static IPaddr_t TftpServerIP; static int TftpServerPort; /* The UDP port at their end */ static int TftpOurPort; /* The UDP port at our end */ @@ -43,6 +64,10 @@ 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; +#ifdef CONFIG_TFTP_TSIZE +static int TftpTsize; /* The file size reported by the server */ +static short TftpNumchars; /* The number of hashes we printed */ +#endif #define STATE_RRQ 1 #define STATE_DATA 2 @@ -64,15 +89,21 @@ static char default_filename[DEFAULT_NAME_LEN]; static char tftp_filename[MAX_LEN]; -#ifdef CFG_DIRECT_FLASH_TFTP +#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP extern flash_info_t flash_info[]; #endif /* 512 is poor choice for ethernet, MTU is typically 1500. * Minus eth.hdrs thats 1468. Can get 2x better throughput with * almost-MTU block sizes. At least try... fall back to 512 if need be. + * (but those using CONFIG_IP_DEFRAG may want to set a larger block in cfg file) */ +#ifdef CONFIG_TFTP_BLOCKSIZE +#define TFTP_MTU_BLOCKSIZE CONFIG_TFTP_BLOCKSIZE +#else #define TFTP_MTU_BLOCKSIZE 1468 +#endif + static unsigned short TftpBlkSize=TFTP_BLOCK_SIZE; static unsigned short TftpBlkSizeOption=TFTP_MTU_BLOCKSIZE; @@ -106,10 +137,10 @@ store_block (unsigned block, uchar * src, unsigned len) { ulong offset = block * TftpBlkSize + TftpBlockWrapOffset; ulong newsize = offset + len; -#ifdef CFG_DIRECT_FLASH_TFTP +#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP int i, rc = 0; - for (i=0; i>20); - } else { + } +#ifdef CONFIG_TFTP_TSIZE + else if (TftpTsize) { + while (TftpNumchars < NetBootFileXferSize * 50 / TftpTsize) { + putc('#'); + TftpNumchars++; + } + } +#endif + else { if (((TftpBlock - 1) % 10) == 0) { putc ('#'); } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) { @@ -333,11 +379,8 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) } } -#ifdef ET_DEBUG - if (TftpState == STATE_RRQ) { - puts ("Server did not acknowledge timeout option!\n"); - } -#endif + if (TftpState == STATE_RRQ) + debug("Server did not acknowledge timeout option!\n"); if (TftpState == STATE_RRQ || TftpState == STATE_OACK) { /* first block received */ @@ -370,7 +413,8 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) } TftpLastBlock = TftpBlock; - NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); + TftpTimeoutCountMax = TIMEOUT_COUNT; + NetSetTimeout (TftpTimeoutMSecs, TftpTimeout); store_block (TftpBlock - 1, pkt + 2, len); @@ -420,6 +464,13 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) * We received the whole thing. Try to * run it. */ +#ifdef CONFIG_TFTP_TSIZE + /* Print out the hash marks for the last packet received */ + while (TftpTsize && TftpNumchars < 49) { + putc('#'); + TftpNumchars++; + } +#endif puts ("\ndone\n"); NetState = NETLOOP_SUCCESS; } @@ -428,11 +479,27 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) case TFTP_ERROR: printf ("\nTFTP error: '%s' (%d)\n", pkt + 2, ntohs(*(ushort *)pkt)); - puts ("Starting again\n\n"); + + switch (ntohs(*(ushort *)pkt)) { + case TFTP_ERR_FILE_NOT_FOUND: + case TFTP_ERR_ACCESS_DENIED: + puts("Not retrying...\n"); + eth_halt(); + NetState = NETLOOP_FAIL; + break; + case TFTP_ERR_UNDEFINED: + case TFTP_ERR_DISK_FULL: + case TFTP_ERR_UNEXPECTED_OPCODE: + case TFTP_ERR_UNKNOWN_TRANSFER_ID: + case TFTP_ERR_FILE_ALREADY_EXISTS: + default: + puts("Starting again\n\n"); #ifdef CONFIG_MCAST_TFTP - mcast_cleanup(); + mcast_cleanup(); #endif - NetStartAgain (); + NetStartAgain(); + break; + } break; } } @@ -441,7 +508,7 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) static void TftpTimeout (void) { - if (++TftpTimeoutCount > TIMEOUT_COUNT) { + if (++TftpTimeoutCount > TftpTimeoutCountMax) { puts ("\nRetry count exceeded; starting again\n"); #ifdef CONFIG_MCAST_TFTP mcast_cleanup(); @@ -449,7 +516,7 @@ TftpTimeout (void) NetStartAgain (); } else { puts ("T "); - NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); + NetSetTimeout (TftpTimeoutMSecs, TftpTimeout); TftpSend (); } } @@ -458,9 +525,27 @@ TftpTimeout (void) void TftpStart (void) { -#ifdef CONFIG_TFTP_PORT char *ep; /* Environment pointer */ -#endif + + /* + * Allow the user to choose TFTP blocksize and timeout. + * TFTP protocol has a minimal timeout of 1 second. + */ + if ((ep = getenv("tftpblocksize")) != NULL) + TftpBlkSizeOption = simple_strtol(ep, NULL, 10); + + if ((ep = getenv("tftptimeout")) != NULL) + TftpTimeoutMSecs = simple_strtol(ep, NULL, 10); + + if (TftpTimeoutMSecs < 1000) { + printf("TFTP timeout (%ld ms) too low, " + "set minimum = 1000 ms\n", + TftpTimeoutMSecs); + TftpTimeoutMSecs = 1000; + } + + debug("TFTP blocksize = %i, timeout = %ld ms\n", + TftpBlkSizeOption, TftpTimeoutMSecs); TftpServerIP = NetServerIP; if (BootFile[0] == '\0') { @@ -482,9 +567,8 @@ TftpStart (void) strncpy(tftp_filename, BootFile, MAX_LEN); tftp_filename[MAX_LEN-1] = 0; } else { - *p++ = '\0'; TftpServerIP = string_to_ip (BootFile); - strncpy(tftp_filename, p, MAX_LEN); + strncpy(tftp_filename, p + 1, MAX_LEN); tftp_filename[MAX_LEN-1] = 0; } } @@ -492,18 +576,16 @@ TftpStart (void) #if defined(CONFIG_NET_MULTI) printf ("Using %s device\n", eth_get_name()); #endif - puts ("TFTP from server "); print_IPaddr (TftpServerIP); - puts ("; our IP address is "); print_IPaddr (NetOurIP); + printf("TFTP from server %pI4" + "; our IP address is %pI4", &TftpServerIP, &NetOurIP); /* Check if we need to send across this subnet */ if (NetOurGatewayIP && NetOurSubnetMask) { IPaddr_t OurNet = NetOurIP & NetOurSubnetMask; IPaddr_t ServerNet = TftpServerIP & NetOurSubnetMask; - if (OurNet != ServerNet) { - puts ("; sending through gateway "); - print_IPaddr (NetOurGatewayIP) ; - } + if (OurNet != ServerNet) + printf("; sending through gateway %pI4", &NetOurGatewayIP); } putc ('\n'); @@ -520,7 +602,9 @@ TftpStart (void) puts ("Loading: *\b"); - NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); + TftpTimeoutCountMax = TftpRRQTimeoutCountMax; + + NetSetTimeout (TftpTimeoutMSecs, TftpTimeout); NetSetHandler (TftpHandler); TftpServerPort = WELL_KNOWN_PORT; @@ -546,6 +630,10 @@ TftpStart (void) #ifdef CONFIG_MCAST_TFTP mcast_cleanup(); #endif +#ifdef CONFIG_TFTP_TSIZE + TftpTsize = 0; + TftpNumchars = 0; +#endif TftpSend (); } @@ -639,5 +727,3 @@ static void parse_multicast_oack(char *pkt, int len) } #endif /* Multicast TFTP */ - -#endif