X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=net%2Ftftp.c;h=eca21d294eb3cae2dfbb7072142c61fc39b703e6;hb=038ccac511214b062c56f22b9413f784b86bcd87;hp=5598be32f130550de43a2fb2fd1298deb7103d82;hpb=73a8b27c574f5ec1c8fdd9d8d065bb845d8743d3;p=platform%2Fkernel%2Fu-boot.git diff --git a/net/tftp.c b/net/tftp.c index 5598be3..eca21d2 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -15,7 +15,7 @@ #if (CONFIG_COMMANDS & CFG_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 @@ -32,31 +32,40 @@ #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 reveived\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. @@ -240,7 +299,7 @@ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) static void TftpTimeout (void) { - if (++TftpTimeoutCount >= TIMEOUT_COUNT) { + if (++TftpTimeoutCount > TIMEOUT_COUNT) { puts ("\nRetry count exceeded; starting again\n"); NetStartAgain (); } else { @@ -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);