2 * Copyright 1994, 1995, 2000 Neil Russell.
4 * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
15 #if defined(CONFIG_CMD_NET)
17 DECLARE_GLOBAL_DATA_PTR;
19 #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
20 #define TIMEOUT 5 /* Seconds to timeout for a lost pkt */
22 #ifndef CONFIG_NET_RETRY_COUNT
23 #define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
25 #define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2)
28 /* (for checking the image size) */
29 #define HASHES_PER_LINE 40 /* Number of "loading" hashes per line */
42 static int TftpServerPort; /* The UDP port at their end */
43 static int TftpOurPort; /* The UDP port at our end */
44 static int TftpTimeoutCount;
47 static ulong TftpBlock; /* packet sequence number */
48 static ulong TftpLastBlock; /* last packet sequence number received */
49 static ulong TftpBlockWrap; /* count of sequence number wraparounds */
50 static ulong TftpBlockWrapOffset; /* memory offset due to wrapping */
54 #define STATE_TOO_LARGE 3
55 #define STATE_BAD_MAGIC 4
58 #define TFTP_BLOCK_SIZE 512 /* default TFTP block size */
59 #define TFTP_SEQUENCE_SIZE ((ulong)(1<<16)) /* sequence number is 16 bit */
61 #define DEFAULT_NAME_LEN (8 + 4 + 1)
63 static char default_filename[DEFAULT_NAME_LEN];
64 static char *tftp_filename;
66 #ifdef CFG_DIRECT_FLASH_TFTP
67 extern flash_info_t flash_info[];
70 static __inline__ void store_block(unsigned block, uchar * src, unsigned len){
71 ulong offset = block * TFTP_BLOCK_SIZE + TftpBlockWrapOffset;
72 ulong newsize = offset + len;
74 #ifdef CFG_DIRECT_FLASH_TFTP
77 for(i=0; i<CFG_MAX_FLASH_BANKS; i++){
78 /* start address in flash? */
79 if(load_addr + offset >= flash_info[i].start[0]){
85 if(rc){ /* Flash is destination for this packet */
86 rc = flash_write((char *)src, (ulong)(load_addr+offset), len);
90 NetState = NETLOOP_FAIL;
94 #endif /* CFG_DIRECT_FLASH_TFTP */
96 (void)memcpy((void *)(load_addr + offset), src, len);
99 if(NetBootFileXferSize < newsize){
100 NetBootFileXferSize = newsize;
104 static void TftpSend(void);
105 static void TftpTimeout(void);
107 /**********************************************************************/
109 static void TftpSend(void){
116 * We will always be sending some sort of packet, so
117 * cobble together the packet headers now.
119 pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
125 *s++ = htons(TFTP_RRQ);
128 strcpy ((char *)pkt, tftp_filename);
130 pkt += strlen(tftp_filename) + 1;
131 strcpy ((char *)pkt, "octet");
133 pkt += 5 /*strlen("octet")*/ + 1;
134 strcpy ((char *)pkt, "timeout");
136 pkt += 7 /*strlen("timeout")*/ + 1;
137 sprintf((char *)pkt, "%d", TIMEOUT);
139 printf("send option \"timeout %s\"\n", (char *)pkt);
141 pkt += strlen((char *)pkt) + 1;
149 *s++ = htons(TFTP_ACK);
150 *s++ = htons(TftpBlock);
155 case STATE_TOO_LARGE:
158 *s++ = htons(TFTP_ERROR);
161 strcpy((char *)pkt, "File too large");
162 pkt += 14 /*strlen("File too large")*/ + 1;
166 case STATE_BAD_MAGIC:
169 *s++ = htons(TFTP_ERROR);
172 strcpy((char *)pkt, "File has bad magic");
173 pkt += 18 /*strlen("File has bad magic")*/ + 1;
178 NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort, TftpOurPort, len);
181 static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
186 if(dest != TftpOurPort){
190 if(TftpState != STATE_RRQ && src != TftpServerPort){
200 /* warning: don't use increment (++) in ntohs() macros!! */
205 switch(ntohs(proto)){
216 printf("Got OACK: %s %s\n", pkt, pkt+strlen(pkt)+1);
218 TftpState = STATE_OACK;
219 TftpServerPort = src;
220 TftpSend(); /* Send ACK */
230 TftpBlock = ntohs(*(ushort *)pkt);
233 * RFC1350 specifies that the first data packet will
234 * have sequence number 1. If we receive a sequence
235 * number of 0 this means that there was a wrap
236 * around of the (16 bit) counter.
240 TftpBlockWrapOffset += TFTP_BLOCK_SIZE * TFTP_SEQUENCE_SIZE;
241 printf("\n %lu MB received\n ", TftpBlockWrapOffset>>20);
243 if(((TftpBlock - 1) % 10) == 0){
245 } else if((TftpBlock % (10 * HASHES_PER_LINE)) == 0){
251 if(TftpState == STATE_RRQ){
252 puts("## Error: server did not acknowledge timeout option!\n");
256 if(TftpState == STATE_RRQ || TftpState == STATE_OACK){
257 /* first block received */
258 TftpState = STATE_DATA;
259 TftpServerPort = src;
262 TftpBlockWrapOffset = 0;
264 if(TftpBlock != 1){ /* Assertion */
265 printf("\n## Error: first block is not block 1 (%ld), starting again!\n\n", TftpBlock);
271 if(TftpBlock == TftpLastBlock){
273 * Same block again; ignore it.
278 TftpLastBlock = TftpBlock;
279 NetSetTimeout(TIMEOUT * CFG_HZ, TftpTimeout);
281 store_block(TftpBlock - 1, pkt + 2, len);
284 * Acknoledge the block just received, which will prompt
285 * the server for the next one.
289 if(len < TFTP_BLOCK_SIZE){
291 * We received the whole thing. Try to
294 puts("\n\nTFTP transfer complete!\n");
295 NetState = NETLOOP_SUCCESS;
301 printf("\n## Error: '%s' (%d), starting again!\n\n", pkt + 2, ntohs(*(ushort *)pkt));
307 static void TftpTimeout(void){
310 if(++TftpTimeoutCount > TIMEOUT_COUNT){
311 puts("\n\n## Error: retry count exceeded, starting again!\n\n");
315 NetSetTimeout(TIMEOUT * CFG_HZ, TftpTimeout);
320 void TftpStart(void){
323 #ifdef CONFIG_TFTP_PORT
324 char *ep; /* Environment pointer */
327 if(BootFile[0] == '\0'){
328 sprintf(default_filename, "%02lX%02lX%02lX%02lX.img", NetOurIP & 0xFF, (NetOurIP >> 8) & 0xFF, (NetOurIP >> 16) & 0xFF, (NetOurIP >> 24) & 0xFF);
329 tftp_filename = default_filename;
331 printf("** Warning: no boot file name, using: '%s'\n", tftp_filename);
333 tftp_filename = BootFile;
336 puts("\nTFTP from IP: ");
337 print_IPaddr(NetServerIP);
340 print_IPaddr(NetOurIP);
342 /* Check if we need to send across this subnet */
343 if(NetOurGatewayIP && NetOurSubnetMask){
344 IPaddr_t OurNet = NetOurIP & NetOurSubnetMask;
345 IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask;
347 if(OurNet != ServerNet){
348 puts("\n Gateway IP: ");
349 print_IPaddr(NetOurGatewayIP) ;
353 printf("\n Filename: '%s'", tftp_filename);
356 printf("\n Size: 0x%x Bytes = ", NetBootFileSize<<9);
357 print_size(NetBootFileSize<<9, "");
360 printf("\nLoad address: 0x%lx", load_addr);
362 #if defined(CONFIG_NET_MULTI)
363 printf("\n Using: %s", eth_get_name());
366 puts("\n\n Loading: *\b");
368 NetSetTimeout(TIMEOUT * CFG_HZ, TftpTimeout);
369 NetSetHandler(TftpHandler);
371 TftpServerPort = WELL_KNOWN_PORT;
372 TftpTimeoutCount = 0;
373 TftpState = STATE_RRQ;
375 /* Use a pseudo-random port unless a specific port is set */
376 TftpOurPort = 1024 + (get_timer(0) % 3072);
378 #ifdef CONFIG_TFTP_PORT
379 if((ep = getenv("tftpdstp")) != NULL){
380 TftpServerPort = simple_strtol(ep, NULL, 10);
382 if((ep = getenv("tftpsrcp")) != NULL){
383 TftpOurPort= simple_strtol(ep, NULL, 10);
389 /* zero out server ether in case the server ip has changed */
390 memset(NetServerEther, 0, 6);
395 #endif /* CONFIG_CMD_NET */