xref: /openbmc/u-boot/net/net.c (revision 518e2e1a)
1 /*
2  *	Copied from Linux Monitor (LiMon) - Networking.
3  *
4  *	Copyright 1994 - 2000 Neil Russell.
5  *	(See License)
6  *	Copyright 2000 Roland Borde
7  *	Copyright 2000 Paolo Scaffardi
8  *	Copyright 2000-2002 Wolfgang Denk, wd@denx.de
9  */
10 
11 /*
12  * General Desription:
13  *
14  * The user interface supports commands for BOOTP, RARP, and TFTP.
15  * Also, we support ARP internally. Depending on available data,
16  * these interact as follows:
17  *
18  * BOOTP:
19  *
20  *	Prerequisites:	- own ethernet address
21  *	We want:	- own IP address
22  *			- TFTP server IP address
23  *			- name of bootfile
24  *	Next step:	ARP
25  *
26  * RARP:
27  *
28  *	Prerequisites:	- own ethernet address
29  *	We want:	- own IP address
30  *			- TFTP server IP address
31  *	Next step:	ARP
32  *
33  * ARP:
34  *
35  *	Prerequisites:	- own ethernet address
36  *			- own IP address
37  *			- TFTP server IP address
38  *	We want:	- TFTP server ethernet address
39  *	Next step:	TFTP
40  *
41  * DHCP:
42  *
43  *     Prerequisites:   - own ethernet address
44  *     We want:         - IP, Netmask, ServerIP, Gateway IP
45  *                      - bootfilename, lease time
46  *     Next step:       - TFTP
47  *
48  * TFTP:
49  *
50  *	Prerequisites:	- own ethernet address
51  *			- own IP address
52  *			- TFTP server IP address
53  *			- TFTP server ethernet address
54  *			- name of bootfile (if unknown, we use a default name
55  *			  derived from our own IP address)
56  *	We want:	- load the boot file
57  *	Next step:	none
58  *
59  * NFS:
60  *
61  *	Prerequisites:	- own ethernet address
62  *			- own IP address
63  *			- name of bootfile (if unknown, we use a default name
64  *			  derived from our own IP address)
65  *	We want:	- load the boot file
66  *	Next step:	none
67  */
68 
69 
70 #include <common.h>
71 #include <watchdog.h>
72 #include <command.h>
73 #include <net.h>
74 #include "bootp.h"
75 #include "tftp.h"
76 #include "rarp.h"
77 #include "nfs.h"
78 #ifdef CONFIG_STATUS_LED
79 #include <status_led.h>
80 #include <miiphy.h>
81 #endif
82 
83 #if (CONFIG_COMMANDS & CFG_CMD_NET)
84 
85 #define ARP_TIMEOUT		5		/* Seconds before trying ARP again */
86 #ifndef	CONFIG_NET_RETRY_COUNT
87 # define ARP_TIMEOUT_COUNT	5		/* # of timeouts before giving up  */
88 #else
89 # define ARP_TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
90 #endif
91 
92 #if 0
93 #define ET_DEBUG
94 #endif
95 
96 /** BOOTP EXTENTIONS **/
97 
98 IPaddr_t	NetOurSubnetMask=0;		/* Our subnet mask (0=unknown)	*/
99 IPaddr_t	NetOurGatewayIP=0;		/* Our gateways IP address	*/
100 IPaddr_t	NetOurDNSIP=0;			/* Our DNS IP address		*/
101 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
102 IPaddr_t	NetOurDNS2IP=0;			/* Our 2nd DNS IP address	*/
103 #endif
104 char		NetOurNISDomain[32]={0,};	/* Our NIS domain		*/
105 char		NetOurHostName[32]={0,};	/* Our hostname			*/
106 char		NetOurRootPath[64]={0,};	/* Our bootpath			*/
107 ushort		NetBootFileSize=0;		/* Our bootfile size in blocks	*/
108 
109 /** END OF BOOTP EXTENTIONS **/
110 
111 ulong		NetBootFileXferSize;	/* The actual transferred size of the bootfile (in bytes) */
112 uchar		NetOurEther[6];		/* Our ethernet address			*/
113 uchar		NetServerEther[6] =	/* Boot server enet address		*/
114 			{ 0, 0, 0, 0, 0, 0 };
115 IPaddr_t	NetOurIP;		/* Our IP addr (0 = unknown)		*/
116 IPaddr_t	NetServerIP;		/* Our IP addr (0 = unknown)		*/
117 volatile uchar *NetRxPkt;		/* Current receive packet		*/
118 int		NetRxPktLen;		/* Current rx packet length		*/
119 unsigned	NetIPID;		/* IP packet ID				*/
120 uchar		NetBcastAddr[6] =	/* Ethernet bcast address		*/
121 			{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
122 uchar		NetEtherNullAddr[6] =
123 			{ 0, 0, 0, 0, 0, 0 };
124 int		NetState;		/* Network loop state			*/
125 #ifdef CONFIG_NET_MULTI
126 int		NetRestartWrap = 0;	/* Tried all network devices		*/
127 static int	NetRestarted = 0;	/* Network loop restarted		*/
128 static int	NetDevExists = 0;	/* At least one device configured	*/
129 #endif
130 
131 char		BootFile[128];		/* Boot File name			*/
132 
133 #if (CONFIG_COMMANDS & CFG_CMD_PING)
134 IPaddr_t	NetPingIP;		/* the ip address to ping 		*/
135 
136 static void PingStart(void);
137 #endif
138 
139 volatile uchar	PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
140 
141 volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets			*/
142 
143 static rxhand_f *packetHandler;		/* Current RX packet handler		*/
144 static thand_f *timeHandler;		/* Current timeout handler		*/
145 static ulong	timeStart;		/* Time base value			*/
146 static ulong	timeDelta;		/* Current timeout value		*/
147 volatile uchar *NetTxPacket = 0;	/* THE transmit packet			*/
148 
149 static int net_check_prereq (proto_t protocol);
150 
151 /**********************************************************************/
152 
153 IPaddr_t	NetArpWaitPacketIP;
154 IPaddr_t	NetArpWaitReplyIP;
155 uchar	       *NetArpWaitPacketMAC;	/* MAC address of waiting packet's destination	*/
156 uchar          *NetArpWaitTxPacket;	/* THE transmit packet			*/
157 int		NetArpWaitTxPacketSize;
158 uchar 		NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
159 ulong		NetArpWaitTimerStart;
160 int		NetArpWaitTry;
161 
162 void ArpRequest(void)
163 {
164 	int i;
165 	volatile uchar *pkt;
166 	ARP_t *	arp;
167 
168 #ifdef ET_DEBUG
169 	printf("ARP broadcast %d\n", NetArpWaitTry);
170 #endif
171 	pkt = NetTxPacket;
172 
173 	NetSetEther(pkt, NetBcastAddr, PROT_ARP);
174 	pkt += ETHER_HDR_SIZE;
175 
176 	arp = (ARP_t *)pkt;
177 
178 	arp->ar_hrd = htons(ARP_ETHER);
179 	arp->ar_pro = htons(PROT_IP);
180 	arp->ar_hln = 6;
181 	arp->ar_pln = 4;
182 	arp->ar_op  = htons(ARPOP_REQUEST);
183 
184 	memcpy (&arp->ar_data[0], NetOurEther, 6);	/* source ET addr	*/
185 	NetWriteIP((uchar*)&arp->ar_data[6], NetOurIP);	/* source IP addr	*/
186 	for (i=10; i<16; ++i) {
187 		arp->ar_data[i] = 0;			/* dest ET addr = 0	*/
188 	}
189 
190 	if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)) {
191 	    if (NetOurGatewayIP == 0) {
192 		puts ("## Warning: gatewayip needed but not set\n");
193 	    }
194 	    NetArpWaitReplyIP = NetOurGatewayIP;
195 	} else
196 	    NetArpWaitReplyIP = NetArpWaitPacketIP;
197 
198 	NetWriteIP((uchar*)&arp->ar_data[16], NetArpWaitReplyIP);
199 	(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE);
200 }
201 
202 void ArpTimeoutCheck(void)
203 {
204 	ulong t;
205 
206 	if (!NetArpWaitPacketIP)
207 		return;
208 
209 	t = get_timer(0);
210 
211 	/* check for arp timeout */
212 	if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) {
213 		NetArpWaitTry++;
214 
215 		if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
216 			puts ("\nARP Retry count exceeded; starting again\n");
217 			NetArpWaitTry = 0;
218 			NetStartAgain();
219 		} else {
220 			NetArpWaitTimerStart = t;
221 			ArpRequest();
222 		}
223 	}
224 }
225 
226 /**********************************************************************/
227 /*
228  *	Main network processing loop.
229  */
230 
231 int
232 NetLoop(proto_t protocol)
233 {
234 	DECLARE_GLOBAL_DATA_PTR;
235 
236 	bd_t *bd = gd->bd;
237 
238 #ifdef CONFIG_NET_MULTI
239 	NetRestarted = 0;
240 	NetDevExists = 0;
241 #endif
242 
243 	/* XXX problem with bss workaround */
244 	NetArpWaitPacketMAC = NULL;
245 	NetArpWaitTxPacket = NULL;
246 	NetArpWaitPacketIP = 0;
247 	NetArpWaitReplyIP = 0;
248 	NetArpWaitTxPacket = NULL;
249 	NetTxPacket = NULL;
250 
251 	if (!NetTxPacket) {
252 		int	i;
253 
254 		/*
255 		 *	Setup packet buffers, aligned correctly.
256 		 */
257 		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
258 		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
259 		for (i = 0; i < PKTBUFSRX; i++) {
260 			NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
261 		}
262 
263 	}
264 
265 	if (!NetArpWaitTxPacket) {
266 		NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
267 		NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
268 		NetArpWaitTxPacketSize = 0;
269 	}
270 
271 	eth_halt();
272 	if(eth_init(bd) < 0)
273 	    return(-1);
274 
275 restart:
276 #ifdef CONFIG_NET_MULTI
277 	memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
278 #else
279 	memcpy (NetOurEther, bd->bi_enetaddr, 6);
280 #endif
281 
282 	NetState = NETLOOP_CONTINUE;
283 
284 	/*
285 	 *	Start the ball rolling with the given start function.  From
286 	 *	here on, this code is a state machine driven by received
287 	 *	packets and timer events.
288 	 */
289 
290 	switch (protocol) {
291 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
292 	case NFS:
293 #endif
294 #if (CONFIG_COMMANDS & CFG_CMD_PING)
295 	case PING:
296 #endif
297 	case TFTP:
298 		NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
299 		NetOurGatewayIP = getenv_IPaddr ("gatewayip");
300 		NetOurSubnetMask= getenv_IPaddr ("netmask");
301 
302 		switch (protocol) {
303 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
304 		case NFS:
305 #endif
306 		case TFTP:
307 			NetServerIP = getenv_IPaddr ("serverip");
308 			break;
309 #if (CONFIG_COMMANDS & CFG_CMD_PING)
310 		case PING:
311 			/* nothing */
312 			break;
313 #endif
314 		default:
315 			break;
316 		}
317 
318 		break;
319 	case BOOTP:
320 	case RARP:
321 		/*
322 		 * initialize our IP addr to 0 in order to accept ANY
323 		 * IP addr assigned to us by the BOOTP / RARP server
324 		 */
325 		NetOurIP = 0;
326 		NetServerIP = getenv_IPaddr ("serverip");
327 		break;
328 	default:
329 		break;
330 	}
331 
332 	switch (net_check_prereq (protocol)) {
333 	case 1:
334 		/* network not configured */
335 		return (-1);
336 
337 #ifdef CONFIG_NET_MULTI
338 	case 2:
339 		/* network device not configured */
340 		break;
341 #endif /* CONFIG_NET_MULTI */
342 
343 	case 0:
344 #ifdef CONFIG_NET_MULTI
345 		NetDevExists = 1;
346 #endif
347 		switch (protocol) {
348 		case TFTP:
349 			/* always use ARP to get server ethernet address */
350 			TftpStart();
351 			break;
352 
353 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
354 		case DHCP:
355 			/* Start with a clean slate... */
356 			NetOurIP = 0;
357 			NetServerIP = getenv_IPaddr ("serverip");
358 			DhcpRequest();		/* Basically same as BOOTP */
359 			break;
360 #endif /* CFG_CMD_DHCP */
361 
362 		case BOOTP:
363 			BootpTry = 0;
364 			BootpRequest ();
365 			break;
366 
367 		case RARP:
368 			RarpTry = 0;
369 			RarpRequest ();
370 			break;
371 #if (CONFIG_COMMANDS & CFG_CMD_PING)
372 		case PING:
373 			PingStart();
374 			break;
375 #endif
376 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
377 		case NFS:
378 			NfsStart();
379 			break;
380 #endif
381 		default:
382 			break;
383 		}
384 
385 		NetBootFileXferSize = 0;
386 		break;
387 	}
388 
389 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
390 #if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
391 	/*
392 	 * Echo the inverted link state to the fault LED.
393 	 */
394 	if(miiphy_link(CFG_FAULT_MII_ADDR)) {
395 		status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
396 	} else {
397 		status_led_set (STATUS_LED_RED, STATUS_LED_ON);
398 	}
399 #endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */
400 #endif /* CONFIG_MII, ... */
401 
402 	/*
403 	 *	Main packet reception loop.  Loop receiving packets until
404 	 *	someone sets `NetQuit'.
405 	 */
406 	for (;;) {
407 		WATCHDOG_RESET();
408 #ifdef CONFIG_SHOW_ACTIVITY
409 		{
410 			extern void show_activity(int arg);
411 			show_activity(1);
412 		}
413 #endif
414 		/*
415 		 *	Check the ethernet for a new packet.  The ethernet
416 		 *	receive routine will process it.
417 		 */
418 			eth_rx();
419 
420 		/*
421 		 *	Abort if ctrl-c was pressed.
422 		 */
423 		if (ctrlc()) {
424 			eth_halt();
425 			puts ("\nAbort\n");
426 			return (-1);
427 		}
428 
429 		ArpTimeoutCheck();
430 
431 		/*
432 		 *	Check for a timeout, and run the timeout handler
433 		 *	if we have one.
434 		 */
435 		if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
436 			thand_f *x;
437 
438 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
439 #if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
440 			/*
441 			 * Echo the inverted link state to the fault LED.
442 			 */
443 			if(miiphy_link(CFG_FAULT_MII_ADDR)) {
444 				status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
445 			} else {
446 				status_led_set (STATUS_LED_RED, STATUS_LED_ON);
447 			}
448 #endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */
449 #endif /* CONFIG_MII, ... */
450 			x = timeHandler;
451 			timeHandler = (thand_f *)0;
452 			(*x)();
453 		}
454 
455 
456 		switch (NetState) {
457 
458 		case NETLOOP_RESTART:
459 #ifdef CONFIG_NET_MULTI
460 			NetRestarted = 1;
461 #endif
462 			goto restart;
463 
464 		case NETLOOP_SUCCESS:
465 			if (NetBootFileXferSize > 0) {
466 				char buf[10];
467 				printf("Bytes transferred = %ld (%lx hex)\n",
468 					NetBootFileXferSize,
469 					NetBootFileXferSize);
470 				sprintf(buf, "%lx", NetBootFileXferSize);
471 				setenv("filesize", buf);
472 			}
473 			eth_halt();
474 			return NetBootFileXferSize;
475 
476 		case NETLOOP_FAIL:
477 			return (-1);
478 		}
479 	}
480 }
481 
482 /**********************************************************************/
483 
484 static void
485 startAgainTimeout(void)
486 {
487 	NetState = NETLOOP_RESTART;
488 }
489 
490 static void
491 startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
492 {
493 	/* Totally ignore the packet */
494 }
495 
496 void
497 NetStartAgain(void)
498 {
499 #ifndef CONFIG_NET_MULTI
500 	NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
501 	NetSetHandler(startAgainHandler);
502 #else
503 	DECLARE_GLOBAL_DATA_PTR;
504 
505 	eth_halt();
506 	eth_try_another(!NetRestarted);
507 	eth_init(gd->bd);
508 	if (NetRestartWrap)
509 	{
510 		NetRestartWrap = 0;
511 		if (NetDevExists)
512 		{
513 			NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
514 			NetSetHandler(startAgainHandler);
515 		}
516 		else
517 		{
518 			NetState = NETLOOP_FAIL;
519 		}
520 	}
521 	else
522 	{
523 		NetState = NETLOOP_RESTART;
524 	}
525 #endif
526 }
527 
528 /**********************************************************************/
529 /*
530  *	Miscelaneous bits.
531  */
532 
533 void
534 NetSetHandler(rxhand_f * f)
535 {
536 	packetHandler = f;
537 }
538 
539 
540 void
541 NetSetTimeout(int iv, thand_f * f)
542 {
543 	if (iv == 0) {
544 		timeHandler = (thand_f *)0;
545 	} else {
546 		timeHandler = f;
547 		timeStart = get_timer(0);
548 		timeDelta = iv;
549 	}
550 }
551 
552 
553 void
554 NetSendPacket(volatile uchar * pkt, int len)
555 {
556 	(void) eth_send(pkt, len);
557 }
558 
559 int
560 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
561 {
562 	/* convert to new style broadcast */
563 	if (dest == 0)
564 		dest = 0xFFFFFFFF;
565 
566 	/* if broadcast, make the ether address a broadcast and don't do ARP */
567 	if (dest == 0xFFFFFFFF)
568 		ether = NetBcastAddr;
569 
570 	/* if MAC address was not discovered yet, save the packet and do an ARP request */
571 	if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
572 
573 #ifdef ET_DEBUG
574 		printf("sending ARP for %08lx\n", dest);
575 #endif
576 
577 		NetArpWaitPacketIP = dest;
578 		NetArpWaitPacketMAC = ether;
579 		NetSetEther (NetArpWaitTxPacket, NetArpWaitPacketMAC, PROT_IP);
580 		NetSetIP (NetArpWaitTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
581 		memcpy(NetArpWaitTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE,
582 			(uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, len);
583 
584 		/* size of the waiting packet */
585 		NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE + len;
586 
587 		/* and do the ARP request */
588 		NetArpWaitTry = 1;
589 		NetArpWaitTimerStart = get_timer(0);
590 		ArpRequest();
591 		return 1;	/* waiting */
592 	}
593 
594 #ifdef ET_DEBUG
595 	printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
596 			dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
597 #endif
598 
599 	NetSetEther (NetTxPacket, ether, PROT_IP);
600 	NetSetIP (NetTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
601 	(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len);
602 
603 	return 0;	/* transmited */
604 }
605 
606 #if (CONFIG_COMMANDS & CFG_CMD_PING)
607 static ushort PingSeqNo;
608 
609 int PingSend(void)
610 {
611 	static uchar mac[6];
612 	volatile IP_t *ip;
613 	volatile ushort *s;
614 
615 	/* XXX always send arp request */
616 
617 	memcpy(mac, NetEtherNullAddr, 6);
618 
619 #ifdef ET_DEBUG
620 	printf("sending ARP for %08lx\n", NetPingIP);
621 #endif
622 
623 	NetArpWaitPacketIP = NetPingIP;
624 	NetArpWaitPacketMAC = mac;
625 
626 	NetSetEther(NetArpWaitTxPacket, mac, PROT_IP);
627 
628 	ip = (volatile IP_t *)(NetArpWaitTxPacket + ETHER_HDR_SIZE);
629 
630 	/*
631 	 *	Construct an IP and ICMP header.  (need to set no fragment bit - XXX)
632 	 */
633 	ip->ip_hl_v  = 0x45;		/* IP_HDR_SIZE / 4 (not including UDP) */
634 	ip->ip_tos   = 0;
635 	ip->ip_len   = htons(IP_HDR_SIZE_NO_UDP + 8);
636 	ip->ip_id    = htons(NetIPID++);
637 	ip->ip_off   = htons(0x4000);	/* No fragmentation */
638 	ip->ip_ttl   = 255;
639 	ip->ip_p     = 0x01;		/* ICMP */
640 	ip->ip_sum   = 0;
641 	NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
642 	NetCopyIP((void*)&ip->ip_dst, &NetPingIP);	   /* - "" - */
643 	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
644 
645 	s = &ip->udp_src;		/* XXX ICMP starts here */
646 	s[0] = htons(0x0800);		/* echo-request, code */
647 	s[1] = 0;			/* checksum */
648 	s[2] = 0; 			/* identifier */
649 	s[3] = htons(PingSeqNo++);	/* sequence number */
650 	s[1] = ~NetCksum((uchar *)s, 8/2);
651 
652 	/* size of the waiting packet */
653 	NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE_NO_UDP + 8;
654 
655 	/* and do the ARP request */
656 	NetArpWaitTry = 1;
657 	NetArpWaitTimerStart = get_timer(0);
658 	ArpRequest();
659 	return 1;	/* waiting */
660 }
661 
662 static void
663 PingTimeout (void)
664 {
665 	eth_halt();
666 	NetState = NETLOOP_FAIL;	/* we did not get the reply */
667 }
668 
669 static void
670 PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
671 {
672 	IPaddr_t tmp;
673 	volatile IP_t *ip = (volatile IP_t *)pkt;
674 
675 	tmp = NetReadIP((void *)&ip->ip_src);
676 	if (tmp != NetPingIP)
677 		return;
678 
679 	NetState = NETLOOP_SUCCESS;
680 }
681 
682 static void PingStart(void)
683 {
684 	NetSetTimeout (10 * CFG_HZ, PingTimeout);
685 	NetSetHandler (PingHandler);
686 
687 	PingSend();
688 }
689 
690 #endif
691 
692 void
693 NetReceive(volatile uchar * pkt, int len)
694 {
695 	Ethernet_t *et;
696 	IP_t	*ip;
697 	ARP_t	*arp;
698 	IPaddr_t tmp;
699 	int	x;
700 
701 	NetRxPkt = pkt;
702 	NetRxPktLen = len;
703 	et = (Ethernet_t *)pkt;
704 
705 	x = ntohs(et->et_protlen);
706 
707 	if (x < 1514) {
708 		/*
709 		 *	Got a 802 packet.  Check the other protocol field.
710 		 */
711 		x = ntohs(et->et_prot);
712 		ip = (IP_t *)(pkt + E802_HDR_SIZE);
713 		len -= E802_HDR_SIZE;
714 	} else {
715 		ip = (IP_t *)(pkt + ETHER_HDR_SIZE);
716 		len -= ETHER_HDR_SIZE;
717 	}
718 
719 #ifdef ET_DEBUG
720 	printf("Receive from protocol 0x%x\n", x);
721 #endif
722 
723 	switch (x) {
724 
725 	case PROT_ARP:
726 		/*
727 		 * We have to deal with two types of ARP packets:
728 		 * - REQUEST packets will be answered by sending  our
729 		 *   IP address - if we know it.
730 		 * - REPLY packates are expected only after we asked
731 		 *   for the TFTP server's or the gateway's ethernet
732 		 *   address; so if we receive such a packet, we set
733 		 *   the server ethernet address
734 		 */
735 #ifdef ET_DEBUG
736 		puts ("Got ARP\n");
737 #endif
738 		arp = (ARP_t *)ip;
739 		if (len < ARP_HDR_SIZE) {
740 			printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
741 			return;
742 		}
743 		if (ntohs(arp->ar_hrd) != ARP_ETHER) {
744 			return;
745 		}
746 		if (ntohs(arp->ar_pro) != PROT_IP) {
747 			return;
748 		}
749 		if (arp->ar_hln != 6) {
750 			return;
751 		}
752 		if (arp->ar_pln != 4) {
753 			return;
754 		}
755 
756 		if (NetOurIP == 0) {
757 			return;
758 		}
759 
760 		if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
761 			return;
762 		}
763 
764 		switch (ntohs(arp->ar_op)) {
765 		case ARPOP_REQUEST:		/* reply with our IP address	*/
766 #ifdef ET_DEBUG
767 			puts ("Got ARP REQUEST, return our IP\n");
768 #endif
769 			NetSetEther((uchar *)et, et->et_src, PROT_ARP);
770 			arp->ar_op = htons(ARPOP_REPLY);
771 			memcpy   (&arp->ar_data[10], &arp->ar_data[0], 6);
772 			NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
773 			memcpy   (&arp->ar_data[ 0], NetOurEther, 6);
774 			NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
775 			(void) eth_send((uchar *)et, ((uchar *)arp-pkt) + ARP_HDR_SIZE);
776 			return;
777 
778 		case ARPOP_REPLY:		/* arp reply */
779 			/* are we waiting for a reply */
780 			if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
781 				break;
782 #ifdef ET_DEBUG
783 			printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
784 				arp->ar_data[0], arp->ar_data[1],
785 				arp->ar_data[2], arp->ar_data[3],
786 				arp->ar_data[4], arp->ar_data[5]);
787 #endif
788 
789 			tmp = NetReadIP(&arp->ar_data[6]);
790 
791 			/* matched waiting packet's address */
792 			if (tmp == NetArpWaitReplyIP) {
793 #ifdef ET_DEBUG
794 				puts ("Got it\n");
795 #endif
796 				/* save address for later use */
797 				memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
798 
799 				/* modify header, and transmit it */
800 				memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
801 				(void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
802 
803 				/* no arp request pending now */
804 				NetArpWaitPacketIP = 0;
805 				NetArpWaitTxPacketSize = 0;
806 				NetArpWaitPacketMAC = NULL;
807 
808 			}
809 			return;
810 		default:
811 #ifdef ET_DEBUG
812 			printf("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
813 #endif
814 			return;
815 		}
816 
817 	case PROT_RARP:
818 #ifdef ET_DEBUG
819 		puts ("Got RARP\n");
820 #endif
821 		arp = (ARP_t *)ip;
822 		if (len < ARP_HDR_SIZE) {
823 			printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
824 			return;
825 		}
826 
827 		if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
828 			(ntohs(arp->ar_hrd) != ARP_ETHER)   ||
829 			(ntohs(arp->ar_pro) != PROT_IP)     ||
830 			(arp->ar_hln != 6) || (arp->ar_pln != 4)) {
831 
832 			puts ("invalid RARP header\n");
833 		} else {
834 			NetCopyIP(&NetOurIP,    &arp->ar_data[16]);
835 			if (NetServerIP == 0)
836 				NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
837 			memcpy (NetServerEther, &arp->ar_data[ 0], 6);
838 
839 			(*packetHandler)(0,0,0,0);
840 		}
841 		break;
842 
843 	case PROT_IP:
844 #ifdef ET_DEBUG
845 		puts ("Got IP\n");
846 #endif
847 		if (len < IP_HDR_SIZE) {
848 			debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
849 			return;
850 		}
851 		if (len < ntohs(ip->ip_len)) {
852 			printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
853 			return;
854 		}
855 		len = ntohs(ip->ip_len);
856 #ifdef ET_DEBUG
857 		printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
858 #endif
859 		if ((ip->ip_hl_v & 0xf0) != 0x40) {
860 			return;
861 		}
862 		if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
863 			return;
864 		}
865 		if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
866 			puts ("checksum bad\n");
867 			return;
868 		}
869 		tmp = NetReadIP(&ip->ip_dst);
870 		if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
871 			return;
872 		}
873 		/*
874 		 * watch for ICMP host redirects
875 		 *
876 		 * There is no real handler code (yet). We just watch
877 		 * for ICMP host redirect messages. In case anybody
878 		 * sees these messages: please contact me
879 		 * (wd@denx.de), or - even better - send me the
880 		 * necessary fixes :-)
881 		 *
882 		 * Note: in all cases where I have seen this so far
883 		 * it was a problem with the router configuration,
884 		 * for instance when a router was configured in the
885 		 * BOOTP reply, but the TFTP server was on the same
886 		 * subnet. So this is probably a warning that your
887 		 * configuration might be wrong. But I'm not really
888 		 * sure if there aren't any other situations.
889 		 */
890 		if (ip->ip_p == IPPROTO_ICMP) {
891 			ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
892 
893 			switch (icmph->type) {
894 			case ICMP_REDIRECT:
895 			if (icmph->code != ICMP_REDIR_HOST)
896 				return;
897 			puts (" ICMP Host Redirect to ");
898 			print_IPaddr(icmph->un.gateway);
899 			putc(' ');
900 				break;
901 #if (CONFIG_COMMANDS & CFG_CMD_PING)
902 			case ICMP_ECHO_REPLY:
903 				/*
904 				 *	IP header OK.  Pass the packet to the current handler.
905 				 */
906 				/* XXX point to ip packet */
907 				(*packetHandler)((uchar *)ip, 0, 0, 0);
908 				break;
909 #endif
910 			default:
911 				return;
912 			}
913 		} else if (ip->ip_p != IPPROTO_UDP) {	/* Only UDP packets */
914 			return;
915 		}
916 
917 		/*
918 		 *	IP header OK.  Pass the packet to the current handler.
919 		 */
920 		(*packetHandler)((uchar *)ip +IP_HDR_SIZE,
921 						ntohs(ip->udp_dst),
922 						ntohs(ip->udp_src),
923 						ntohs(ip->udp_len) - 8);
924 
925 		break;
926 	}
927 }
928 
929 
930 /**********************************************************************/
931 
932 static int net_check_prereq (proto_t protocol)
933 {
934 	switch (protocol) {
935 			/* Fall through */
936 #if (CONFIG_COMMANDS & CFG_CMD_PING)
937 	case PING:
938 			if (NetPingIP == 0) {
939 				puts ("*** ERROR: ping address not given\n");
940 				return (1);
941 			}
942 			goto common;
943 #endif
944 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
945 	case NFS:
946 #endif
947 	case TFTP:
948 			if (NetServerIP == 0) {
949 				puts ("*** ERROR: `serverip' not set\n");
950 				return (1);
951 			}
952 
953 #if (CONFIG_COMMANDS & CFG_CMD_PING)
954 		common:
955 #endif
956 
957 			if (NetOurIP == 0) {
958 				puts ("*** ERROR: `ipaddr' not set\n");
959 				return (1);
960 			}
961 			/* Fall through */
962 
963 	case DHCP:
964 	case RARP:
965 	case BOOTP:
966 			if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
967 #ifdef CONFIG_NET_MULTI
968 			    extern int eth_get_dev_index (void);
969 			    int num = eth_get_dev_index();
970 
971 			    switch (num) {
972 			    case -1:
973 				puts ("*** ERROR: No ethernet found.\n");
974 				return (1);
975 			    case 0:
976 				puts ("*** ERROR: `ethaddr' not set\n");
977 				break;
978 			    default:
979 				printf ("*** ERROR: `eth%daddr' not set\n",
980 					num);
981 				break;
982 			    }
983 
984 			    NetStartAgain ();
985 			    return (2);
986 #else
987 			    puts ("*** ERROR: `ethaddr' not set\n");
988 			    return (1);
989 #endif
990 			}
991 			/* Fall through */
992 		default:
993 			return(0);
994 	}
995 	return (0);	/* OK */
996 }
997 /**********************************************************************/
998 
999 int
1000 NetCksumOk(uchar * ptr, int len)
1001 {
1002 	return !((NetCksum(ptr, len) + 1) & 0xfffe);
1003 }
1004 
1005 
1006 unsigned
1007 NetCksum(uchar * ptr, int len)
1008 {
1009 	ulong	xsum;
1010 
1011 	xsum = 0;
1012 	while (len-- > 0)
1013 		xsum += *((ushort *)ptr)++;
1014 	xsum = (xsum & 0xffff) + (xsum >> 16);
1015 	xsum = (xsum & 0xffff) + (xsum >> 16);
1016 	return (xsum & 0xffff);
1017 }
1018 
1019 
1020 void
1021 NetSetEther(volatile uchar * xet, uchar * addr, uint prot)
1022 {
1023 	Ethernet_t *et = (Ethernet_t *)xet;
1024 
1025 	memcpy (et->et_dest, addr, 6);
1026 	memcpy (et->et_src, NetOurEther, 6);
1027 	et->et_protlen = htons(prot);
1028 }
1029 
1030 
1031 void
1032 NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
1033 {
1034 	volatile IP_t *ip = (IP_t *)xip;
1035 
1036 	/*
1037 	 *	If the data is an odd number of bytes, zero the
1038 	 *	byte after the last byte so that the checksum
1039 	 *	will work.
1040 	 */
1041 	if (len & 1)
1042 		xip[IP_HDR_SIZE + len] = 0;
1043 
1044 	/*
1045 	 *	Construct an IP and UDP header.
1046 			(need to set no fragment bit - XXX)
1047 	 */
1048 	ip->ip_hl_v  = 0x45;		/* IP_HDR_SIZE / 4 (not including UDP) */
1049 	ip->ip_tos   = 0;
1050 	ip->ip_len   = htons(IP_HDR_SIZE + len);
1051 	ip->ip_id    = htons(NetIPID++);
1052 	ip->ip_off   = htons(0x4000);	/* No fragmentation */
1053 	ip->ip_ttl   = 255;
1054 	ip->ip_p     = 17;		/* UDP */
1055 	ip->ip_sum   = 0;
1056 	NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1057 	NetCopyIP((void*)&ip->ip_dst, &dest);	   /* - "" - */
1058 	ip->udp_src  = htons(sport);
1059 	ip->udp_dst  = htons(dport);
1060 	ip->udp_len  = htons(8 + len);
1061 	ip->udp_xsum = 0;
1062 	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1063 }
1064 
1065 void copy_filename (uchar *dst, uchar *src, int size)
1066 {
1067 	if (*src && (*src == '"')) {
1068 		++src;
1069 		--size;
1070 	}
1071 
1072 	while ((--size > 0) && *src && (*src != '"')) {
1073 		*dst++ = *src++;
1074 	}
1075 	*dst = '\0';
1076 }
1077 
1078 #endif /* CFG_CMD_NET */
1079 
1080 void ip_to_string (IPaddr_t x, char *s)
1081 {
1082     x = ntohl(x);
1083     sprintf (s,"%d.%d.%d.%d",
1084 	(int)((x >> 24) & 0xff),
1085 	(int)((x >> 16) & 0xff),
1086 	(int)((x >>  8) & 0xff),
1087 	(int)((x >>  0) & 0xff)
1088     );
1089 }
1090 
1091 IPaddr_t string_to_ip(char *s)
1092 {
1093 	IPaddr_t addr;
1094 	char *e;
1095 	int i;
1096 
1097 	if (s == NULL)
1098 		return(0);
1099 
1100 	for (addr=0, i=0; i<4; ++i) {
1101 		ulong val = s ? simple_strtoul(s, &e, 10) : 0;
1102 		addr <<= 8;
1103 		addr |= (val & 0xFF);
1104 		if (s) {
1105 			s = (*e) ? e+1 : e;
1106 		}
1107 	}
1108 
1109 	return (htonl(addr));
1110 }
1111 
1112 void print_IPaddr (IPaddr_t x)
1113 {
1114     char tmp[16];
1115 
1116     ip_to_string(x, tmp);
1117 
1118     puts(tmp);
1119 }
1120 
1121 IPaddr_t getenv_IPaddr (char *var)
1122 {
1123 	return (string_to_ip(getenv(var)));
1124 }
1125