www.pudn.com > uc_tftp.rar > tftp.c
/****************************************************************************** * Filename : tftp.c * * Program : loader. * * Copyright : Copyright (C) 2001, Young-Su, Ahn. * * Author : Young-Su, Ahn* * Description : Use Tftp. * * Make tftp packet and transmit it. * * Handling received Tftp packet. * * Created at : Wed Mar 13 2001. * * Based on : pptboot-0.5.3, CS8900A device driver. * * Modified by : * * Modified at : * ******************************************************************************/ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "main.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 short tftpBlock = 0; static short tftpLastBlock = 0; static U32 loadAddr = 0; short tftpPort = 69; short tftpHostPort=0; short tftpClientPort = 7777; static char requestFile[128]; static U32 tftpTimeout; // Prototypes. //bool TftpStart(char *filename); bool TftpStart(int itype); void TftpTx(char *txBuf); /**********************************************************************/ // ¿ªÇÒ : tftp [filename] [addr]ÀÇ ÀÎÀÚ¸¦ tftp¸¦ ½ÇÇàÇϱâ À§ÇÑ ÇÔ¼ö¿Í // ¿¬°á. // ¸Å°³ : // ¹Ýȯ : ¼º°øÇϸé true, ½ÇÆÐÇϸé false. // ÁÖÀÇ : bool DoTftp(int itype) { // tftp·Î ¹ÞÀº file data¸¦ ±â·ÏÇÒ ÁÖ¼Ò¸¦ »ý¼º. if (itype==0) { loadAddr = (U32)KERNEL_DRAM_BASE; } else if(itype==1) { loadAddr = (U32)RAMDISK_DRAM_BASE; } else { loadAddr = (U32)LOADER_DRAM_DOWN_BASE; } // IP°¡ ¾øÀ¸¸é bootp¸¦ ½ÇÇàÇÏ¿© IP¸¦ ÇÒ´ç ¹ÞÀ½. if (clientIP==0){ Serial_Printf("\tNo IP. Bootp start...\n\r"); if (DoBootp()==false) { Serial_Printf("\tBootp failed. try again.\n\r"); return false; } } return TftpStart(itype); } // DoTftp. // ¿ªÇÒ : tftp¸¦ ½ÇÇàÇÒ È¯°æ Ãâ·Â. // ¸Å°³ : // ¹Ýȯ : ¼º°øÇϸé true, ½ÇÆÐÇϸé false. // ÁÖÀÇ : //bool TftpStart(char *filename) bool TftpStart(int itype) { char *txPktBuf, *rxPktBuf; char *kfd="zImage"; char *rfd="ramdisk.gz"; char *bfd="kloader.bin"; txPktBuf = (char *)PktBuf; rxPktBuf = (char *)PktBuf; Serial_Printf("\ni-type = %d\n",itype); // tftp ½ÇÇà ȯ°æ Ãâ·Â. Serial_Printf("TFTP Start...\n\r"); Serial_Printf("\tHost (server) IP : "); PrintIPAddr(hostIP); Serial_Printf("\n\r"); Serial_Printf("\tClient (target) IP : "); PrintIPAddr(clientIP); Serial_Printf("\n\r"); if(itype == 0) StrCpy(requestFile, kfd); else if(itype == 1) StrCpy(requestFile, rfd); else StrCpy(requestFile, bfd); Serial_Printf("\tLoading Filename : %s",requestFile); Serial_Printf("\n\r"); Serial_Printf("\tSave Address : 0x%x",loadAddr); Serial_Printf("\n\r"); Serial_Printf("\n\r\rLoading start...\n\r"); // tftp ½ÃÀÛ È¯°æ. protocol = PROT_TFTP; tftpState = TFTP_STATE_RRQ; tftpHostPort = 0; // tftp request packet Àü¼Û. TftpTx(txPktBuf); // tftpTimeoutÀº À̰÷¿¡¼ Á¤Çϸç, tftp data packetÀ» ¹ÞÀ» ¶§¸¶´Ù °»½ÅµÈ´Ù. // ½Ã°£ÀÌ ÃʰúÇϸé tftp´Â ½ÇÆÐ·Î °£ÁÖÇϰí Áß´ÜÇÑ´Ù. tftpTimeout = GetTime() + TFTP_TIMEOUT * HZ; // tftp°¡ ¼º°øÇϰųª ½ÇÆÐÇÒ ¶§±îÁö tftp data pakcetÀ» ¼ö½Å. while (tftpState!=TFTP_STATE_SUCCESS && tftpState!=TFTP_STATE_FAILURE){ RxPacket(rxPktBuf); // ½Ã°£ Ãʰú¸é ½ÇÆÐÇϰí Áß´Ü. if (GetTime()>tftpTimeout){ Serial_Printf("\n\r\tTftp is failed. Try again.\n\r\n\r"); tftpState=TFTP_STATE_FAILURE; } } // ´ÙÀ½ tftp ½ÇÇàÀ» À§ÇØ È¯°æÀ» µÇµ¹¸². protocol = NOPROTOCOL; tftpState = TFTP_NONE; tftpBlock = 0; tftpHostPort = 0; return true; } // TftpStart. // ¿ªÇÒ : tftp°¡ ÇÊ¿ä·Î ÇÏ´Â packetÀ» ¸¸µé¾î Àü¼Û.. // ¸Å°³ : // ¹Ýȯ : ¼º°øÇϸé true, ½ÇÆÐÇϸé false. // ÁÖÀÇ : void TftpTx(char *txPktBuf) { char *pktPtr = (char *)(txPktBuf+ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE); U16 hostPort = 0; int len = 0; // Serial_Printf(" ",tftpState); // MemSet(txPktBuf, 0, MAX_PKT_SIZE); MemSet(txPktBuf-(ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE), 0, MAX_PKT_SIZE); // make tftp header. switch (tftpState){ // tftp request packetÀ» ¸¸µë. case TFTP_STATE_RRQ: *((U16 *)pktPtr)++ = SWAP16(TFTP_RRQ); StrCpy((char *)pktPtr, requestFile); pktPtr += StrLen(requestFile) + 1; StrCpy((char *)pktPtr, "octet"); pktPtr += 5 + 1; len = pktPtr - txPktBuf; hostPort = tftpPort; break; // ¼ö½ÅÇÑ data packet¿¡ ´ëÇÑ acknowledge packetÀ» ¸¸µë. case TFTP_STATE_DATA: *((U16 *)pktPtr)++ = SWAP16(TFTP_ACK); *((U16 *)pktPtr)++ = SWAP16(tftpBlock); len = pktPtr - txPktBuf; hostPort = tftpHostPort; break; // error packetÀ» ¸¸µë. case TFTP_STATE_TOO_LARGE: *((U16 *)pktPtr)++ = SWAP16(TFTP_ERROR); *((U16 *)pktPtr)++ = SWAP16(3); StrCpy((char *)pktPtr, "File too large"); pktPtr += 14 + 1; len = pktPtr - txPktBuf; hostPort = tftpHostPort; break; // error packetÀ» ¸¸µë. case TFTP_STATE_BAD_MAGIC: *((U16 *)pktPtr)++ = SWAP16(TFTP_ERROR); *((U16 *)pktPtr)++ = SWAP16(2); StrCpy((char *)pktPtr, "File has bad magic"); pktPtr += 18 + 1; len = pktPtr - txPktBuf; 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, (char *)hostEther, PROT_IP); // tftp packet Àü¼Û. TxPacket(txPktBuf, ETHER_HDR_SIZE+IP_HDR_SIZE+UDP_HDR_SIZE+len); return; } // TftpTx. // ¿ªÇÒ : tftp packetÀ» ¹Þ¾Æ ó¸®. // ¸Å°³ : // ¹Ýȯ : ¼º°øÇϸé true, ½ÇÆÐÇϸé false. // ÁÖÀÇ : bool TftpRx(char *rxPktBuf, int len){ char *pktPtr = rxPktBuf; short value; U32 rlen=0; // tftp·Î Àü¼Û¹ÞÀº dataÀÇ ±æÀÌ(Àӽà buffer). // handling received data. value = SWAP16(*(short *)pktPtr); // packet type. // Serial_Printf(" ",value); 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) { Serial_Printf("\nLength err "); return false; } //Serial_Printf("\nBlockNo - 0x%x",*(U16 *)pktPtr); tftpBlock = SWAP16(*(U16 *)pktPtr); // tftp data packet¿¡¼ block ¹øÈ£. pktPtr += 2; len -= 2; // tftp receive ÁøÇà Ç¥½Ã. if (((tftpBlock)%128)==0){ // each 64 kbyte. //ClearLine(); rlen = (long)tftpBlock * 512; Serial_Printf("\n0x%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À» ´Ù½Ã ¹Þ¾ÒÀ» ¶§´Â ¹«½Ã. // Serial_Printf(" ", tftpBlock); if (tftpBlock <= tftpLastBlock) break; tftpLastBlock = tftpBlock; // ¼ö½ÅÇÑ tftp packetÀÇ data ºÎºÐÀ» ÁöÁ¤ÇÑ memory ¿µ¿ª¿¡ ±â·Ï. blockÀº 512 byte ´ÜÀ§. MemCpy((char *)(loadAddr+(tftpBlock-1)*512), (char *)pktPtr, len); // TftpStart()¿¡¼ checkÇÏ´Â tftpTimeout ½Ã°£À» °»½Å. tftpTimeout = GetTime() + TFTP_TIMEOUT * HZ; // Acknowledge¸¦ º¸³¿. À̰ÍÀ» ¹ÞÀº ÈÄ server´Â ´ÙÀ½ blockÀÇ data¸¦ °¡Áø packetÀ» Àü¼Û. TftpTx(rxPktBuf); // ¼ö½ÅÇÑ tftp packetÀÌ dataÀÇ ¸¶Áö¸· blockÀÏ ¶§. if (len < 512){ // We received the whole thing. Try to run it. //ClearLine(); rlen = ((long)tftpBlock-1) * 512 + len; Serial_Printf("\n0x%08lx (%ld) bytes received.", rlen, rlen); Serial_Printf("\nftp done.\n\n"); tftpState = TFTP_STATE_SUCCESS; } break; // error ó¸®. case TFTP_ERROR : // tftp RRQ or tftp ack pakcet has some error. Serial_Printf("\n\r\rTFTP error: '"); Serial_Printf(pktPtr+2); Serial_Printf("' ("); OutputDec(SWAP16(*(U16 *)pktPtr)); Serial_Printf(")\n\r"); tftpState = TFTP_STATE_FAILURE; break; } return true; } // TftpRx.