Exemple #1
0
/*
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 */
static void BootpCopyNetParams(Bootp_t *bp){
	IPaddr_t tmp_ip;

	NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
	NetCopyIP(&tmp_ip, &bp->bp_siaddr);

	if(tmp_ip != 0){
		NetCopyIP(&NetServerIP, &bp->bp_siaddr);
	}

	memcpy(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src, 6);

	if(strlen(bp->bp_file) > 0){
		copy_filename(BootFile, bp->bp_file, sizeof(BootFile));
	}

#ifdef DEBUG
	printf("Bootfile: %s\n", BootFile);
#endif

	/*
	 * Propagate to environment:
	 * don't delete exising entry when BOOTP / DHCP reply does
	 * not contain a new value
	 */
	if(*BootFile){
		setenv("bootfile", BootFile);
	}
}
void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
{
	struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src;
	IPaddr_t src_ip;
	int eth_hdr_size;

	switch (icmph->type) {
	case ICMP_ECHO_REPLY:
		src_ip = NetReadIP((void *)&ip->ip_src);
		if (src_ip == NetPingIP)
			net_set_state(NETLOOP_SUCCESS);
		return;
	case ICMP_ECHO_REQUEST:
		eth_hdr_size = net_update_ether(et, et->et_src, PROT_IP);

		debug_cond(DEBUG_DEV_PKT, "Got ICMP ECHO REQUEST, return "
			"%d bytes\n", eth_hdr_size + len);

		ip->ip_sum = 0;
		ip->ip_off = 0;
		NetCopyIP((void *)&ip->ip_dst, &ip->ip_src);
		NetCopyIP((void *)&ip->ip_src, &NetOurIP);
		ip->ip_sum = ~NetCksum((uchar *)ip,
				       IP_HDR_SIZE >> 1);

		icmph->type = ICMP_ECHO_REPLY;
		icmph->checksum = 0;
		icmph->checksum = ~NetCksum((uchar *)icmph,
			(len - IP_HDR_SIZE) >> 1);
		NetSendPacket((uchar *)et, eth_hdr_size + len);
		return;
/*	default:
		return;*/
	}
}
Exemple #3
0
/*------------------------------------------------------------------------
 * This sends an TCP segment to the ip layer.  The segment is 
 * is normally either a web page or a graphic.
 * See "TCP/IP Illustrated, Volume 1" Sect 17.3
 *------------------------------------------------------------------------
 */
void http_send(uchar *outbuf, uint len, uchar nr)
{
	TCP_t 	*tcp;
	IP_t 	*ip;
	uint 	sum;
	ushort 	result;
	uint	dest_ip;
	  
	/* Fill in TCP segment header */
	tcp = (TCP_t *)(outbuf + 34);
	ip = (IP_t *)(outbuf + 14);
	
	tcp->source_port = htons(HTTP_PORT);
	tcp->dest_port = htons(conxn[nr].port);
	tcp->sequence = htonl(conxn[nr].my_sequence);
	tcp->ack_number = htonl(conxn[nr].his_sequence);
	
	/* Header is always 20 bytes long */
	tcp->flags = htons(0x5000 | FLG_ACK | FLG_PSH);
	tcp->window = htons(WINDOW_SIZE);
	tcp->checksum = 0;
	tcp->urgent_ptr = 0;

	/* 
	 * Compute checksum including 12 bytes of pseudoheader
	 * Must pre-fill 2 items in ip header to do this
	 */
	dest_ip = htonl(conxn[nr].ipaddr);
	NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* in network byte order */
	NetCopyIP((void*)&ip->ip_dst, &dest_ip);
	
	/* Sum source_ipaddr, dest_ipaddr, and entire TCP message */
	sum = (uint)cksum(outbuf + 26, 8 + len);
			
	/*
	 * Add in the rest of pseudoheader which is
	 * protocol id and TCP segment length
	 */
	sum += (uint)htons(0x0006);
	sum += (uint)htons(len);
	
	/* In case there was a carry, add it back around */
	result = (uint)(sum + (sum >> 16));
	tcp->checksum = ~result;

	memcpy(outbuf, conxn[nr].mac, 6);
   
	if (http_debug == DEBUG)
		printf("%s : Sending msg to IP layer\n", __func__);
	NetSendIPPacket(outbuf, dest_ip, TCP_TYPE, len);

	/* (Re)start TCP retransmit timer */
	conxn[nr].timer = TCP_TIMEOUT;
}
Exemple #4
0
/*
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 */
static void BootpCopyNetParams(Bootp_t *bp)
{
	IPaddr_t tmp_ip;

	NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
#if !defined(CONFIG_BOOTP_SERVERIP)
	NetCopyIP(&tmp_ip, &bp->bp_siaddr);
	if (tmp_ip != 0)
		NetCopyIP(&NetServerIP, &bp->bp_siaddr);
	memcpy (NetServerEther, ((Ethernet_t *)NetRxPacket)->et_src, 6);
#endif
}
static void keymile_hdlc_enet_doarp(volatile void *packet, int len)
{
	ARP_t *arp;
	IPaddr_t src_ip; /* U-Boot's IP */
	IPaddr_t dest_ip; /* the mgcoge's IP */
	unsigned char *packet_copy = malloc(len);

	/*
	 * Handling an ARP request means that a new transfer has started.
	 * Update our cached parameters now.
	 */
	initCachedNumbers(0); /* may reinit port numbers */

	/* special handling required for ARP */
	arp = (ARP_t *)(packet + ETHER_HDR_SIZE);
	/*
	 *	XXXX
	 * This is pretty dirty!  NetReceive only uses
	 * a few fields when handling an ARP reply, so
	 * we only modify those here.  This could
	 * result in catastrophic failure at a later
	 * time if the handler is modified!
	 */
	arp->ar_op = htons(ARPOP_REPLY);
	/* save his/our IP */
	src_ip = NetReadIP(&arp->ar_data[6]);
	dest_ip = NetReadIP(&arp->ar_data[16]);
	/* copy target IP to source IP */
	NetCopyIP(&arp->ar_data[6], &dest_ip);
	/* copy our IP to the right place */
	NetCopyIP(&arp->ar_data[16], &src_ip);
	/* always use 0x7f as the MAC for the coge */
	arp->ar_data[0] = HDLC_UACUA;
	/*
	 * copy the packet
	 * if NetReceive wants to write to stdout, it may overwrite packet
	 * especially if stdout is set to nc!
	 *
	 * However, if the malloc() above fails then we can still try the
	 * original packet, rather than causing the transfer to fail.
	 */
	if (packet_copy != NULL) {
		memcpy(packet_copy, (char *)packet, len);
		NetReceive(packet_copy, len);
		free(packet_copy);
	} else
		NetReceive(packet, len);
}
Exemple #6
0
/*
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 */
static void BootpCopyNetParams(Bootp_t *bp)
{
	IPaddr_t tmp_ip;

	NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
#if !defined(CONFIG_BOOTP_SERVERIP)
	NetCopyIP(&tmp_ip, &bp->bp_siaddr);
	if (tmp_ip != 0)
		NetCopyIP(&NetServerIP, &bp->bp_siaddr);
	memcpy (NetServerEther, ((Ethernet_t *)NetRxPacket)->et_src, 6);
#endif
#ifdef PRODUCTION_CODE
	/*
	 * Server overrides any target value to ensure the correct file is downloaded
	 */
	if (strlen(bp->bp_file) > 0)
		copy_filename (BootFile, bp->bp_file, sizeof(BootFile));

	debug("Bootfile: %s\n", BootFile);

	/* Propagate to environment:
	 * don't delete exising entry when BOOTP / DHCP reply does
	 * not contain a new value
	 */
	if (*BootFile) {
		setenv ("bootfile", BootFile);
	}
#else
	/*
	 * During development it is useful to be able to force the bootfile value from the
	 * target, rather than allowing the server to override it.
	 */
	if (strlen(bp->bp_file) > 0 && !getenv("bootfile")) 
	{
		/* Propagate to environment:
		 * Only set when BOOTP / DHCP reply contains a new value
		 * and bootfile doesn't exist.
		 */
		copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
		setenv ("bootfile", BootFile);
	}
	debug ("Bootfile: %s\n", BootFile);
	
#endif
}
Exemple #7
0
/*
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 */
static void BootpCopyNetParams(struct Bootp_t *bp)
{
#if !defined(CONFIG_BOOTP_SERVERIP)
	IPaddr_t tmp_ip;

	NetCopyIP(&tmp_ip, &bp->bp_siaddr);
	if (tmp_ip != 0)
		NetCopyIP(&NetServerIP, &bp->bp_siaddr);
	memcpy(NetServerEther, ((struct ethernet_hdr *)NetRxPacket)->et_src, 6);
	if (strlen(bp->bp_file) > 0)
		copy_filename(BootFile, bp->bp_file, sizeof(BootFile));

	debug("Bootfile: %s\n", BootFile);

	/* Propagate to environment:
	 * don't delete exising entry when BOOTP / DHCP reply does
	 * not contain a new value
	 */
	if (*BootFile)
		setenv("bootfile", BootFile);
#endif
	NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
}
Exemple #8
0
static void BootpVendorFieldProcess(u8 * ext){
	int size = *(ext + 1);

	NetBootFileSize = 0;

	switch(*ext){
		/* Fixed length fields */
		case 1:	/* Subnet mask */
			if (NetOurSubnetMask == 0){
				NetCopyIP(&NetOurSubnetMask, (IPaddr_t *)(ext + 2));
			}
			break;

		case 2: /* Time offset - Not yet supported */
			break;

		/* Variable length fields */
		case 3: /* Gateways list */
			if(NetOurGatewayIP == 0){
				NetCopyIP(&NetOurGatewayIP, (IPaddr_t *)(ext + 2));
			}
			break;

		case 4: /* Time server - Not yet supported */
			break;

		case 5: /* IEN-116 name server - Not yet supported */
			break;

		case 6:
			if(NetOurDNSIP == 0){
				NetCopyIP(&NetOurDNSIP, (IPaddr_t *)(ext + 2));
			}
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
			if((NetOurDNS2IP == 0) && (size > 4)){
				NetCopyIP(&NetOurDNS2IP, (IPaddr_t *)(ext + 2 + 4));
			}
#endif
			break;

		case 7: /* Log server - Not yet supported */
			break;

		case 8: /* Cookie/Quote server - Not yet supported */
			break;

		case 9: /* LPR server - Not yet supported */
			break;

		case 10: /* Impress server - Not yet supported */
			break;

		case 11: /* RPL server - Not yet supported */
			break;

		case 12: /* Host name */
			if(NetOurHostName[0] == 0){
				size = truncate_sz("Host Name", sizeof(NetOurHostName), size);
				memcpy(&NetOurHostName, ext + 2, size);
				NetOurHostName[size] = 0;
			}
			break;

		case 13: /* Boot file size */
			if(size == 2){
				NetBootFileSize = ntohs(*(ushort *)(ext + 2));
			} else if(size == 4){
				NetBootFileSize = ntohl(*(ulong *)(ext + 2));
			}
			break;

		case 14: /* Merit dump file - Not yet supported */
			break;

		case 15: /* Domain name - Not yet supported */
			break;

		case 16: /* Swap server - Not yet supported */
			break;

		case 17: /* Root path */
			if(NetOurRootPath[0] == 0){
				size = truncate_sz("Root Path", sizeof(NetOurRootPath), size);
				memcpy(&NetOurRootPath, ext + 2, size);
				NetOurRootPath[size] = 0;
			}
			break;

		case 18: /* Extension path - Not yet supported */
			/*
			 * This can be used to send the information of the
			 * vendor area in another file that the client can
			 * access via TFTP.
			 */
			break;

		/* IP host layer fields */
		case 40: /* NIS Domain name */
			if(NetOurNISDomain[0] == 0){
				size = truncate_sz("NIS Domain Name", sizeof(NetOurNISDomain), size);
				memcpy(&NetOurNISDomain, ext + 2, size);
				NetOurNISDomain[size] = 0;
			}
			break;

		/* Application layer fields */
		case 43: /* Vendor specific info - Not yet supported */
			/*
			 * Binary information to exchange specific
			 * product information.
			 */
			break;
			/* Reserved (custom) fields (128..254) */
	}

}
Exemple #9
0
static void link_local_timeout(void)
{
	switch (state) {
	case PROBE:
		/* timeouts in the PROBE state mean no conflicting ARP packets
		   have been received, so we can progress through the states */
		if (nprobes < PROBE_NUM) {
			nprobes++;
			debug_cond(DEBUG_LL_STATE, "probe/%u %s@%pI4\n",
					nprobes, eth_get_name(), &ip);
			arp_raw_request(0, NetEtherNullAddr, ip);
			timeout_ms = PROBE_MIN * 1000;
			timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
		} else {
			/* Switch to announce state */
			state = ANNOUNCE;
			nclaims = 0;
			debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n",
					nclaims, eth_get_name(), &ip);
			arp_raw_request(ip, NetOurEther, ip);
			timeout_ms = ANNOUNCE_INTERVAL * 1000;
		}
		break;
	case RATE_LIMIT_PROBE:
		/* timeouts in the RATE_LIMIT_PROBE state mean no conflicting
		   ARP packets have been received, so we can move immediately
		   to the announce state */
		state = ANNOUNCE;
		nclaims = 0;
		debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n",
				nclaims, eth_get_name(), &ip);
		arp_raw_request(ip, NetOurEther, ip);
		timeout_ms = ANNOUNCE_INTERVAL * 1000;
		break;
	case ANNOUNCE:
		/* timeouts in the ANNOUNCE state mean no conflicting ARP
		   packets have been received, so we can progress through
		   the states */
		if (nclaims < ANNOUNCE_NUM) {
			nclaims++;
			debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n",
					nclaims, eth_get_name(), &ip);
			arp_raw_request(ip, NetOurEther, ip);
			timeout_ms = ANNOUNCE_INTERVAL * 1000;
		} else {
			/* Switch to monitor state */
			state = MONITOR;
			printf("Successfully assigned %pI4\n", &ip);
			NetCopyIP(&NetOurIP, &ip);
			ready = 1;
			conflicts = 0;
			timeout_ms = -1;
			/* Never timeout in the monitor state */
			NetSetTimeout(0, NULL);

			/* NOTE: all other exit paths should deconfig ... */
			net_set_state(NETLOOP_SUCCESS);
			return;
		}
		break;
	case DEFEND:
		/* We won!  No ARP replies, so just go back to monitor */
		state = MONITOR;
		timeout_ms = -1;
		conflicts = 0;
		break;
	default:
		/* Invalid, should never happen.  Restart the whole protocol */
		state = PROBE;
		ip = pick();
		timeout_ms = 0;
		nprobes = 0;
		nclaims = 0;
		break;
	}
	configure_wait();
}
static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
	ushort proto;
	int i;
	static int ledcount=0,ledstate=1;
	
	if (dest != TftpOurPort) 
	{
		return;
	}
	/* don't care the packets that donot send to TFTP port */
	
	if (TftpState != STATE_RRQ && src != TftpServerPort)
	{
		return;
	}
	
	if (len < 2)
	{
		return;
	}
	

	#if 0
	if (0==ledcount%64)/*the led flicker when packet received*/
		{
			ledstate+=1;
			ledstate%=2;
		}
	if(0==ledstate%2)
		LEDON(11);
	else
		LEDOFF(11);
	++ledcount;
	if (0xffffff==i)
		i=0;
	#endif
	len -= 2;
	/* warning: don't use increment (++) in ntohs() macros!! */
	proto = *((ushort *)pkt)++;
	
	switch (ntohs(proto))
	{
	case TFTP_RRQ:

		printf("\n Get read request from:(");
		print_IPaddr(TempServerIP);
		printf(")\n");
		NetCopyIP(&NetServerIP,&TempServerIP);
		TftpServerPort = src;
		TftpBlock = 1;
		TftpBlockWrapOffset = 0;		
		TftpState = STATE_RRQ;
		
		for (i=0; i<13; i++) 
		{
			if (*((uint8_t *)pkt)++ != asuslink[i])
				break;
		}
		if (i==13) 
		{ /* it's the firmware transmitting situation */
			/* here get the IP address from the first packet. */
			NetOurIP = (*((uint8_t *)pkt)++) & 0x000000ff;
			NetOurIP<<=8;
			NetOurIP|= (*((uint8_t *)pkt)++) & 0x000000ff;
			NetOurIP<<=8;
			NetOurIP|= (*((uint8_t *)pkt)++) & 0x000000ff;
			NetOurIP<<=8;
			NetOurIP|= (*((uint8_t *)pkt)++) & 0x000000ff;
		}
		else
		{
			for (i=0; i<13; i++)
			{
				if (*((uint8_t *)pkt)++ != maclink[i])
					break;
			}
			if(i==13)
			{
				/* here get the IP address from the first packet. */
				NetOurIP = (*((uint8_t *)pkt)++)& 0x000000ff;
				NetOurIP<<=8;
				NetOurIP|=(*((uint8_t *)pkt)++)& 0x000000ff;
				NetOurIP<<=8;
				NetOurIP|=(*((uint8_t *)pkt)++)& 0x000000ff;
				NetOurIP<<=8;
				NetOurIP|=(*((uint8_t *)pkt)++)& 0x000000ff;
			}
		}
		
		TftpdSend();//send a vacant Data packet as a ACK
		break;
		
	case TFTP_WRQ:
		TftpServerPort = src;
		TftpBlock = 0;
		TftpState = STATE_WRQ;
		TftpdSend();
		break;
		
	case TFTP_DATA:
		if (len < 2)
			return;
		len -= 2;
		TftpBlock = ntohs(*(ushort *)pkt);
		/*
		* RFC1350 specifies that the first data packet will
		* have sequence number 1. If we receive a sequence
		* number of 0 this means that there was a wrap
		* around of the (16 bit) counter.
		*/
		if (TftpBlock == 0)
		{
			printf("\n\t %lu MB reveived\n\t ", TftpBlockWrapOffset>>20);
		} 
		else 
		{
			if (((TftpBlock - 1) % 10) == 0) 
static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
	ushort proto;
	int i;

	if (dest != TftpOurPort)
	{
		return;
	}
	/* don't care the packets that donot send to TFTP port */

	if (TftpState != STATE_RRQ && src != TftpServerPort)
	{
		return;
	}

	if (len < 2)
	{
		return;
	}

	len -= 2;
	/* warning: don't use increment (++) in ntohs() macros!! */
	proto = *((ushort *)pkt)++;

	switch (ntohs(proto))
	{
	case TFTP_RRQ:

		printf("\n Get read request from:(");
		print_IPaddr(TempServerIP);
		printf(")\n");
		NetCopyIP(&NetServerIP,&TempServerIP);
		TftpServerPort = src;
		TftpBlock = 1;
		TftpBlockWrapOffset = 0;
		TftpState = STATE_RRQ;
		TftpdSend();//send a vacant Data packet as a ACK
		break;

	case TFTP_WRQ:
		TftpServerPort = src;
		TftpBlock = 0;
		TftpState = STATE_WRQ;
		TftpdSend();
		break;

	case TFTP_DATA:
		if (len < 2)
			return;
		len -= 2;
		TftpBlock = ntohs(*(ushort *)pkt);
		/*
		* RFC1350 specifies that the first data packet will
		* have sequence number 1. If we receive a sequence
		* number of 0 this means that there was a wrap
		* around of the (16 bit) counter.
		*/
		if (TftpBlock == 0)
		{
			printf("\n\t %lu MB reveived\n\t ", TftpBlockWrapOffset>>20);
		}
		else
		{
			if (((TftpBlock - 1) % 10) == 0)
//extern int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
void recoveryHandle(void)
{
	char cmd[256];
	char img[10];
	char * argv[3];
	char *env;
	MV_32 imagAddr, imagSize = 0, netflag = 1;
	char ip[16]= {"dhcp"};
	char* usbload[5];
	unsigned int netwait = 3000;
	int upgrade = -1;
	
	/* get the loadaddr env var */
	if (!getenv("loadaddr")) {
		printf("Missing loadaddr environment variable assuming default (%s)!\n", RCVR_LOAD_ADDR);
		setenv("loadaddr",RCVR_LOAD_ADDR);
		saveenv();
	}

#ifdef CONFIG_USB_STORAGE
	/* First try to perform recovery from USB DOK*/
	/* try to recognize storage devices immediately */
	if (usb_init() >= 0)
	{
		if (usb_stor_scan(1) >= 0)
		{
			netflag = 0;
			usbload[0] = "usbload";
			usbload[1] = "usb";
			usbload[2] = "0:1";
			usbload[3] = getenv("loadaddr");
			usbload[4] = "/multiware.img";

			printf("Trying to load image from USB flash drive using FAT FS\n");
			if (do_fat_fsload(0, 0, 5, usbload) == 1)
			{
				printf("Trying to load image from USB flash drive using ext2 FS partition 0\n");
				usbload[2] = "0:0";
				if(do_ext2load(0, 0, 5, usbload) == 1)
				{
					printf("Trying to load image from USB flash drive using ext2 FS partition 1\n");
					usbload[2] = "0:1";
					if(do_ext2load(0, 0, 5, usbload) == 1)
					{
						printf("Couldn't load recovery image from USB flash drive, Trying network interface\n");
						netflag = 1;
					}
					else
					{
						env = getenv("filesize");
						usbload[3] = getenv("loadaddr");
						imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */
			
						/* Trying to check if we forced to upgrade by placing upgrade.me */
						usbload[4] = "/upgrade.me";
						usbload[3] = "0x000000000";
						env=getenv("loadaddr");
						imagAddr=simple_strtoul(env, NULL, 16);
						sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1);
						printf("dummyaddr:%s\n", usbload[3]);
						upgrade=do_ext2load(0, 0, 5, usbload);
					}
				}
				else
				{
					env = getenv("filesize");
					imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */

					/* Trying to check if we forced to upgrade by placing upgrade.me */
					usbload[4] = "/upgrade.me";
					usbload[3] = "0x000000000";
					env=getenv("loadaddr");
					imagAddr=simple_strtoul(env, NULL, 16);
					sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1);
					printf("dummyaddr:%s\n", usbload[3]);
					upgrade=do_ext2load(0, 0, 5, usbload);
				}
			}
			else
			{
				env = getenv("filesize");
				imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */

				/* Trying to check if we forced to upgrade by placing upgrade.me */
				usbload[4] = "/upgrade.me";
				usbload[3] = "0x000000000";
				env=getenv("loadaddr");
				imagAddr=simple_strtoul(env, NULL, 16);
				sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1);
				printf("dummyaddr:%s\n", usbload[3]);
				upgrade=do_fat_fsload(0, 0, 5, usbload);
			}

			// Decide on upgrade/init mode
			if (upgrade == 0)
				sprintf(ip, "usb_upgrade");
			else
				sprintf(ip, "usb");
			printf("USB mode:%s\n", ip);
		}
	}
#endif

	if(netflag == 1)
	{
		/* if recovery ip set same as our ip then skip dhcp */
		while ( strcmp(getenv("rcvrip"), getenv("ipaddr")) && (netwait > 0) )
		{
			/* Perform the DHCP */
			printf("Aquiring an IP address using DHCP after delay...\n");
			mvOsDelay(netwait);
			netwait-=1000;

			if (NetLoop(DHCP) != -1)
			{
				/* We'vev got DHCP progressing with recovery */
				printf("DHCP should be ready for Recovery.\n");
				break;
			}
		}

		/* No DHCP after timeout or forced */
		if ( !strcmp(getenv("rcvrip"), getenv("ipaddr")) || (netwait <= 0) )
		{
			ulong tmpip;
			printf("No DHCP after timeout or manual IP address configured, switching to static IP address (%s)!\n", getenv("rcvrip"));
			tmpip = getenv_IPaddr ("rcvrip");
			NetCopyIP(&NetOurIP, &tmpip);
			sprintf(ip, "static");
		}

		/* Perform the recovery */
		printf("Starting retrieval of recovery image over network...\n");
		if ((imagSize = NetLoop(RCVR)) == -1)
		{
			printf("Failed\n");
			return;
		}
	}

	switch (mvBoardIdGet())
	{
		case RD_88F6510_SFU_ID:
		case RD_88F6560_GW_ID:
		case DB_88F6535_BP_ID:
			setenv("bootcmd","setenv bootargs ${console} ubi.mtd=2 root=ubi0:rootfsU rootfstype=ubifs ${mvNetConfig} ${mvPhoneConfig}; nand read.e ${loadaddr} 0x200000 0x400000; bootm ${loadaddr};");
			setenv("console","console=ttyS0,115200");
			saveenv();
		break;
	}

	printf("\nPermanent bootcmd: %s\n", getenv("bootcmd"));
	printf("\nPermanent console: %s\n", getenv("console"));

	/* This assignment to cmd should execute prior to the RD setenv and saveenv below*/
	sprintf(cmd,"setenv bootargs ${console} root=/dev/ram0 ${mvNetConfig} recovery=%s rcvrip=%s:%s%s  ethact=${ethact} ethaddr=%s eth1addr=%s; bootm ${loadaddr};", ip, getenv("rcvrip"), getenv("serverip"), getenv("bootargs_end"), getenv("ethaddr"), getenv("eth1addr"));
	setenv("bootcmd", cmd);
	printf("\nRecovery bootcmd: %s\n", cmd);

	printf("Booting recovery image at: [%s]...\n", getenv("loadaddr"));
	sprintf(cmd, "boot");
	sprintf(img, "%s", getenv("loadaddr"));
	argv[0] = cmd;
	argv[1] = img;

	do_bootd(NULL, 0, 2, argv);
}
void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
{
	struct arp_hdr *arp;
	IPaddr_t reply_ip_addr;
	uchar *pkt;
	int eth_hdr_size;

	/*
	 * We have to deal with two types of ARP packets:
	 * - REQUEST packets will be answered by sending  our
	 *   IP address - if we know it.
	 * - REPLY packates are expected only after we asked
	 *   for the TFTP server's or the gateway's ethernet
	 *   address; so if we receive such a packet, we set
	 *   the server ethernet address
	 */
	debug_cond(DEBUG_NET_PKT, "Got ARP\n");

	arp = (struct arp_hdr *)ip;
	if (len < ARP_HDR_SIZE) {
		printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
		return;
	}
	if (ntohs(arp->ar_hrd) != ARP_ETHER)
		return;
	if (ntohs(arp->ar_pro) != PROT_IP)
		return;
	if (arp->ar_hln != ARP_HLEN)
		return;
	if (arp->ar_pln != ARP_PLEN)
		return;

	if (NetOurIP == 0)
		return;

	if (NetReadIP(&arp->ar_tpa) != NetOurIP)
		return;

	switch (ntohs(arp->ar_op)) {
	case ARPOP_REQUEST:
		/* reply with our IP address */
		debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n");
		pkt = (uchar *)et;
		eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP);
		pkt += eth_hdr_size;
		arp->ar_op = htons(ARPOP_REPLY);
		memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN);
		NetCopyIP(&arp->ar_tpa, &arp->ar_spa);
		memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN);
		NetCopyIP(&arp->ar_spa, &NetOurIP);

#ifdef CONFIG_CMD_LINK_LOCAL
		/*
		 * Work-around for brain-damaged Cisco equipment with
		 *   arp-proxy enabled.
		 *
		 *   If the requesting IP is not on our subnet, wait 5ms to
		 *   reply to ARP request so that our reply will overwrite
		 *   the arp-proxy's instead of the other way around.
		 */
		if ((NetReadIP(&arp->ar_tpa) & NetOurSubnetMask) !=
		    (NetReadIP(&arp->ar_spa) & NetOurSubnetMask))
			udelay(5000);
#endif
		NetSendPacket((uchar *)et, eth_hdr_size + ARP_HDR_SIZE);
		return;

	case ARPOP_REPLY:		/* arp reply */
		/* are we waiting for a reply */
		if (!NetArpWaitPacketIP)
			break;

#ifdef CONFIG_KEEP_SERVERADDR
		if (NetServerIP == NetArpWaitPacketIP) {
			char buf[20];
			sprintf(buf, "%pM", &arp->ar_sha);
			setenv("serveraddr", buf);
		}
#endif

		reply_ip_addr = NetReadIP(&arp->ar_spa);

		/* matched waiting packet's address */
		if (reply_ip_addr == NetArpWaitReplyIP) {
			debug_cond(DEBUG_DEV_PKT,
				"Got ARP REPLY, set eth addr (%pM)\n",
				arp->ar_data);

			/* save address for later use */
			if (NetArpWaitPacketMAC != NULL)
				memcpy(NetArpWaitPacketMAC,
				       &arp->ar_sha, ARP_HLEN);

			net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr,
				0, len);

			/* set the mac address in the waiting packet's header
			   and transmit it */
			memcpy(((struct ethernet_hdr *)NetTxPacket)->et_dest,
				&arp->ar_sha, ARP_HLEN);
			NetSendPacket(NetTxPacket, NetArpWaitTxPacketSize);

			/* no arp request pending now */
			NetArpWaitPacketIP = 0;
			NetArpWaitTxPacketSize = 0;
			NetArpWaitPacketMAC = NULL;

		}
		return;
	default:
		debug("Unexpected ARP opcode 0x%x\n",
		      ntohs(arp->ar_op));
		return;
	}
}