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

📄 tftp.c

📁 一个嵌入式系统的bootloader程序 具有良好的结构体系,良好的可读性
💻 C
字号:
/////////////////////////////////////////////////////////////////////////////////
// Copyright(c) 2001-2002 Hybus Co,.ltd. All rights reserved.
//
// Module name:
//      tftp.c
//
// Description:
//
//
// Author:
//      bedguy
//
// Created:
//      2002.10
//
///////////////////////////////////////////////////////////////////////////////

#include "net.h"
#include "tftp.h"
#include "bootp.h"

#define TFTP_PORT					69		// Well known TFTP port #
#define TFTP_TIMEOUT				5		// Seconds to tftpTimeout for a lost pkt
#define TIMEOUT_COUNT				10		// # of tftpTimeouts before giving up

// TFTP operations.
#define TFTP_RRQ					1
#define TFTP_WRQ					2
#define TFTP_DATA					3
#define TFTP_ACK					4
#define TFTP_ERROR					5


#define TFTP_NONE					0
#define TFTP_STATE_RRQ				1
#define TFTP_STATE_DATA				2
#define TFTP_STATE_TOO_LARGE		3
#define TFTP_STATE_BAD_MAGIC		4
#define TFTP_STATE_SUCCESS			5
#define TFTP_STATE_FAILURE			6


static short	tftpState = 0;
static unsigned short	tftpBlock = 0;
static short	tftpLastBlock = 0;
static ulong	loadAddr = 0;
ushort			tftpPort = 69;
ushort			tftpHostPort=0;
ushort			tftpClientPort = 7777;
static char		requestFile[128];
static ulong	tftpTimeout;

// Prototypes.
bool			TftpStart(char *filename);
void			TftpTx(char *txBuf);

bool DoTftp(CMD_TBL *cptr, int argc, char **argv){
	// tftp肺 罐篮 file data甫 扁废且 林家甫 积己.
	if (argc!=3){
		printf(cptr->usage);
		return false;
	}
	if (!StrCmp(argv[2], "kernel")){
		loadAddr = (long)KERNEL_DRAM_BASE;
	}
	else if (!StrCmp(argv[2], "root")){
		loadAddr = (long)ROOT_DRAM_BASE;
	}
	else if (!StrCmp(argv[2], "loader")){
		loadAddr = (long)LOADER_DRAM_BASE;
	}
	else {
		if (!HexToInt(argv[2], &loadAddr, 32)){
			printf(cptr->usage);
			return false;
		}
	}

	// IP啊 绝栏搁 bootp甫 角青窍咯 IP甫 且寸 罐澜.
	if (clientIP==0){
		printf("No IP. Bootp start...\n");
		if (DoBootp(0, 0,0)==false){
			printf("\tBootp failed. try again.\n");
			return false;
		}
	}
	return TftpStart(argv[1]);	// argv[1] : filename.
}	// DoTftp.


bool TftpStart(char *filename){
	char		*txPktBuf, *rxPktBuf;

	txPktBuf = PktBuf;
	rxPktBuf = PktBuf;
	
	// check filename.
	if (!filename || !filename[0]){
		printf("boot file name is not exists.\n");
		return false;
	}
	
	printf("TFTP Start...\n");
	
	printf("\tHost   (server) IP       : ");
	PrintIPAddr(hostIP);
	printf("\n");
	
	printf("\tClient (target) IP       : ");
	PrintIPAddr(clientIP);
	printf("\n");

	StrCpy(requestFile, filename);
	printf("\tLoading Filename         : %s\n", requestFile);
	printf("\tSave Address             : 0x%08lx\n", loadAddr);
	
	printf("\nLoading start...\n");

	protocol = PROT_TFTP;
	tftpState = TFTP_STATE_RRQ;
	tftpHostPort = 0;

	TftpTx(txPktBuf);

	tftpTimeout = GetTime() + TFTP_TIMEOUT * HZ;
	
	while (tftpState!=TFTP_STATE_SUCCESS && tftpState!=TFTP_STATE_FAILURE){
		RxPacket(rxPktBuf);
		if (GetTime()>tftpTimeout){
			printf("\n\tTftp is failed. Try again.\n\n");
			tftpState=TFTP_STATE_FAILURE;
		}
	}

	protocol = NOPROTOCOL;
	tftpState = TFTP_NONE;
	tftpBlock = 0;
	tftpHostPort = 0;
	return true;
}	// TftpStart.


void TftpTx(char *txPktBuf){
	char		*pktPtr = (char *)(txPktBuf+ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE);
	ushort		hostPort = 0;
	int			len = 0;

	MemSet(txPktBuf, 0, MAX_PKT_SIZE);
	// make tftp header.
	switch (tftpState){
		// tftp request packet阑 父惦.
		case TFTP_STATE_RRQ:
			*((ushort *)pktPtr)++ = SWAP16(TFTP_RRQ);
			StrCpy((char *)pktPtr, requestFile);
			pktPtr += StrLen(requestFile) + 1;
			StrCpy((char *)pktPtr, "octet");
			pktPtr += 5 + 1;
			len = pktPtr - (txPktBuf+ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE);
			hostPort = tftpPort;
			break;

		// 荐脚茄 data packet俊 措茄 acknowledge packet阑 父惦.
		case TFTP_STATE_DATA:
			*((ushort *)pktPtr)++ = SWAP16(TFTP_ACK);
			*((ushort *)pktPtr)++ = SWAP16(tftpBlock);
			len = pktPtr - (txPktBuf+ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE);
			hostPort = tftpHostPort;
			break;

		// error packet阑 父惦.
		case TFTP_STATE_TOO_LARGE:
			*((ushort *)pktPtr)++ = SWAP16(TFTP_ERROR);
			*((ushort *)pktPtr)++ = SWAP16(3);
			StrCpy((char *)pktPtr, "File too large");
			pktPtr += 14 + 1;
			len = pktPtr - (txPktBuf+ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE);
			hostPort = tftpHostPort;

			break;

		// error packet阑 父惦.
		case TFTP_STATE_BAD_MAGIC:
			*((ushort *)pktPtr)++ = SWAP16(TFTP_ERROR);
			*((ushort *)pktPtr)++ = SWAP16(2);
			StrCpy((char *)pktPtr, "File has bad magic");
			pktPtr += 18 + 1;
			len = pktPtr - (txPktBuf+ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE);
			hostPort = tftpHostPort;
			break;
		default :
			return;
	}
	// Ethernet, IP, UDP Header甫 父惦.
	SetUdpHeader((char *)(txPktBuf+ETHER_HDR_SIZE+IP_HDR_SIZE), hostPort, tftpClientPort, len);
	SetIPHeader((char *)(txPktBuf+ETHER_HDR_SIZE), clientIP, hostIP, UDP_HDR_SIZE+len);
	SetEtherHeader(txPktBuf, hostEther, PROT_IP);

	// tftp packet 傈价.
	TxPacket(txPktBuf, ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE+len);
	return;
}	// TftpTx.


bool TftpRx(char *rxPktBuf, int len){
	char			*pktPtr = rxPktBuf;
	short			value;
	unsigned long		rlen=0;			// tftp肺 傈价罐篮 data狼 辨捞(烙矫 buffer).
	
	// handling received data.
	value = SWAP16(*(short *)pktPtr);	// packet type.
	pktPtr+=2;
	len-=2;
	switch (value){
		case TFTP_RRQ :
		case TFTP_WRQ :
		case TFTP_ACK :
		default:
			break;
		// tftp data packet.
		case TFTP_DATA :
			// error. check data index.
			if (len < 2) return false;
			tftpBlock = SWAP16(*(ushort *)pktPtr);	// tftp data packet俊辑 block 锅龋.
			pktPtr += 2;
			len -= 2;
			// tftp receive 柳青 钎矫.
			if (((tftpBlock)%128)==0){	// each 64 kbyte.
				ClearLine();
				rlen = (unsigned long)tftpBlock * 512;
				printf("\t0x%08lx bytes received.", rlen);
			}

			// request俊 措茄 霉锅掳 data packet老锭 鞘夸茄 沥焊 汲沥.
			if (tftpState == TFTP_STATE_RRQ){
				tftpState = TFTP_STATE_DATA;
				tftpLastBlock = 0;

				if (tftpBlock != 1){
					tftpState = TFTP_STATE_FAILURE;
					return false;
				}
			}
			// 捞傈狼 packet阑 促矫 罐疽阑 锭绰 公矫.
			if (tftpBlock <= tftpLastBlock) break;

			tftpLastBlock = tftpBlock;
	
			MemCpy((char *)(loadAddr+(tftpBlock-1)*512), (char *)pktPtr, len);

			tftpTimeout = GetTime() + TFTP_TIMEOUT * HZ;
			
			TftpTx(rxPktBuf);

			if (len < 512){
				// We received the whole thing.  Try to run it.
				ClearLine();
				rlen = ((long)tftpBlock-1) * 512 + len;
				printf("\t0x%08lx (%ld) bytes received.\n", rlen, rlen);
				printf("\ttftp done.\n\n");
				tftpState = TFTP_STATE_SUCCESS;
			}
			break;
		// error 贸府.
		case TFTP_ERROR :
			// tftp RRQ or tftp ack pakcet has some error.
			printf("\nTFTP error: '%s' (%d)\n", pktPtr+2, SWAP16(*(ushort *)pktPtr));
			tftpState = TFTP_STATE_FAILURE;
			break;
	}
	return true;
}	// TftpRx.

⌨️ 快捷键说明

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