Small fixes in new web pages
[oweals/u-boot_mod.git] / u-boot / net / net.c
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  * SNTP:
69  *
70  *      Prerequisites:  - own ethernet address
71  *                      - own IP address
72  *      We want:        - network time
73  *      Next step:      none
74  */
75
76 #include <common.h>
77 #include <command.h>
78 #include <net.h>
79 #include "bootp.h"
80 #include "tftp.h"
81 #include "rarp.h"
82 #include "nfs.h"
83 #include "httpd.h"
84
85 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
86 #include "sntp.h"
87 #endif
88
89 #include "../httpd/uipopt.h"
90 #include "../httpd/uip.h"
91 #include "../httpd/uip_arp.h"
92
93 #if (CONFIG_COMMANDS & CFG_CMD_NET)
94
95 DECLARE_GLOBAL_DATA_PTR;
96
97 #define ARP_TIMEOUT                             5               /* Seconds before trying ARP again */
98
99 #ifndef CONFIG_NET_RETRY_COUNT
100         #define ARP_TIMEOUT_COUNT       5               /* # of timeouts before giving up  */
101 #else
102         #define ARP_TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
103 #endif
104
105 unsigned char *webfailsafe_data_pointer = NULL;
106 int     webfailsafe_is_running = 0;
107 int     webfailsafe_ready_for_upgrade = 0;
108 int     webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
109
110 void NetReceiveHttpd(volatile uchar * inpkt, int len);
111
112 extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
113
114 /** BOOTP EXTENTIONS **/
115 IPaddr_t NetOurSubnetMask = 0;          /* Our subnet mask (0=unknown) */
116 IPaddr_t NetOurGatewayIP = 0;           /* Our gateways IP address */
117 IPaddr_t NetOurDNSIP = 0;                       /* Our DNS IP address */
118
119 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
120 IPaddr_t NetOurDNS2IP = 0;                      /* Our 2nd DNS IP address */
121 #endif
122
123 char NetOurNISDomain[32] = {0,};        /* Our NIS domain */
124 char NetOurHostName[32] = {0,};         /* Our hostname */
125 char NetOurRootPath[64] = {0,};         /* Our bootpath */
126 ushort NetBootFileSize = 0;                     /* Our bootfile size in blocks */
127 /** END OF BOOTP EXTENTIONS **/
128
129 ulong NetBootFileXferSize;                                              /* The actual transferred size of the bootfile (in bytes) */
130 uchar NetOurEther[6];                                                   /* Our ethernet address */
131 uchar NetServerEther[6] = {0, 0, 0, 0, 0, 0};   /* Boot server enet address */
132 IPaddr_t NetOurIP;                                                              /* Our IP addr (0 = unknown) */
133 IPaddr_t NetServerIP;                                                   /* Server IP addr (0 = unknown) */
134 volatile uchar *NetRxPkt;                                               /* Current receive packet */
135 int NetRxPktLen;                                                                /* Current rx packet length */
136 unsigned NetIPID;                                                               /* IP packet ID */
137
138 uchar NetBcastAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};   /* Ethernet bcast address */
139 uchar NetEtherNullAddr[6] = {0, 0, 0, 0, 0, 0};
140
141 int NetState;   /* Network loop state */
142
143 #ifdef CONFIG_NET_MULTI
144 int NetRestartWrap = 0;                 /* Tried all network devices */
145 static int NetRestarted = 0;    /* Network loop restarted */
146 static int NetDevExists = 0;    /* At least one device configured */
147 #endif
148
149 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
150 ushort NetOurVLAN = 0xFFFF;                     /* default is without VLAN */
151 ushort NetOurNativeVLAN = 0xFFFF;       /* ditto */
152
153 char BootFile[128]; /* Boot File name */
154
155 #if (CONFIG_COMMANDS & CFG_CMD_PING)
156 IPaddr_t NetPingIP;     /* the ip address to ping */
157 static void PingStart(void);
158 #endif /* CFG_CMD_PING */
159
160 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
161 IPaddr_t NetNtpServerIP;        /* NTP server IP address */
162 int NetTimeOffset = 0;          /* offset time from UTC */
163 #endif /* CFG_CMD_SNTP */
164
165 #ifdef CONFIG_NETCONSOLE
166 void NcStart(void);
167 int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
168 #endif /* CONFIG_NETCONSOLE */
169
170 volatile uchar PktBuf[(PKTBUFSRX + 1) * PKTSIZE_ALIGN + PKTALIGN];
171 volatile uchar *NetRxPackets[PKTBUFSRX];        /* Receive packets */
172
173 static rxhand_f *packetHandler;         /* Current RX packet handler */
174 static thand_f *timeHandler;            /* Current timeout handler */
175 static ulong timeStart;                         /* Time base value */
176 static ulong timeDelta;                         /* Current timeout value */
177 volatile uchar *NetTxPacket = 0;        /* THE transmit packet */
178
179 static int net_check_prereq(proto_t protocol);
180
181 /**********************************************************************/
182
183 IPaddr_t NetArpWaitPacketIP;
184 IPaddr_t NetArpWaitReplyIP;
185
186 uchar *NetArpWaitPacketMAC;     /* MAC address of waiting packet's destination */
187 uchar *NetArpWaitTxPacket;      /* THE transmit packet */
188 uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
189 ulong NetArpWaitTimerStart;
190
191 int NetArpWaitTry;
192 int NetArpWaitTxPacketSize;
193
194 void ArpRequest(void){
195         int i;
196         volatile uchar *pkt;
197         ARP_t *arp;
198
199 #ifdef ET_DEBUG
200         printf("ARP broadcast %d\n", NetArpWaitTry);
201 #endif
202
203         pkt = NetTxPacket;
204         pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
205
206         arp = (ARP_t *)pkt;
207
208         arp->ar_hrd = htons(ARP_ETHER);
209         arp->ar_pro = htons(PROT_IP);
210         arp->ar_hln = 6;
211         arp->ar_pln = 4;
212         arp->ar_op  = htons(ARPOP_REQUEST);
213
214         memcpy(&arp->ar_data[0], NetOurEther, 6);                       /* source ET addr */
215         NetWriteIP((uchar *)&arp->ar_data[6], NetOurIP);        /* source IP addr */
216
217         for(i = 10; i < 16; ++i){
218                 arp->ar_data[i] = 0; /* dest ET addr = 0 */
219         }
220
221         if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)){
222                 if(NetOurGatewayIP == 0){
223                         puts("** Warning: gatewayip needed but not set\n");
224                         NetArpWaitReplyIP = NetArpWaitPacketIP;
225                 } else {
226                         NetArpWaitReplyIP = NetOurGatewayIP;
227                 }
228         } else {
229                 NetArpWaitReplyIP = NetArpWaitPacketIP;
230         }
231
232         NetWriteIP((uchar *)&arp->ar_data[16], NetArpWaitReplyIP);
233         (void)eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
234 }
235
236 void ArpTimeoutCheck(void){
237         ulong t;
238         bd_t *bd = gd->bd;
239
240         if(!NetArpWaitPacketIP){
241                 return;
242         }
243
244         t = get_timer(0);
245
246         /* check for arp timeout */
247         if((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ){
248                 NetArpWaitTry++;
249
250                 if(NetArpWaitTry >= ARP_TIMEOUT_COUNT){
251                         puts("## Error: ARP retry count exceeded, starting again\n");
252                         NetArpWaitTry = 0;
253                         NetStartAgain();
254                 } else {
255                         NetArpWaitTimerStart = t;
256                         ArpRequest();
257                 }
258         }
259 }
260
261 /**********************************************************************/
262 /*
263  *      Main network processing loop.
264  */
265 int NetLoop(proto_t protocol){
266         bd_t *bd = gd->bd;
267
268 #ifdef CONFIG_NET_MULTI
269         NetRestarted = 0;
270         NetDevExists = 0;
271 #endif
272
273         /* XXX problem with bss workaround */
274         NetArpWaitPacketMAC     = NULL;
275         NetArpWaitTxPacket      = NULL;
276         NetArpWaitPacketIP      = 0;
277         NetArpWaitReplyIP       = 0;
278         NetArpWaitTxPacket      = NULL;
279         NetTxPacket                     = NULL;
280
281         if(!NetTxPacket){
282                 int i;
283                 /*
284                  *      Setup packet buffers, aligned correctly.
285                  */
286                 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
287                 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
288
289                 for(i = 0; i < PKTBUFSRX; i++){
290                         NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
291                 }
292         }
293
294         if(!NetArpWaitTxPacket){
295                 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
296                 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
297                 NetArpWaitTxPacketSize = 0;
298         }
299
300         if(eth_is_on_demand_init() || protocol != NETCONS){
301                 eth_halt();
302 #ifdef CONFIG_NET_MULTI
303                 eth_set_current();
304 #endif
305                 if(!eth_init(bd)){
306                         eth_halt();
307                         return(-1);
308                 }
309         } else {
310                 eth_init_state_only(bd);
311         }
312
313         /* restart label */
314         restart:
315
316 #ifdef CONFIG_NET_MULTI
317         memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
318 #else
319         memcpy(NetOurEther, bd->bi_enetaddr, 6);
320 #endif
321
322         NetState = NETLOOP_CONTINUE;
323
324         /*
325          *      Start the ball rolling with the given start function.  From
326          *      here on, this code is a state machine driven by received
327          *      packets and timer events.
328          */
329
330         switch(protocol){
331 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
332                 case NFS:
333 #endif
334 #if (CONFIG_COMMANDS & CFG_CMD_PING)
335                 case PING:
336 #endif
337 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
338                 case SNTP:
339 #endif
340                 case NETCONS:
341                 case TFTP:
342                         NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
343
344                         NetOurGatewayIP         = getenv_IPaddr("gatewayip");
345                         NetOurSubnetMask        = getenv_IPaddr("netmask");
346                         NetOurVLAN                      = getenv_VLAN("vlan");
347                         NetOurNativeVLAN        = getenv_VLAN("nvlan");
348
349                         switch(protocol){
350 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
351                                 case NFS:
352 #endif
353                                 case NETCONS:
354                                 case TFTP:
355                                         NetServerIP = getenv_IPaddr("serverip");
356                                         break;
357 #if (CONFIG_COMMANDS & CFG_CMD_PING)
358                                 case PING:
359                                         /* nothing */
360                                         break;
361 #endif
362 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
363                                 case SNTP:
364                                         /* nothing */
365                                         break;
366 #endif
367                                 default:
368                                         break;
369                         }
370
371                         break;
372
373                 case BOOTP:
374                 case RARP:
375                         /*
376                          * initialize our IP addr to 0 in order to accept ANY
377                          * IP addr assigned to us by the BOOTP / RARP server
378                          */
379                         NetOurIP                        = 0;
380                         NetServerIP                     = getenv_IPaddr("serverip");
381                         NetOurVLAN                      = getenv_VLAN("vlan"); /* VLANs must be read */
382                         NetOurNativeVLAN        = getenv_VLAN("nvlan");
383
384                 case CDP:
385                         NetOurVLAN                      = getenv_VLAN("vlan"); /* VLANs must be read */
386                         NetOurNativeVLAN        = getenv_VLAN("nvlan");
387                         break;
388
389                 default:
390                         break;
391         }
392
393         switch(net_check_prereq(protocol)){
394                 case 1:
395                         /* network not configured */
396                         eth_halt();
397                         return(-1);
398
399 #ifdef CONFIG_NET_MULTI
400                 case 2:
401                         /* network device not configured */
402                         break;
403 #endif /* CONFIG_NET_MULTI */
404
405                 case 0:
406 #ifdef CONFIG_NET_MULTI
407                         NetDevExists = 1;
408 #endif
409                         switch(protocol){
410                                 case TFTP:
411                                         /* always use ARP to get server ethernet address */
412                                         TftpStart();
413                                         break;
414
415 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
416                                 case DHCP:
417                                         /* Start with a clean slate... */
418                                         BootpTry = 0;
419                                         NetOurIP = 0;
420                                         NetServerIP = getenv_IPaddr("serverip");
421                                         DhcpRequest(); /* Basically same as BOOTP */
422                                         break;
423
424 #endif /* CFG_CMD_DHCP */
425
426 #if (CONFIG_COMMANDS & CFG_CMD_PING)
427                                 case PING:
428                                         PingStart();
429                                         break;
430 #endif
431
432 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
433                                 case NFS:
434                                         NfsStart();
435                                         break;
436 #endif
437
438 #ifdef CONFIG_NETCONSOLE
439                                 case NETCONS:
440                                         NcStart();
441                                         break;
442 #endif
443
444 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
445                                 case SNTP:
446                                         SntpStart();
447                                         break;
448 #endif
449
450                                 default:
451                                         break;
452                         }
453
454                         NetBootFileXferSize = 0;
455                         break;
456         }
457
458         /*
459          *      Main packet reception loop.  Loop receiving packets until
460          *      someone sets `NetState' to a state that terminates.
461          */
462         for(;;){
463                 /*
464                  *      Check the ethernet for a new packet.  The ethernet
465                  *      receive routine will process it.
466                  */
467                 eth_rx();
468
469                 /*
470                  *      Abort if ctrl-c was pressed.
471                  */
472                 if(ctrlc()){
473                         eth_halt();
474
475                         /* Invalidate the last protocol */
476                         eth_set_last_protocol(BOOTP);
477
478                         puts("\nAbort\n");
479                         return(-1);
480                 }
481
482                 ArpTimeoutCheck();
483
484                 /*
485                  *      Check for a timeout, and run the timeout handler
486                  *      if we have one.
487                  */
488                 if(timeHandler && ((get_timer(0) - timeStart) > timeDelta)){
489                         thand_f *x;
490                         x = timeHandler;
491                         timeHandler = (thand_f *)0;
492                         (*x)();
493                 }
494
495                 switch(NetState){
496
497                         case NETLOOP_RESTART:
498 #ifdef CONFIG_NET_MULTI
499                                 NetRestarted = 1;
500 #endif
501                                 goto restart;
502
503                         case NETLOOP_SUCCESS:
504                                 if(NetBootFileXferSize > 0){
505                                         char buf[10];
506                                         printf("\nBytes transferred: %ld (0x%lx)\n", NetBootFileXferSize, NetBootFileXferSize);
507
508                                         sprintf(buf, "%lx", NetBootFileXferSize);
509                                         setenv("filesize", buf);
510
511                                         sprintf(buf, "%lX", (unsigned long)load_addr);
512                                         setenv("fileaddr", buf);
513                                 }
514
515                                 if(protocol != NETCONS){
516                                         eth_halt();
517                                 } else {
518                                         eth_halt_state_only();
519                                 }
520
521                                 eth_set_last_protocol(protocol);
522
523                                 return(NetBootFileXferSize);
524
525                         case NETLOOP_FAIL:
526                                 /* Invalidate the last protocol */
527                                 eth_set_last_protocol(BOOTP);
528                                 return(-1);
529                 }
530         }
531 }
532
533 /**********************************************************************/
534
535 static void startAgainTimeout(void){
536         NetState = NETLOOP_RESTART;
537 }
538
539 static void startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
540         /* Totally ignore the packet */
541 }
542
543 void NetStartAgain(void){
544         char *nretry;
545         int noretry = 0, once = 0;
546         bd_t *bd = gd->bd;
547
548         if((nretry = getenv("netretry")) != NULL){
549                 noretry = (strcmp(nretry, "no") == 0);
550                 once = (strcmp(nretry, "once") == 0);
551         }
552
553         if(noretry){
554                 eth_halt();
555                 NetState = NETLOOP_FAIL;
556                 return;
557         }
558
559 #ifndef CONFIG_NET_MULTI
560         NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
561         NetSetHandler(startAgainHandler);
562 #else   /* !CONFIG_NET_MULTI*/
563         eth_halt();
564         eth_try_another(!NetRestarted);
565         eth_init(gd->bd);
566
567         if(NetRestartWrap){
568                 NetRestartWrap = 0;
569                 if(NetDevExists && !once){
570                         NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
571                         NetSetHandler(startAgainHandler);
572                 } else {
573                         NetState = NETLOOP_FAIL;
574                 }
575         } else {
576                 NetState = NETLOOP_RESTART;
577         }
578 #endif  /* CONFIG_NET_MULTI */
579 }
580
581 /**********************************************************************/
582 /*
583  *      Miscelaneous bits.
584  */
585
586 void NetSetHandler(rxhand_f * f){
587         packetHandler = f;
588 }
589
590 void NetSetTimeout(ulong iv, thand_f * f){
591         if(iv == 0){
592                 timeHandler = (thand_f *)0;
593         } else {
594                 timeHandler = f;
595                 timeStart = get_timer(0);
596                 timeDelta = iv;
597         }
598 }
599
600 void NetSendPacket(volatile uchar * pkt, int len){
601         (void)eth_send(pkt, len);
602 }
603
604 int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len){
605         uchar *pkt;
606
607         /* convert to new style broadcast */
608         if(dest == 0){
609                 dest = 0xFFFFFFFF;
610         }
611
612         /* if broadcast, make the ether address a broadcast and don't do ARP */
613         if(dest == 0xFFFFFFFF){
614                 ether = NetBcastAddr;
615         }
616
617         /* if MAC address was not discovered yet, save the packet and do an ARP request */
618         if(memcmp(ether, NetEtherNullAddr, 6) == 0){
619
620 #ifdef ET_DEBUG
621                 printf("Sending ARP for %08lx\n", dest);
622 #endif
623                 NetArpWaitPacketIP = dest;
624                 NetArpWaitPacketMAC = ether;
625
626                 pkt = NetArpWaitTxPacket;
627                 pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP);
628
629                 NetSetIP(pkt, dest, dport, sport, len);
630                 memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
631
632                 /* size of the waiting packet */
633                 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
634
635                 /* and do the ARP request */
636                 NetArpWaitTry = 1;
637                 NetArpWaitTimerStart = get_timer(0);
638                 ArpRequest();
639
640                 return(1); /* waiting */
641         }
642
643 #ifdef ET_DEBUG
644         printf("Sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n", dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
645 #endif
646
647         pkt = (uchar *)NetTxPacket;
648         pkt += NetSetEther(pkt, ether, PROT_IP);
649         NetSetIP(pkt, dest, dport, sport, len);
650         (void)eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
651
652         return(0); /* transmitted */
653 }
654
655 #if (CONFIG_COMMANDS & CFG_CMD_PING)
656 static ushort PingSeqNo;
657
658 int PingSend(void){
659         static uchar mac[6];
660         volatile IP_t *ip;
661         volatile ushort *s;
662         uchar *pkt;
663
664         /* XXX always send arp request */
665
666         memcpy(mac, NetEtherNullAddr, 6);
667
668 #ifdef ET_DEBUG
669         printf("Sending ARP for %08lx\n", NetPingIP);
670 #endif
671
672         NetArpWaitPacketIP = NetPingIP;
673         NetArpWaitPacketMAC = mac;
674
675         pkt = NetArpWaitTxPacket;
676         pkt += NetSetEther(pkt, mac, PROT_IP);
677
678         ip = (volatile IP_t *)pkt;
679
680         /*
681          *      Construct an IP and ICMP header.  (need to set no fragment bit - XXX)
682          */
683         ip->ip_hl_v     = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
684         ip->ip_tos      = 0;
685         ip->ip_len      = htons(IP_HDR_SIZE_NO_UDP + 8);
686         ip->ip_id       = htons(NetIPID++);
687         ip->ip_off      = htons(0x4000); /* No fragmentation */
688         ip->ip_ttl      = 255;
689         ip->ip_p        = 0x01; /* ICMP */
690         ip->ip_sum      = 0;
691
692         NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
693         NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */
694
695         ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
696
697         s = &ip->udp_src; /* XXX ICMP starts here */
698
699         s[0] = htons(0x0800); /* echo-request, code */
700         s[1] = 0; /* checksum */
701         s[2] = 0; /* identifier */
702         s[3] = htons(PingSeqNo++); /* sequence number */
703         s[1] = ~NetCksum((uchar *)s, 8/2);
704
705         /* size of the waiting packet */
706         NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
707
708         /* and do the ARP request */
709         NetArpWaitTry = 1;
710         NetArpWaitTimerStart = get_timer(0);
711         ArpRequest();
712
713         return(1); /* waiting */
714 }
715
716 static void PingTimeout(void){
717         eth_halt();
718         NetState = NETLOOP_FAIL; /* we did not get the reply */
719 }
720
721 static void PingHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
722         IPaddr_t tmp;
723         volatile IP_t *ip = (volatile IP_t *)pkt;
724
725         tmp = NetReadIP((void *)&ip->ip_src);
726
727         if(tmp != NetPingIP){
728                 return;
729         }
730
731         NetState = NETLOOP_SUCCESS;
732 }
733
734 static void PingStart(void){
735         bd_t *bd = gd->bd;
736 #if defined(CONFIG_NET_MULTI)
737         printf("Using %s device\n", eth_get_name());
738 #endif  /* CONFIG_NET_MULTI */
739
740         NetSetTimeout(10 * CFG_HZ, PingTimeout);
741         NetSetHandler(PingHandler);
742
743         PingSend();
744 }
745 #endif  /* CFG_CMD_PING */
746
747 void NetReceive(volatile uchar * inpkt, int len){
748         Ethernet_t *et;
749         IP_t *ip;
750         ARP_t *arp;
751         IPaddr_t tmp;
752         int x;
753         uchar *pkt;
754         ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
755
756 #ifdef ET_DEBUG
757         printf("Packet received\n");
758 #endif
759
760         if(webfailsafe_is_running){
761                 NetReceiveHttpd(inpkt, len);
762                 return;
763         }
764
765         NetRxPkt = inpkt;
766         NetRxPktLen = len;
767         et = (Ethernet_t *)inpkt;
768
769         /* too small packet? */
770         if(len < ETHER_HDR_SIZE){
771                 return;
772         }
773
774         myvlanid = ntohs(NetOurVLAN);
775
776         if(myvlanid == (ushort)-1){
777                 myvlanid = VLAN_NONE;
778         }
779
780         mynvlanid = ntohs(NetOurNativeVLAN);
781
782         if(mynvlanid == (ushort)-1){
783                 mynvlanid = VLAN_NONE;
784         }
785
786         x = ntohs(et->et_protlen);
787
788 #ifdef ET_DEBUG
789         printf("Packet received\n");
790 #endif
791
792         if(x < 1514){
793                 /*
794                  *      Got a 802 packet.  Check the other protocol field.
795                  */
796                 x = ntohs(et->et_prot);
797
798                 ip = (IP_t *)(inpkt + E802_HDR_SIZE);
799                 len -= E802_HDR_SIZE;
800
801         } else if(x != PROT_VLAN){ /* normal packet */
802                 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
803                 len -= ETHER_HDR_SIZE;
804
805         } else { /* VLAN packet */
806                 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
807
808 #ifdef ET_DEBUG
809                 printf("VLAN packet received\n");
810 #endif
811                 /* too small packet? */
812                 if(len < VLAN_ETHER_HDR_SIZE){
813                         return;
814                 }
815
816                 /* if no VLAN active */
817                 if((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE){
818                         return;
819                 }
820
821                 cti = ntohs(vet->vet_tag);
822                 vlanid = cti & VLAN_IDMASK;
823                 x = ntohs(vet->vet_type);
824
825                 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
826                 len -= VLAN_ETHER_HDR_SIZE;
827         }
828
829 #ifdef ET_DEBUG
830         printf("Receive from protocol 0x%x\n", x);
831 #endif
832
833         if((myvlanid & VLAN_IDMASK) != VLAN_NONE){
834                 if(vlanid == VLAN_NONE){
835                         vlanid = (mynvlanid & VLAN_IDMASK);
836                 }
837                 /* not matched? */
838                 if(vlanid != (myvlanid & VLAN_IDMASK)){
839                         return;
840                 }
841         }
842
843         switch(x){
844
845                 case PROT_ARP:
846                         /*
847                          * We have to deal with two types of ARP packets:
848                          * - REQUEST packets will be answered by sending  our
849                          *   IP address - if we know it.
850                          * - REPLY packates are expected only after we asked
851                          *   for the TFTP server's or the gateway's ethernet
852                          *   address; so if we receive such a packet, we set
853                          *   the server ethernet address
854                          */
855 #ifdef ET_DEBUG
856                         puts("Got ARP\n");
857 #endif
858                         arp = (ARP_t *)ip;
859
860                         if(len < ARP_HDR_SIZE){
861                                 printf("## Error: bad length %d < %d\n", len, ARP_HDR_SIZE);
862                                 return;
863                         }
864
865                         if(ntohs(arp->ar_hrd) != ARP_ETHER){
866                                 return;
867                         }
868
869                         if(ntohs(arp->ar_pro) != PROT_IP){
870                                 return;
871                         }
872
873                         if(arp->ar_hln != 6){
874                                 return;
875                         }
876
877                         if(arp->ar_pln != 4){
878                                 return;
879                         }
880
881                         if(NetOurIP == 0){
882                                 return;
883                         }
884
885                         if(NetReadIP(&arp->ar_data[16]) != NetOurIP){
886                                 return;
887                         }
888
889                         switch(ntohs(arp->ar_op)){
890                                 case ARPOP_REQUEST: /* reply with our IP address        */
891 #ifdef ET_DEBUG
892                                         puts("Got ARP REQUEST, return our IP\n");
893 #endif
894                                         pkt = (uchar *)et;
895                                         pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
896                                         arp->ar_op = htons(ARPOP_REPLY);
897                                         memcpy(&arp->ar_data[10], &arp->ar_data[0], 6);
898                                         NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
899                                         memcpy(&arp->ar_data[0], NetOurEther, 6);
900                                         NetCopyIP(&arp->ar_data[6], &NetOurIP);
901                                         (void)eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
902
903                                         return;
904
905                                 case ARPOP_REPLY: /* arp reply */
906                                         /* are we waiting for a reply */
907                                         if(!NetArpWaitPacketIP || !NetArpWaitPacketMAC){
908                                                 break;
909                                         }
910 #ifdef ET_DEBUG
911                                         printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n", arp->ar_data[0], arp->ar_data[1], arp->ar_data[2], arp->ar_data[3], arp->ar_data[4], arp->ar_data[5]);
912 #endif
913
914                                         tmp = NetReadIP(&arp->ar_data[6]);
915
916                                         /* matched waiting packet's address */
917                                         if(tmp == NetArpWaitReplyIP){
918 #ifdef ET_DEBUG
919                                                 puts("Got it\n");
920 #endif
921                                                 /* save address for later use */
922                                                 memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
923
924 #ifdef CONFIG_NETCONSOLE
925                                                 (*packetHandler)(0,0,0,0);
926 #endif
927                                                 /* modify header, and transmit it */
928                                                 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
929                                                 (void)eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
930
931                                                 /* no arp request pending now */
932                                                 NetArpWaitPacketIP = 0;
933                                                 NetArpWaitTxPacketSize = 0;
934                                                 NetArpWaitPacketMAC = NULL;
935
936                                         }
937
938                                         return;
939                                 default:
940 #ifdef ET_DEBUG
941                                         printf("## Error: unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
942 #endif
943                                         return;
944                         }
945                         break;
946
947                 case PROT_RARP:
948 #ifdef ET_DEBUG
949                         puts("Got RARP\n");
950 #endif
951                         arp = (ARP_t *)ip;
952                         if(len < ARP_HDR_SIZE){
953                                 printf("## Error: bad length %d < %d\n", len, ARP_HDR_SIZE);
954                                 return;
955                         }
956
957                         if((ntohs(arp->ar_op) != RARPOP_REPLY) || (ntohs(arp->ar_hrd) != ARP_ETHER) || (ntohs(arp->ar_pro) != PROT_IP) || (arp->ar_hln != 6) || (arp->ar_pln != 4)){
958                                 puts("## Error: invalid RARP header\n");
959                         } else {
960                                 NetCopyIP(&NetOurIP, &arp->ar_data[16]);
961                                 if(NetServerIP == 0){
962                                         NetCopyIP(&NetServerIP, &arp->ar_data[6]);
963                                 }
964                                 memcpy(NetServerEther, &arp->ar_data[0], 6);
965                                 (*packetHandler)(0, 0, 0, 0);
966                         }
967
968                         break;
969
970                 case PROT_IP:
971 #ifdef ET_DEBUG
972                         puts("Got IP\n");
973 #endif
974                         if(len < IP_HDR_SIZE){
975                                 debug("## Error: len bad %d < %d\n", len, IP_HDR_SIZE);
976                                 return;
977                         }
978
979                         if(len < ntohs(ip->ip_len)){
980                                 printf("## Error: len bad %d < %d\n", len, ntohs(ip->ip_len));
981                                 return;
982                         }
983
984                         len = ntohs(ip->ip_len);
985 #ifdef ET_DEBUG
986                         printf("Len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
987 #endif
988                         if((ip->ip_hl_v & 0xf0) != 0x40){
989                                 return;
990                         }
991
992                         if(ip->ip_off & htons(0x1fff)){ /* Can't deal w/ fragments */
993                                 return;
994                         }
995
996                         if(!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)){
997 #ifdef ET_DEBUG
998                                 puts("\n## Error: checksum bad\n");
999 #endif
1000                                 return;
1001                         }
1002
1003                         tmp = NetReadIP(&ip->ip_dst);
1004
1005                         if(NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF){
1006                                 return;
1007                         }
1008                         /*
1009                          * watch for ICMP host redirects
1010                          *
1011                          * There is no real handler code (yet). We just watch
1012                          * for ICMP host redirect messages. In case anybody
1013                          * sees these messages: please contact me
1014                          * (wd@denx.de), or - even better - send me the
1015                          * necessary fixes :-)
1016                          *
1017                          * Note: in all cases where I have seen this so far
1018                          * it was a problem with the router configuration,
1019                          * for instance when a router was configured in the
1020                          * BOOTP reply, but the TFTP server was on the same
1021                          * subnet. So this is probably a warning that your
1022                          * configuration might be wrong. But I'm not really
1023                          * sure if there aren't any other situations.
1024                          */
1025                         if(ip->ip_p == IPPROTO_ICMP){
1026                                 ICMP_t *icmph = (ICMP_t *) & (ip->udp_src);
1027
1028                                 switch(icmph->type){
1029                                         case ICMP_REDIRECT:
1030                                                 if(icmph->code != ICMP_REDIR_HOST){
1031                                                         return;
1032                                                 }
1033
1034                                                 puts(" ICMP Host Redirect to ");
1035                                                 print_IPaddr(icmph->un.gateway);
1036                                                 putc(' ');
1037
1038                                                 return;
1039 #if (CONFIG_COMMANDS & CFG_CMD_PING)
1040                                         case ICMP_ECHO_REPLY:
1041                                                 /*
1042                                                  *      IP header OK.  Pass the packet to the current handler.
1043                                                  */
1044                                                 /* XXX point to ip packet */
1045                                                 (*packetHandler)((uchar *)ip, 0, 0, 0);
1046                                                 return;
1047 #endif
1048                                         default:
1049                                                 return;
1050                                 }
1051                         } else if(ip->ip_p != IPPROTO_UDP){ /* Only UDP packets */
1052                                 return;
1053                         }
1054
1055 #ifdef CONFIG_UDP_CHECKSUM
1056                         if(ip->udp_xsum != 0){
1057                                 ulong xsum;
1058                                 ushort *sumptr;
1059                                 ushort sumlen;
1060
1061                                 xsum = ip->ip_p;
1062                                 xsum += (ntohs(ip->udp_len));
1063                                 xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1064                                 xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
1065                                 xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1066                                 xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
1067
1068                                 sumlen = ntohs(ip->udp_len);
1069                                 sumptr = (ushort *)&(ip->udp_src);
1070
1071                                 while(sumlen > 1){
1072                                         ushort sumdata;
1073
1074                                         sumdata = *sumptr++;
1075                                         xsum += ntohs(sumdata);
1076                                         sumlen -= 2;
1077                                 }
1078
1079                                 if(sumlen > 0){
1080                                         ushort sumdata;
1081
1082                                         sumdata = *(unsigned char *)sumptr;
1083                                         sumdata = (sumdata << 8) & 0xff00;
1084                                         xsum += sumdata;
1085                                 }
1086
1087                                 while((xsum >> 16) != 0){
1088                                         xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
1089                                 }
1090
1091                                 if((xsum != 0x00000000) && (xsum != 0x0000ffff)){
1092                                         printf("## Error: UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum));
1093                                         return;
1094                                 }
1095                         }
1096 #endif
1097
1098 #ifdef CONFIG_NETCONSOLE
1099                         nc_input_packet((uchar *)ip +IP_HDR_SIZE, ntohs(ip->udp_dst), ntohs(ip->udp_src), ntohs(ip->udp_len) - 8);
1100 #endif
1101                         /*
1102                          *      IP header OK.  Pass the packet to the current handler.
1103                          */
1104                         (*packetHandler)((uchar *)ip + IP_HDR_SIZE, ntohs(ip->udp_dst), ntohs(ip->udp_src), ntohs(ip->udp_len) - 8);
1105                         break;
1106         }
1107 }
1108
1109 /**********************************************************************/
1110
1111 static int net_check_prereq(proto_t protocol){
1112         switch(protocol){
1113                 /* Fall through */
1114 #if (CONFIG_COMMANDS & CFG_CMD_PING)
1115                 case PING:
1116                         if(NetPingIP == 0){
1117                                 puts("## Error: ping address not given\n");
1118                                 return(1);
1119                         }
1120                         goto common;
1121 #endif
1122 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
1123                 case SNTP:
1124                         if(NetNtpServerIP == 0){
1125                                 puts("## Error: NTP server address not given\n");
1126                                 return(1);
1127                         }
1128                         goto common;
1129 #endif
1130 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
1131                 case NFS:
1132 #endif
1133                 case NETCONS:
1134                 case TFTP:
1135                         if(NetServerIP == 0){
1136                                 puts("## Error: serverip not set\n");
1137                                 return(1);
1138                         }
1139 #if (CONFIG_COMMANDS & (CFG_CMD_PING | CFG_CMD_SNTP))
1140                         common:
1141 #endif
1142                         if(NetOurIP == 0){
1143                                 puts("## Error: ipaddr not set\n");
1144                                 return(1);
1145                         }
1146                         /* Fall through */
1147
1148                 case DHCP:
1149                 case RARP:
1150                 case BOOTP:
1151                 case CDP:
1152                         if(memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0){
1153 #ifdef CONFIG_NET_MULTI
1154                                 extern int eth_get_dev_index(void);
1155                                 int num = eth_get_dev_index();
1156
1157                                 switch(num){
1158                                         case -1:
1159                                                 puts("## Error: no ethernet found\n");
1160                                                 return(1);
1161                                         case 0:
1162                                                 puts("## Error: ethaddr not set\n");
1163                                                 break;
1164                                         default:
1165                                                 printf("## Error: eth%daddr not set\n", num);
1166                                                 break;
1167                                 }
1168
1169                                 NetStartAgain();
1170                                 return(2);
1171 #else
1172                                 puts("## Error: ethaddr not set\n");
1173                                 return(1);
1174 #endif
1175                         }
1176                         /* Fall through */
1177                 default:
1178                         return(0);
1179         }
1180
1181         return(0); /* OK */
1182 }
1183 /**********************************************************************/
1184
1185 int NetCksumOk(uchar * ptr, int len){
1186         return(!((NetCksum(ptr, len) + 1) & 0xfffe));
1187 }
1188
1189 unsigned NetCksum(uchar * ptr, int len){
1190         ulong xsum;
1191         ushort *p = (ushort *)ptr;
1192
1193         xsum = 0;
1194
1195         while(len-- > 0){
1196                 xsum += *p++;
1197         }
1198
1199         xsum = (xsum & 0xffff) + (xsum >> 16);
1200         xsum = (xsum & 0xffff) + (xsum >> 16);
1201
1202         return(xsum & 0xffff);
1203 }
1204
1205 int NetEthHdrSize(void){
1206         ushort myvlanid;
1207
1208         myvlanid = ntohs(NetOurVLAN);
1209
1210         if(myvlanid == (ushort) -1){
1211                 myvlanid = VLAN_NONE;
1212         }
1213
1214         return(((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE);
1215 }
1216
1217 int NetSetEther(volatile uchar * xet, uchar * addr, uint prot){
1218         Ethernet_t *et = (Ethernet_t *)xet;
1219         ushort myvlanid;
1220
1221         myvlanid = ntohs(NetOurVLAN);
1222
1223         if(myvlanid == (ushort) -1){
1224                 myvlanid = VLAN_NONE;
1225         }
1226
1227         memcpy(et->et_dest, addr, 6);
1228         memcpy(et->et_src, NetOurEther, 6);
1229
1230         if((myvlanid & VLAN_IDMASK) == VLAN_NONE){
1231                 et->et_protlen = htons(prot);
1232
1233                 return(ETHER_HDR_SIZE);
1234         } else {
1235                 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
1236
1237                 vet->vet_vlan_type = htons(PROT_VLAN);
1238                 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1239                 vet->vet_type = htons(prot);
1240                 return(VLAN_ETHER_HDR_SIZE);
1241         }
1242 }
1243
1244 void NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len){
1245         volatile IP_t *ip = (IP_t *)xip;
1246
1247         /*
1248          *      If the data is an odd number of bytes, zero the
1249          *      byte after the last byte so that the checksum
1250          *      will work.
1251          */
1252         if(len & 1){
1253                 xip[IP_HDR_SIZE + len] = 0;
1254         }
1255
1256         /*
1257          *      Construct an IP and UDP header.
1258          *      (need to set no fragment bit - XXX)
1259          */
1260         ip->ip_hl_v     = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
1261         ip->ip_tos      = 0;
1262         ip->ip_len      = htons(IP_HDR_SIZE + len);
1263         ip->ip_id       = htons(NetIPID++);
1264         ip->ip_off      = htons(0x4000); /* No fragmentation */
1265         ip->ip_ttl      = 255;
1266         ip->ip_p        = 17; /* UDP */
1267         ip->ip_sum      = 0;
1268
1269         NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1270         NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
1271
1272         ip->udp_src  = htons(sport);
1273         ip->udp_dst  = htons(dport);
1274         ip->udp_len  = htons(8 + len);
1275         ip->udp_xsum = 0;
1276         ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1277 }
1278
1279 void copy_filename(char *dst, char *src, int size){
1280         if(*src && (*src == '"')){
1281                 ++src;
1282                 --size;
1283         }
1284
1285         while((--size > 0) && *src && (*src != '"')){
1286                 *dst++ = *src++;
1287         }
1288         *dst = '\0';
1289 }
1290
1291 #endif /* CFG_CMD_NET */
1292
1293 void ip_to_string(IPaddr_t x, char *s){
1294         x = ntohl(x);
1295         sprintf(s, "%d.%d.%d.%d", (int)((x >> 24) & 0xff), (int)((x >> 16) & 0xff), (int)((x >> 8) & 0xff), (int)((x >> 0) & 0xff));
1296 }
1297
1298 IPaddr_t string_to_ip(char *s){
1299         IPaddr_t addr;
1300         char *e;
1301         int i;
1302
1303         if(s == NULL){
1304                 return(0);
1305         }
1306
1307         for(addr = 0, i = 0; i < 4; ++i){
1308                 ulong val = s ? simple_strtoul(s, &e, 10) : 0;
1309                 addr <<= 8;
1310                 addr |= (val & 0xFF);
1311                 if(s){
1312                         s = (*e) ? e + 1 : e;
1313                 }
1314         }
1315
1316         return(htonl(addr));
1317 }
1318
1319 void VLAN_to_string(ushort x, char *s){
1320         x = ntohs(x);
1321
1322         if(x == (ushort) -1){
1323                 x = VLAN_NONE;
1324         }
1325
1326         if(x == VLAN_NONE){
1327                 strcpy(s, "none");
1328         } else {
1329                 sprintf(s, "%d", x & VLAN_IDMASK);
1330         }
1331 }
1332
1333 ushort string_to_VLAN(char *s){
1334         ushort id;
1335
1336         if(s == NULL){
1337                 return(htons(VLAN_NONE));
1338         }
1339
1340         if(*s < '0' || *s > '9'){
1341                 id = VLAN_NONE;
1342         } else {
1343                 id = (ushort) simple_strtoul(s, NULL, 10);
1344         }
1345
1346         return(htons(id));
1347 }
1348
1349 void print_IPaddr(IPaddr_t x){
1350         char tmp[16];
1351
1352         ip_to_string(x, tmp);
1353
1354         puts(tmp);
1355 }
1356
1357 IPaddr_t getenv_IPaddr(char *var){
1358         return(string_to_ip(getenv(var)));
1359 }
1360
1361 ushort getenv_VLAN(char *var){
1362         return(string_to_VLAN(getenv(var)));
1363 }
1364
1365
1366 /**********************************************************************************
1367  * HTTPD section
1368  */
1369
1370 #define BUF     ((struct uip_eth_hdr *)&uip_buf[0])
1371
1372 void NetSendHttpd(void){
1373         volatile uchar *tmpbuf = NetTxPacket;
1374         int i;
1375
1376         for(i = 0; i < 40 + UIP_LLH_LEN; i++){
1377                 tmpbuf[i] = uip_buf[i];
1378         }
1379
1380         for(; i < uip_len; i++){
1381                 tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN];
1382         }
1383
1384         eth_send(NetTxPacket, uip_len);
1385 }
1386
1387 void NetReceiveHttpd(volatile uchar * inpkt, int len){
1388         memcpy(uip_buf, (const void *)inpkt, len);
1389         uip_len = len;
1390
1391         if(BUF->type == htons(UIP_ETHTYPE_IP)){
1392                 uip_arp_ipin();
1393                 uip_input();
1394
1395                 if(uip_len > 0){
1396                         uip_arp_out();
1397                         NetSendHttpd();
1398                 }
1399         } else if(BUF->type == htons(UIP_ETHTYPE_ARP)){
1400                 uip_arp_arpin();
1401
1402                 if(uip_len > 0){
1403                         NetSendHttpd();
1404                 }
1405         }
1406 }
1407
1408 /* *************************************
1409  *
1410  * HTTP web server for web failsafe mode
1411  *
1412  ***************************************/
1413 int NetLoopHttpd(void){
1414         bd_t *bd = gd->bd;
1415         unsigned short int ip[2];
1416         unsigned char ethinit_attempt = 0;
1417         struct uip_eth_addr eaddr;
1418
1419 #ifdef CONFIG_NET_MULTI
1420         NetRestarted = 0;
1421         NetDevExists = 0;
1422 #endif
1423
1424         /* XXX problem with bss workaround */
1425         NetArpWaitPacketMAC     = NULL;
1426         NetArpWaitTxPacket      = NULL;
1427         NetArpWaitPacketIP      = 0;
1428         NetArpWaitReplyIP       = 0;
1429         NetArpWaitTxPacket      = NULL;
1430         NetTxPacket                     = NULL;
1431
1432         if(!NetTxPacket){
1433                 int i;
1434                 // Setup packet buffers, aligned correctly.
1435                 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
1436                 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
1437
1438                 for(i = 0; i < PKTBUFSRX; i++){
1439                         NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
1440                 }
1441         }
1442
1443         if(!NetArpWaitTxPacket){
1444                 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
1445                 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
1446                 NetArpWaitTxPacketSize = 0;
1447         }
1448
1449         // restart label
1450         restart:
1451
1452         eth_halt();
1453
1454 #ifdef CONFIG_NET_MULTI
1455         eth_set_current();
1456 #endif
1457
1458         while(ethinit_attempt < 10){
1459                 if(eth_init(bd)){
1460                         ethinit_attempt = 0;
1461                         break;
1462                 } else {
1463                         ethinit_attempt++;
1464                         eth_halt();
1465                         milisecdelay(1000);
1466                 }
1467         }
1468
1469         if(ethinit_attempt > 0){
1470                 eth_halt();
1471                 printf("## Error: couldn't initialize eth (cable disconnected?)!\n\n");
1472                 return(-1);
1473         }
1474
1475         // get MAC address
1476 #ifdef CONFIG_NET_MULTI
1477         memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
1478 #else
1479         eth_getenv_enetaddr("ethaddr", NetOurEther);
1480 #endif
1481
1482         eaddr.addr[0] = NetOurEther[0];
1483         eaddr.addr[1] = NetOurEther[1];
1484         eaddr.addr[2] = NetOurEther[2];
1485         eaddr.addr[3] = NetOurEther[3];
1486         eaddr.addr[4] = NetOurEther[4];
1487         eaddr.addr[5] = NetOurEther[5];
1488
1489         // set MAC address
1490         uip_setethaddr(eaddr);
1491
1492         // set ip and other addresses
1493         // TODO: do we need this with uIP stack?
1494         NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
1495
1496         NetOurGatewayIP         = getenv_IPaddr("gatewayip");
1497         NetOurSubnetMask        = getenv_IPaddr("netmask");
1498         NetOurVLAN                      = getenv_VLAN("vlan");
1499         NetOurNativeVLAN        = getenv_VLAN("nvlan");
1500
1501         // start server...
1502         printf("HTTP server is starting at IP: %ld.%ld.%ld.%ld\n", (bd->bi_ip_addr & 0xff000000) >> 24, (bd->bi_ip_addr & 0x00ff0000) >> 16, (bd->bi_ip_addr & 0x0000ff00) >> 8, (bd->bi_ip_addr & 0x000000ff));
1503
1504         HttpdStart();
1505
1506         // set local host ip address
1507         ip[0] = ((bd->bi_ip_addr & 0xFFFF0000) >> 16);
1508         ip[1] = (bd->bi_ip_addr & 0x0000FFFF);
1509
1510         uip_sethostaddr(ip);
1511
1512         // set network mask (255.255.255.0 -> local network)
1513         ip[0] = ((0xFFFFFF00 & 0xFFFF0000) >> 16);
1514         ip[1] = (0xFFFFFF00 & 0x0000FFFF);
1515
1516         uip_setnetmask(ip);
1517
1518         // should we also set default router ip address?
1519         //uip_setdraddr();
1520
1521         // show current progress of the process
1522         do_http_progress(WEBFAILSAFE_PROGRESS_START);
1523
1524         webfailsafe_is_running = 1;
1525
1526         // infinite loop
1527         for(;;){
1528
1529                 /*
1530                  *      Check the ethernet for a new packet.
1531                  *      The ethernet receive routine will process it.
1532                  */
1533                 if(eth_rx() > 0){
1534                         HttpdHandler();
1535                 }
1536
1537                 // if CTRL+C was pressed -> return!
1538                 if(ctrlc()){
1539                         eth_halt();
1540
1541                         // reset global variables to default state
1542                         webfailsafe_is_running = 0;
1543                         webfailsafe_ready_for_upgrade = 0;
1544                         webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
1545
1546                         /* Invalidate the last protocol */
1547                         eth_set_last_protocol(BOOTP);
1548
1549                         printf("\nWeb failsafe mode aborted!\n\n");
1550                         return(-1);
1551                 }
1552
1553                 // until upload is not completed, get back to the start of the loop
1554                 if(!webfailsafe_ready_for_upgrade){
1555                         continue;
1556                 }
1557
1558                 // stop eth interface
1559                 eth_halt();
1560
1561                 // show progress
1562                 do_http_progress(WEBFAILSAFE_PROGRESS_UPLOAD_READY);
1563
1564                 // try to make upgrade!
1565                 if(do_http_upgrade(NetBootFileXferSize, webfailsafe_upgrade_type) >= 0){
1566                         milisecdelay(500);
1567
1568                         do_http_progress(WEBFAILSAFE_PROGRESS_UPGRADE_READY);
1569
1570                         milisecdelay(500);
1571
1572                         /* reset the board */
1573                         do_reset(NULL, 0, 0, NULL);
1574                 }
1575                 break;
1576         }
1577
1578         // reset global variables to default state
1579         webfailsafe_is_running = 0;
1580         webfailsafe_ready_for_upgrade = 0;
1581         webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
1582
1583         NetBootFileXferSize = 0;
1584
1585         do_http_progress(WEBFAILSAFE_PROGRESS_UPGRADE_FAILED);
1586
1587         // go to restart
1588         goto restart;
1589
1590         return(-1);
1591 }