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