void TftpStart (void) { struct timestamp now; time_get(&now); #ifdef ET_DEBUG printf ("\nServer ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n", NetServerEther[0], NetServerEther[1], NetServerEther[2], NetServerEther[3], NetServerEther[4], NetServerEther[5] ); #endif /* DEBUG */ printf ("TFTP from server %s", inet_ntoa(NetServerIP)); printf ("; our IP address is %s", inet_ntoa(NetOurIP)); // Check if we need to send across this subnet if (NetOurGatewayIP && NetOurSubnetMask) { IPaddr_t OurNet = NetOurIP & NetOurSubnetMask; IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask; if (OurNet != ServerNet) { printf ("; sending through gateway "); print_IPaddr (NetOurGatewayIP) ; } } printf("\n"); printf ("Filename '%s'.", tftp_filename); if (NetBootFileSize) { printf (" Size is %d%s kB => %x Bytes", NetBootFileSize/2, (NetBootFileSize%2) ? ".5" : "", NetBootFileSize<<9); } printf("\n"); printf ("Load address: 0x%lx\n\n", get_board_desc()->memctrl_membase); printf ("Press Ctrl-C to abort...\n"); printf ("Loading: *\b"); NetSetTimeout (TIMEOUT * 1000, TftpTimeout); NetSetHandler (TftpHandler); TftpServerPort = WELL_KNOWN_PORT; TftpTimeoutCount = 0; TftpState = STATE_RRQ; TftpOurPort = 1024 + (now.usec % 3072); //FIXED TftpSend (); }
static void TftpTimeout (void) { if (++TftpTimeoutCount >= TIMEOUT_COUNT) { printf ("\nRetry count exceeded; starting again\n"); NetStartAgain (); } else { printf ("T "); NetSetTimeout (TIMEOUT * 1000, TftpTimeout); TftpSend (); } }
static void TftpTimeout(void) { if (++TftpTimeoutCount > TftpTimeoutCountMax) { restart("Retry count exceeded"); } else { puts("T "); NetSetTimeout(TftpTimeoutMSecs, TftpTimeout); if (TftpState != STATE_RECV_WRQ) TftpSend(); } }
static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){ bd_t *bd = gd->bd; ushort proto; ushort *s; if(dest != TftpOurPort){ return; } if(TftpState != STATE_RRQ && src != TftpServerPort){ return; } if(len < 2){ return; } len -= 2; /* warning: don't use increment (++) in ntohs() macros!! */ s = (ushort *)pkt; proto = *s++; pkt = (uchar *)s; switch(ntohs(proto)){ case TFTP_RRQ: case TFTP_WRQ: case TFTP_ACK: break; 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; // TFTP DATA PACKET case TFTP_DATA: if(len < 2){ return; } len -= 2; TftpBlock = ntohs(*(ushort *)pkt); /* * 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 %lu MB received\n ", TftpBlockWrapOffset>>20); } else { if(((TftpBlock - 1) % 10) == 0){
static void TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) { __be16 proto; __be16 *s; int i; if (dest != TftpOurPort) { #ifdef CONFIG_MCAST_TFTP if (Multicast && (!Mcast_port || (dest != Mcast_port))) #endif return; } if (TftpState != STATE_SEND_RRQ && src != TftpRemotePort && TftpState != STATE_RECV_WRQ && TftpState != STATE_SEND_WRQ) return; if (len < 2) return; len -= 2; /* warning: don't use increment (++) in ntohs() macros!! */ s = (__be16 *)pkt; proto = *s++; pkt = (uchar *)s; switch (ntohs(proto)) { case TFTP_RRQ: break; case TFTP_ACK: #ifdef CONFIG_CMD_TFTPPUT if (TftpWriting) { if (TftpFinalBlock) { tftp_complete(); } else { /* * Move to the next block. We want our block * count to wrap just like the other end! */ int block = ntohs(*s); int ack_ok = (TftpBlock == block); TftpBlock = (unsigned short)(block + 1); update_block_number(); if (ack_ok) TftpSend(); /* Send next data block */ } } #endif break; default: break; #ifdef CONFIG_CMD_TFTPSRV case TFTP_WRQ: debug("Got WRQ\n"); TftpRemoteIP = sip; TftpRemotePort = src; TftpOurPort = 1024 + (get_timer(0) % 3072); new_transfer(); TftpSend(); /* Send ACK(0) */ break; #endif case TFTP_OACK: debug("Got OACK: %s %s\n", pkt, pkt + strlen((char *)pkt) + 1); TftpState = STATE_OACK; TftpRemotePort = src; /* * Check for 'blksize' option. * Careful: "i" is signed, "len" is unsigned, thus * something like "len-8" may give a *huge* number */ for (i = 0; i+8 < len; i++) { if (strcmp((char *)pkt+i, "blksize") == 0) { TftpBlkSize = (unsigned short) simple_strtoul((char *)pkt+i+8, NULL, 10); debug("Blocksize ack: %s, %d\n", (char *)pkt+i+8, TftpBlkSize); } #ifdef CONFIG_TFTP_TSIZE if (strcmp((char *)pkt+i, "tsize") == 0) { TftpTsize = simple_strtoul((char *)pkt+i+6, NULL, 10); debug("size = %s, %d\n", (char *)pkt+i+6, TftpTsize); } #endif } #ifdef CONFIG_MCAST_TFTP parse_multicast_oack((char *)pkt, len-1); if ((Multicast) && (!MasterClient)) TftpState = STATE_DATA; /* passive.. */ else #endif #ifdef CONFIG_CMD_TFTPPUT if (TftpWriting) { /* Get ready to send the first block */ TftpState = STATE_DATA; TftpBlock++; } #endif TftpSend(); /* Send ACK or first data block */ break; case TFTP_DATA: if (len < 2) return; len -= 2; TftpBlock = ntohs(*(__be16 *)pkt); update_block_number(); if (TftpState == STATE_SEND_RRQ) debug("Server did not acknowledge timeout option!\n"); if (TftpState == STATE_SEND_RRQ || TftpState == STATE_OACK || TftpState == STATE_RECV_WRQ) { /* first block received */ TftpState = STATE_DATA; TftpRemotePort = src; new_transfer(); #ifdef CONFIG_MCAST_TFTP if (Multicast) { /* start!=1 common if mcast */ TftpLastBlock = TftpBlock - 1; } else #endif if (TftpBlock != 1) { /* Assertion */ printf("\nTFTP error: " "First block is not block 1 (%ld)\n" "Starting again\n\n", TftpBlock); NetStartAgain(); break; } } if (TftpBlock == TftpLastBlock) { /* * Same block again; ignore it. */ break; } TftpLastBlock = TftpBlock; TftpTimeoutCountMax = TIMEOUT_COUNT; NetSetTimeout(TftpTimeoutMSecs, TftpTimeout); store_block(TftpBlock - 1, pkt + 2, len); /* * 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 * needed block is; else I'm passive; not ACKING */ if (Multicast) { if (len < TftpBlkSize) { TftpEndingBlock = TftpBlock; } else if (MasterClient) { TftpBlock = PrevBitmapHole = ext2_find_next_zero_bit( Bitmap, (Mapsize*8), PrevBitmapHole); if (TftpBlock > ((Mapsize*8) - 1)) { printf("tftpfile too big\n"); /* try to double it and retry */ Mapsize <<= 1; mcast_cleanup(); NetStartAgain(); return; } TftpLastBlock = TftpBlock; } } #endif TftpSend(); #ifdef CONFIG_MCAST_TFTP if (Multicast) { if (MasterClient && (TftpBlock >= TftpEndingBlock)) { puts("\nMulticast tftp done\n"); mcast_cleanup(); net_set_state(NETLOOP_SUCCESS); } } else #endif if (len < TftpBlkSize) tftp_complete(); break; case TFTP_ERROR: printf("\nTFTP error: '%s' (%d)\n", pkt + 2, ntohs(*(__be16 *)pkt)); switch (ntohs(*(__be16 *)pkt)) { case TFTP_ERR_FILE_NOT_FOUND: case TFTP_ERR_ACCESS_DENIED: puts("Not retrying...\n"); eth_halt(); net_set_state(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(); #endif NetStartAgain(); break; } break; } }
static void TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) { ushort proto; ushort *s; int i; if (dest != TftpOurPort) { #ifdef CONFIG_MCAST_TFTP if (Multicast && (!Mcast_port || (dest != Mcast_port))) #endif return; } if (TftpState != STATE_RRQ && src != TftpServerPort) { return; } if (len < 2) { return; } len -= 2; /* warning: don't use increment (++) in ntohs() macros!! */ s = (ushort *)pkt; proto = *s++; pkt = (uchar *)s; switch (ntohs(proto)) { case TFTP_RRQ: case TFTP_WRQ: case TFTP_ACK: break; default: break; case TFTP_OACK: debug("Got OACK: %s %s\n", pkt, pkt+strlen(pkt)+1); TftpState = STATE_OACK; TftpServerPort = src; /* * Check for 'blksize' option. * Careful: "i" is signed, "len" is unsigned, thus * something like "len-8" may give a *huge* number */ for (i=0; i+8<len; i++) { if (strcmp ((char*)pkt+i,"blksize") == 0) { TftpBlkSize = (unsigned short) simple_strtoul((char*)pkt+i+8,NULL,10); debug ("Blocksize ack: %s, %d\n", (char*)pkt+i+8,TftpBlkSize); break; } } #ifdef CONFIG_MCAST_TFTP parse_multicast_oack((char *)pkt,len-1); if ((Multicast) && (!MasterClient)) TftpState = STATE_DATA; /* passive.. */ else #endif TftpSend (); /* Send ACK */ break; case TFTP_DATA: if (len < 2) return; len -= 2; TftpBlock = ntohs(*(ushort *)pkt); /* * 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 += TftpBlkSize * TFTP_SEQUENCE_SIZE; printf("\n\t %lu MB received\n\t ", TftpBlockWrapOffset>>20); } else { if (((TftpBlock - 1) % 10) == 0) {
static void TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) { ushort proto; ushort *s; int i; if (dest != TftpOurPort) { #ifdef CONFIG_MCAST_TFTP if (Multicast && (!Mcast_port || (dest != Mcast_port))) #endif return; } if (TftpState != STATE_SEND_RRQ && src != TftpRemotePort && TftpState != STATE_RECV_WRQ) return; if (len < 2) return; len -= 2; /* warning: don't use increment (++) in ntohs() macros!! */ s = (ushort *)pkt; proto = *s++; pkt = (uchar *)s; switch (ntohs(proto)) { case TFTP_RRQ: 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; TftpRemotePort = src; /* * Check for 'blksize' option. * Careful: "i" is signed, "len" is unsigned, thus * something like "len-8" may give a *huge* number */ for (i = 0; i+8 < len; i++) { if (strcmp((char *)pkt+i, "blksize") == 0) { TftpBlkSize = (unsigned short) simple_strtoul((char *)pkt+i+8, NULL, 10); debug("Blocksize ack: %s, %d\n", (char *)pkt+i+8, TftpBlkSize); } #ifdef CONFIG_TFTP_TSIZE if (strcmp((char *)pkt+i, "tsize") == 0) { TftpTsize = simple_strtoul((char *)pkt+i+6, NULL, 10); debug("size = %s, %d\n", (char *)pkt+i+6, TftpTsize); } #else #ifdef CONFIG_MSTAR_PM_SWIR if(strcmp((char *)pkt+i, "tsize") == 0) { TftpImageSize = simple_strtoul((char *)pkt+i+6, NULL, 10); //if image size is bigger than limited image size, it'll overwrite Uboot and make Uboot crash. //then you need split load image, load image more than one time. #if CONFIG_LZO if(TftpImageSize > ((CONFIG_UNLZO_DST_ADDR - load_addr) - gd->mon_len)) { printf("warning: image size is (0x%lx), which is bigger than (0x%lx),pls consider to split the image.\n", (long unsigned int)TftpImageSize,((CONFIG_UNLZO_DST_ADDR - load_addr) - gd->mon_len)); } #else if(TftpImageSize > ((gd->ram_size - gd->mon_len)- load_addr)) { printf("warning: image size is (0x%lx), which is bigger than (0x%lx),pls consider to split the image.\n", (long unsigned int)TftpImageSize,((gd->ram_size - gd->mon_len)- load_addr)); } #endif } #endif #endif } #ifdef CONFIG_MCAST_TFTP parse_multicast_oack((char *)pkt, len-1); if ((Multicast) && (!MasterClient)) TftpState = STATE_DATA; /* passive.. */ else #endif TftpSend(); /* Send ACK */ break; case TFTP_DATA: if (len < 2) return; len -= 2; TftpBlock = ntohs(*(ushort *)pkt); /* * 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 += TftpBlkSize * TFTP_SEQUENCE_SIZE; printf("\n\t %lu MB received\n\t ", TftpBlockWrapOffset>>20); } #ifdef CONFIG_TFTP_TSIZE else if (TftpTsize) {
static void TftpHandler (unsigned char * pkt, unsigned dest, unsigned src, unsigned len) { if (dest != TftpOurPort) { return; } if (TftpState != STATE_RRQ && src != TftpServerPort) { return; } if (len < 2) { return; } len -= 2; unsigned short val = *((unsigned short *) pkt); pkt += sizeof(unsigned short); switch (val) { case TFTP_RRQ: case TFTP_WRQ: case TFTP_ACK: break; default: break; case TFTP_DATA: if (len < 2) return; len -= 2; TftpBlock = *(unsigned short *)pkt; if (((TftpBlock - 1) % 10) == 0) { printf("#"); TftpTimeoutCount = 0; } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) { printf ("\n\t "); } if (TftpState == STATE_RRQ) { TftpState = STATE_DATA; TftpServerPort = src; TftpLastBlock = 0; if (TftpBlock != 1) { /* Assertion */ printf ("\nTFTP error: " "First block is not block 1 (%d)\n" "Starting again\n\n", TftpBlock); NetStartAgain (); break; } } if (TftpBlock == TftpLastBlock) { /* * Same block again; ignore it. */ break; } TftpLastBlock = TftpBlock; NetSetTimeout (TIMEOUT * 1000, TftpTimeout); store_block (TftpBlock - 1, pkt + 2, len); /* * Acknoledge the block just received, which will prompt * the server for the next one. */ TftpSend (); if (len < 512) { /* * We received the whole thing. Try to * run it. */ printf ("\ndone\n"); NetState = NETLOOP_SUCCESS; } break; case TFTP_ERROR: printf ("\nTFTP error: '%s' (%d)\n", pkt + 2, *(unsigned short *)pkt); printf ("Starting again\n\n"); NetStartAgain (); break; } }