⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftp.c

📁 关于s3c2440之bootloader的源代码
💻 C
字号:
/* * vivi/net/tftp.c  * * Based on u-boot * * $Id: tftp.c,v 1.0 2004/08/12 11:14:01 kingmonkey Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Description: net tftp protocol routines . * */  #include "printk.h"#include "command.h"#include "net.h"#include "tftp.h"#include "bootp.h"#include <string.h>#define WELL_KNOWN_PORT	69		/* Well known TFTP port #		*/#define TIMEOUT		100		/* Seconds to timeout for a lost pkt	*/#ifndef	CONFIG_NET_RETRY_COUNT# define TIMEOUT_COUNT	1000		/* # of timeouts before giving up  */#else# define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT * 20)#endif					/* (for checking the image size)	*/#define HASHES_PER_LINE	65		/* Number of "loading" hashes per line	*//* *	TFTP operations. */#define TFTP_RRQ	1#define TFTP_WRQ	2#define TFTP_DATA	3#define TFTP_ACK	4#define TFTP_ERROR	5#define TFTP_OACK	6static int	TftpServerPort;		/* The UDP port at their end		*/static int	TftpOurPort;		/* The UDP port at our end		*/static int	TftpTimeoutCount;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 */static void TftpSend (void);static void TftpTimeout (void);static __inline__ voidstore_block (unsigned block, uchar * src, unsigned len){	ulong offset = block * TFTP_BLOCK_SIZE + TftpBlockWrapOffset;	ulong newsize = offset + len;	(void)memcpy((void *)(load_addr + offset), src, len);	if (NetBootFileXferSize < newsize)		NetBootFileXferSize = newsize;}/**********************************************************************/static voidTftpSend (void){	volatile uchar *	pkt;	volatile uchar *	xp;	int			len = 0;	/*	 *	We will always be sending some sort of packet, so	 *	cobble together the packet headers now.	 */	pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;	switch (TftpState) {	case STATE_RRQ:		xp = pkt;		*((ushort *)pkt)++ = htons(TFTP_RRQ);		strcpy ((char *)pkt, BootFile);		pkt += strlen(BootFile) + 1;		strcpy ((char *)pkt, "octet");		pkt += strlen("octet") + 1;		strcpy ((char *)pkt, "timeout");		pkt += strlen("timeout") + 1;		sprintf((char *)pkt, "%d", TIMEOUT);//		printk("send option \"timeout %s\"\n", (char *)pkt);		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);		len = pkt - xp;		break;	case STATE_TOO_LARGE:		xp = pkt;		*((ushort *)pkt)++ = htons(TFTP_ERROR);		*((ushort *)pkt)++ = htons(3);		strcpy ((char *)pkt, "File too large");		pkt += strlen("File too large") + 1;		len = pkt - xp;		break;	case STATE_BAD_MAGIC:		xp = pkt;		*((ushort *)pkt)++ = htons(TFTP_ERROR);		*((ushort *)pkt)++ = htons(2);		strcpy ((char *)pkt, "File has bad magic");		pkt += strlen("File has bad magic") + 1;		len = pkt - xp;		break;	}	NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort, TftpOurPort, len);}static voidTftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len){	ushort proto;	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!! */	proto = *((ushort *)pkt)++;		switch (ntohs(proto)) {	case TFTP_RRQ:	case TFTP_WRQ:	case TFTP_ACK:		break;		case TFTP_OACK:#ifdef ET_DEBUG		printk("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);		/*		 * 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;			printk("\n\t %lu MB reveived\n\t ", TftpBlockWrapOffset>>20);		} else {			if (((TftpBlock - 1) % 10) == 0) 				printk("#");			 			else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) 				printk("\n ");					}		if (TftpState == STATE_RRQ) 			printk("Server did not acknowledge timeout option!\n");		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 */				printk ("\nTFTP error: "					"First block is not block 1 (%ld)\n"					"Starting again\n\n",					TftpBlock);				NetStartAgain ();				break;			}		}				/*		 *	Same block again; ignore it.		 */		if (TftpBlock == TftpLastBlock) 						break;				TftpLastBlock = TftpBlock;		NetSetTimeout (TIMEOUT * CFG_HZ, 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 < TFTP_BLOCK_SIZE) {			/*			 *	We received the whole thing.  Try to			 *	run it.			 */			printk("\ndone\n");			NetState = NETLOOP_SUCCESS;		}		break;	case TFTP_ERROR:		printk ("\nTFTP error: '%s' (%d)\n",pkt + 2, ntohs(*(ushort *)pkt));		printk("Starting again\n\n");		NetStartAgain ();		break;	default:		break;	}}static voidTftpTimeout (void){	if (++TftpTimeoutCount > TIMEOUT_COUNT) {		printk("\nRetry count exceeded! starting again .....\n");		NetStartAgain ();	} else {//		printk("T ");		NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);		TftpSend ();	}}voidTftpStart (void){	if (BootFile[0] == '\0') {		printk ("*** Warning: no boot file name; please input tftp <ipaddr> filename\n");		return;	} 	printk("TFTP from server ");		print_IPaddr (NetServerIP);	printk("; our IP address is ");	print_IPaddr (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) {		printk("; sending through gateway ");		print_IPaddr (NetOurGatewayIP) ;	    }	}		printk("\n");	printk ("Filename '%s'.", BootFile);	if (NetBootFileSize) {		printk (" Size is 0x%x Bytes = ", NetBootFileSize<<9);//		print_size (NetBootFileSize<<9, "");	}	printk("\n");	load_addr = 0x30008000;		printk ("Load address: 0x%lx\n", load_addr);	printk("Loading: *\b");	NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);	NetSetHandler (TftpHandler);	TftpServerPort = WELL_KNOWN_PORT;	TftpTimeoutCount = 0;	TftpState = STATE_RRQ;	TftpOurPort = 1024 + (get_timer(0) % 3072);	TftpBlock = 0;	/* zero out server ether in case the server ip has changed */	memset(NetServerEther, 0, 6);	TftpSend ();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -