Example #1
0
int net_start_again(void)
{
	char *nretry;
	int retry_forever = 0;
	unsigned long retrycnt = 0;
	int ret;

	nretry = getenv("netretry");
	if (nretry) {
		if (!strcmp(nretry, "yes"))
			retry_forever = 1;
		else if (!strcmp(nretry, "no"))
			retrycnt = 0;
		else if (!strcmp(nretry, "once"))
			retrycnt = 1;
		else
			retrycnt = simple_strtoul(nretry, NULL, 0);
	} else {
		retrycnt = 0;
		retry_forever = 0;
	}

	if ((!retry_forever) && (net_try_count >= retrycnt)) {
		eth_halt();
		net_set_state(NETLOOP_FAIL);
		/*
		 * We don't provide a way for the protocol to return an error,
		 * but this is almost always the reason.
		 */
		return -ETIMEDOUT;
	}

	net_try_count++;

	eth_halt();
#if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
	eth_try_another(!net_restarted);
#endif
	ret = eth_init();
	if (net_restart_wrap) {
		net_restart_wrap = 0;
		if (net_dev_exists) {
			net_set_timeout_handler(10000UL,
						start_again_timeout_handler);
			net_set_udp_handler(NULL);
		} else {
			net_set_state(NETLOOP_FAIL);
		}
	} else {
		net_set_state(NETLOOP_RESTART);
	}
	return ret;
}
Example #2
0
void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
{
	struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src;
	struct in_addr src_ip;
	int eth_hdr_size;

	switch (icmph->type) {
	case ICMP_ECHO_REPLY:
		src_ip = net_read_ip((void *)&ip->ip_src);
		if (src_ip.s_addr == net_ping_ip.s_addr)
			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;
		net_copy_ip((void *)&ip->ip_dst, &ip->ip_src);
		net_copy_ip((void *)&ip->ip_src, &net_ip);
		ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE);

		icmph->type = ICMP_ECHO_REPLY;
		icmph->checksum = 0;
		icmph->checksum = compute_ip_checksum(icmph, len - IP_HDR_SIZE);
		net_send_packet((uchar *)et, eth_hdr_size + len);
		return;
/*	default:
		return;*/
	}
}
Example #3
0
void
NfsStart(void)
{
	debug("%s\n", __func__);
	nfs_download_state = NETLOOP_FAIL;

	NfsServerIP = NetServerIP;
	nfs_path = (char *)nfs_path_buff;

	if (nfs_path == NULL) {
		net_set_state(NETLOOP_FAIL);
		puts("*** ERROR: Fail allocate memory\n");
		return;
	}

	if (BootFile[0] == '\0') {
		sprintf(default_filename, "/nfsroot/%02X%02X%02X%02X.img",
			NetOurIP & 0xFF,
			(NetOurIP >>  8) & 0xFF,
			(NetOurIP >> 16) & 0xFF,
			(NetOurIP >> 24) & 0xFF);
		strcpy(nfs_path, default_filename);

		printf("*** Warning: no boot file name; using '%s'\n",
			nfs_path);
	} else {
Example #4
0
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;*/
	}
}
Example #5
0
void NetStartAgain(void)
{
	char *nretry;
	int retry_forever = 0;
	unsigned long retrycnt = 0;

	nretry = getenv("netretry");
	if (nretry) {
		if (!strcmp(nretry, "yes"))
			retry_forever = 1;
		else if (!strcmp(nretry, "no"))
			retrycnt = 0;
		else if (!strcmp(nretry, "once"))
			retrycnt = 1;
		else
			retrycnt = simple_strtoul(nretry, NULL, 0);
	} else
		retry_forever = 1;

	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
		eth_halt();
		net_set_state(NETLOOP_FAIL);
		return;
	}

	NetTryCount++;

	eth_halt();
#if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
	eth_try_another(!NetRestarted);
#endif
	eth_init(gd->bd);
	if (NetRestartWrap) {
		NetRestartWrap = 0;
		if (NetDevExists) {
			NetSetTimeout(10000UL, startAgainTimeout);
			net_set_udp_handler(NULL);
		} else {
			net_set_state(NETLOOP_FAIL);
		}
	} else {
		net_set_state(NETLOOP_RESTART);
	}
}
Example #6
0
void register_net_interface(net_interface_t *interface) {
    interface->rx_total = 0;
    interface->tx_total = 0;

    interface->ip_data = 0;

    uint32_t flags;
    spin_lock_irqsave(&interface_lock, &flags);

    list_add(&interface->list, &interfaces);

    spin_unlock_irqstore(&interface_lock, flags);

    net_set_state(interface, IF_DOWN);
}
Example #7
0
/*
 *	Timeout on BOOTP/DHCP request.
 */
static void
BootpTimeout(void)
{
	if (BootpTry >= TIMEOUT_COUNT) {
#ifdef CONFIG_BOOTP_MAY_FAIL
		puts("\nRetry count exceeded\n");
		net_set_state(NETLOOP_FAIL);
#else
		puts("\nRetry count exceeded; starting again\n");
		NetStartAgain();
#endif
	} else {
		NetSetTimeout(TIMEOUT, BootpTimeout);
		BootpRequest();
	}
}
Example #8
0
/* The TFTP get or put is complete */
static void tftp_complete(void)
{
#ifdef CONFIG_TFTP_TSIZE
	/* Print hash marks for the last packet received */
	while (TftpTsize && TftpNumchars < 49) {
		putc('#');
		TftpNumchars++;
	}
#endif
	time_start = get_timer(time_start);
	if (time_start > 0) {
		puts("\n\t ");	/* Line up with "Loading: " */
		print_size(NetBootFileXferSize /
			time_start * 1000, "/s");
	}
	puts("\ndone\n");
	net_set_state(NETLOOP_SUCCESS);
}
Example #9
0
/*
 *	Timeout on BOOTP/DHCP request.
 */
static void bootp_timeout_handler(void)
{
	ulong time_taken = get_timer(bootp_start);

	if (time_taken >= TIMEOUT_MS) {
#ifdef CONFIG_BOOTP_MAY_FAIL
		puts("\nRetry time exceeded\n");
		net_set_state(NETLOOP_FAIL);
#else
		puts("\nRetry time exceeded; starting again\n");
		net_start_again();
#endif
	} else {
		bootp_timeout *= 2;
		if (bootp_timeout > 2000)
			bootp_timeout = 2000;
		net_set_timeout_handler(bootp_timeout, bootp_timeout_handler);
		bootp_request();
	}
}
Example #10
0
/*
 *	Timeout on BOOTP/DHCP request.
 */
static void
BootpTimeout(void)
{
	ulong time_taken = get_timer(bootp_start);

	if (time_taken >= TIMEOUT_MS) {
#ifdef CONFIG_BOOTP_MAY_FAIL
		puts("\nRetry time exceeded\n");
		net_set_state(NETLOOP_FAIL);
#else
		puts("\nRetry time exceeded; starting again\n");
		NetStartAgain();
#endif
	} else {
		bootp_timeout *= 2;
		if (bootp_timeout > 2000)
			bootp_timeout = 2000;
		NetSetTimeout(bootp_timeout, BootpTimeout);
		BootpRequest();
	}
}
Example #11
0
static inline void
store_block(int block, uchar *src, unsigned len)
{
	ulong offset = block * TftpBlkSize + TftpBlockWrapOffset;
	ulong newsize = offset + len;
#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
	int i, rc = 0;

	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
		/* start address in flash? */
		if (flash_info[i].flash_id == FLASH_UNKNOWN)
			continue;
		if (load_addr + offset >= flash_info[i].start[0]) {
			rc = 1;
			break;
		}
	}

	if (rc) { /* Flash is destination for this packet */
		rc = flash_write((char *)src, (ulong)(load_addr+offset), len);
		if (rc) {
			flash_perror(rc);
			net_set_state(NETLOOP_FAIL);
			return;
		}
	} else
#endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
	{
		(void)memcpy((void *)(load_addr + offset), src, len);
	}
#ifdef CONFIG_MCAST_TFTP
	if (Multicast)
		ext2_set_bit(block, Bitmap);
#endif

	if (NetBootFileXferSize < newsize)
		NetBootFileXferSize = newsize;
}
Example #12
0
/*
 * Check if autoload is enabled. If so, use either NFS or TFTP to download
 * the boot file.
 */
void net_auto_load(void)
{
#if defined(CONFIG_CMD_NFS)
	const char *s = getenv("autoload");

	if (s != NULL && strcmp(s, "NFS") == 0) {
		/*
		 * Use NFS to load the bootfile.
		 */
		nfs_start();
		return;
	}
#endif
	if (getenv_yesno("autoload") == 0) {
		/*
		 * Just use BOOTP/RARP to configure system;
		 * Do not use TFTP to load the bootfile.
		 */
		net_set_state(NETLOOP_SUCCESS);
		return;
	}
	tftp_start(TFTPGET);
}
Example #13
0
void link_local_start(void)
{
	ip = getenv_IPaddr("llipaddr");
	if (ip != 0 && (ip & IN_CLASSB_NET) != LINKLOCAL_ADDR) {
		puts("invalid link address");
		net_set_state(NETLOOP_FAIL);
		return;
	}
	NetOurSubnetMask = IN_CLASSB_NET;

	seed = seed_mac();
	if (ip == 0)
		ip = pick();

	state = PROBE;
	timeout_ms = 0;
	conflicts = 0;
	nprobes = 0;
	nclaims = 0;
	ready = 0;

	configure_wait();
}
Example #14
0
int arp_timeout_check(void)
{
	ulong t;

	if (!net_arp_wait_packet_ip.s_addr)
		return 0;

	t = get_timer(0);

	/* check for arp timeout */
	if ((t - arp_wait_timer_start) > ARP_TIMEOUT) {
		arp_wait_try++;

		if (arp_wait_try >= ARP_TIMEOUT_COUNT) {
			puts("\nARP Retry count exceeded; starting again\n");
			arp_wait_try = 0;
			net_set_state(NETLOOP_FAIL);
		} else {
			arp_wait_timer_start = t;
			arp_request();
		}
	}
	return 1;
}
Example #15
0
static void bootme_handler(uchar *pkt, unsigned dest_port, IPaddr_t src_ip,
			unsigned src_port, unsigned len)
{
	uchar *eth_pkt = pkt;
	unsigned eth_len = len;
	static char cursor = '|';
	enum bootme_state last_state = BOOTME_INIT;
#if 1
	debug("received packet of len %d from %pI4:%d to port %d\n",
		len, &src_ip, src_port, dest_port);
	ce_dump_block(pkt, len);
#endif
	if (!bootme_packet_handler) {
		printf("No packet handler set for BOOTME protocol; dropping packet\n");
		return;
	}
	if (dest_port != bootme_src_port || !len)
		return; /* not for us */

	printf("%c\x08", cursor);
	cursor = next_cursor(cursor);

	if (is_broadcast(bootme_ip)) {
		bootme_ip = src_ip;
	} else if (src_ip != bootme_ip) {
		debug("src_ip %pI4 does not match destination IP %pI4\n",
			&src_ip, &bootme_ip);
		return; /* not from our server */
	}

	last_state = bootme_state;
	bootme_dst_port = src_port;
	debug("bootme_dst_port set to %d\n", bootme_dst_port);
	if (bootme_state == BOOTME_INIT) {
		bootme_src_port = EDBG_SVC_PORT;
		debug("%s: bootme_src_port set to %d\n", __func__, bootme_src_port);
	}
	bootme_state = bootme_packet_handler(eth_pkt, eth_len);
	debug("bootme_packet_handler() returned %d\n", bootme_state);
	if (bootme_state != last_state)
		debug("bootme_state: %d -> %d\n", last_state, bootme_state);
	switch (bootme_state) {
	case BOOTME_INIT:
		break;

	case BOOTME_DOWNLOAD:
		if (last_state != BOOTME_INIT)
			NetBootFileXferSize += len - 4;
		/* fallthru */
	case BOOTME_DEBUG:
		if (last_state == BOOTME_INIT) {
			bootme_timeout = 3 * 1000;
		}
		NetSetTimeout(bootme_timeout, bootme_timeout_handler);
		break;

	case BOOTME_DONE:
		net_set_state(NETLOOP_SUCCESS);
		bootme_packet_handler = NULL;
		break;

	case BOOTME_ERROR:
		net_set_state(NETLOOP_FAIL);
		bootme_packet_handler = NULL;
	}
}
Example #16
0
static void bootme_wait_arp_handler(uchar *pkt, unsigned dest,
				IPaddr_t sip, unsigned src,
				unsigned len)
{
	net_set_state(NETLOOP_SUCCESS); /* got arp reply - quit net loop */
}
Example #17
0
static void nc_wait_arp_handler(uchar *pkt, unsigned dest,
				 struct in_addr sip, unsigned src,
				 unsigned len)
{
	net_set_state(NETLOOP_SUCCESS); /* got arp reply - quit net loop */
}
Example #18
0
static void start_again_timeout_handler(void)
{
	net_set_state(NETLOOP_RESTART);
}
Example #19
0
int net_loop(enum proto_t protocol)
{
	int ret = -EINVAL;

	net_restarted = 0;
	net_dev_exists = 0;
	net_try_count = 1;
	debug_cond(DEBUG_INT_STATE, "--- net_loop Entry\n");

	bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
	net_init();
	if (eth_is_on_demand_init() || protocol != NETCONS) {
		eth_halt();
		eth_set_current();
		ret = eth_init();
		if (ret < 0) {
			eth_halt();
			return ret;
		}
	} else {
		eth_init_state_only();
	}
restart:
#ifdef CONFIG_USB_KEYBOARD
	net_busy_flag = 0;
#endif
	net_set_state(NETLOOP_CONTINUE);

	/*
	 *	Start the ball rolling with the given start function.  From
	 *	here on, this code is a state machine driven by received
	 *	packets and timer events.
	 */
	debug_cond(DEBUG_INT_STATE, "--- net_loop Init\n");
	net_init_loop();

	switch (net_check_prereq(protocol)) {
	case 1:
		/* network not configured */
		eth_halt();
		return -ENODEV;

	case 2:
		/* network device not configured */
		break;

	case 0:
		net_dev_exists = 1;
		net_boot_file_size = 0;
		switch (protocol) {
		case TFTPGET:
#ifdef CONFIG_CMD_TFTPPUT
		case TFTPPUT:
#endif
			/* always use ARP to get server ethernet address */
			tftp_start(protocol);
			break;
#ifdef CONFIG_CMD_TFTPSRV
		case TFTPSRV:
			tftp_start_server();
			break;
#endif
#if defined(CONFIG_CMD_DHCP)
		case DHCP:
			bootp_reset();
			net_ip.s_addr = 0;
			dhcp_request();		/* Basically same as BOOTP */
			break;
#endif

		case BOOTP:
			bootp_reset();
			net_ip.s_addr = 0;
			bootp_request();
			break;

#if defined(CONFIG_CMD_RARP)
		case RARP:
			rarp_try = 0;
			net_ip.s_addr = 0;
			rarp_request();
			break;
#endif
#if defined(CONFIG_CMD_PING)
		case PING:
			ping_start();
			break;
#endif
#if defined(CONFIG_CMD_NFS)
		case NFS:
			nfs_start();
			break;
#endif
#if defined(CONFIG_CMD_CDP)
		case CDP:
			cdp_start();
			break;
#endif
#if defined(CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD)
		case NETCONS:
			nc_start();
			break;
#endif
#if defined(CONFIG_CMD_SNTP)
		case SNTP:
			sntp_start();
			break;
#endif
#if defined(CONFIG_CMD_DNS)
		case DNS:
			dns_start();
			break;
#endif
#if defined(CONFIG_CMD_LINK_LOCAL)
		case LINKLOCAL:
			link_local_start();
			break;
#endif
		default:
			break;
		}

		break;
	}

#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
#if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
	defined(CONFIG_STATUS_LED)			&& \
	defined(STATUS_LED_RED)
	/*
	 * Echo the inverted link state to the fault LED.
	 */
	if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
		status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
	else
		status_led_set(STATUS_LED_RED, STATUS_LED_ON);
#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
#endif /* CONFIG_MII, ... */
#ifdef CONFIG_USB_KEYBOARD
	net_busy_flag = 1;
#endif

	/*
	 *	Main packet reception loop.  Loop receiving packets until
	 *	someone sets `net_state' to a state that terminates.
	 */
	for (;;) {
		WATCHDOG_RESET();
#ifdef CONFIG_SHOW_ACTIVITY
		show_activity(1);
#endif
		if (arp_timeout_check() > 0)
			time_start = get_timer(0);

		/*
		 *	Check the ethernet for a new packet.  The ethernet
		 *	receive routine will process it.
		 *	Most drivers return the most recent packet size, but not
		 *	errors that may have happened.
		 */
		eth_rx();

		/*
		 *	Abort if ctrl-c was pressed.
		 */
		if (ctrlc()) {
			/* cancel any ARP that may not have completed */
			net_arp_wait_packet_ip.s_addr = 0;

			net_cleanup_loop();
			eth_halt();
			/* Invalidate the last protocol */
			eth_set_last_protocol(BOOTP);

			puts("\nAbort\n");
			/* include a debug print as well incase the debug
			   messages are directed to stderr */
			debug_cond(DEBUG_INT_STATE, "--- net_loop Abort!\n");
			ret = -EINTR;
			goto done;
		}

		/*
		 *	Check for a timeout, and run the timeout handler
		 *	if we have one.
		 */
		if (time_handler &&
		    ((get_timer(0) - time_start) > time_delta)) {
			thand_f *x;

#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
#if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
	defined(CONFIG_STATUS_LED)			&& \
	defined(STATUS_LED_RED)
			/*
			 * Echo the inverted link state to the fault LED.
			 */
			if (miiphy_link(eth_get_dev()->name,
					CONFIG_SYS_FAULT_MII_ADDR))
				status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
			else
				status_led_set(STATUS_LED_RED, STATUS_LED_ON);
#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
#endif /* CONFIG_MII, ... */
			debug_cond(DEBUG_INT_STATE, "--- net_loop timeout\n");
			x = time_handler;
			time_handler = (thand_f *)0;
			(*x)();
		}

		if (net_state == NETLOOP_FAIL)
			ret = net_start_again();

		switch (net_state) {
		case NETLOOP_RESTART:
			net_restarted = 1;
			goto restart;

		case NETLOOP_SUCCESS:
			net_cleanup_loop();
			if (net_boot_file_size > 0) {
				printf("Bytes transferred = %d (%x hex)\n",
				       net_boot_file_size, net_boot_file_size);
				setenv_hex("filesize", net_boot_file_size);
				setenv_hex("fileaddr", load_addr);
			}
			if (protocol != NETCONS)
				eth_halt();
			else
				eth_halt_state_only();

			eth_set_last_protocol(protocol);

			ret = net_boot_file_size;
			debug_cond(DEBUG_INT_STATE, "--- net_loop Success!\n");
			goto done;

		case NETLOOP_FAIL:
			net_cleanup_loop();
			/* Invalidate the last protocol */
			eth_set_last_protocol(BOOTP);
			debug_cond(DEBUG_INT_STATE, "--- net_loop Fail!\n");
			goto done;

		case NETLOOP_CONTINUE:
			continue;
		}
	}

done:
#ifdef CONFIG_USB_KEYBOARD
	net_busy_flag = 0;
#endif
#ifdef CONFIG_CMD_TFTPPUT
	/* Clear out the handlers */
	net_set_udp_handler(NULL);
	net_set_icmp_handler(NULL);
#endif
	return ret;
}
Example #20
0
int NetLoop(enum proto_t protocol)
{
	bd_t *bd = gd->bd;
	int ret = -1;

	NetRestarted = 0;
	NetDevExists = 0;
	NetTryCount = 1;
	debug_cond(DEBUG_INT_STATE, "--- NetLoop Entry\n");

	bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
	net_init();
	if (eth_is_on_demand_init() || protocol != NETCONS) {
		eth_halt();
		eth_set_current();
		if (eth_init(bd) < 0) {
			eth_halt();
			return -1;
		}
	} else
		eth_init_state_only(bd);

restart:
#ifdef CONFIG_USB_KEYBOARD
	net_busy_flag = 0;
#endif
	net_set_state(NETLOOP_CONTINUE);

	/*
	 *	Start the ball rolling with the given start function.  From
	 *	here on, this code is a state machine driven by received
	 *	packets and timer events.
	 */
	debug_cond(DEBUG_INT_STATE, "--- NetLoop Init\n");
	NetInitLoop();

	switch (net_check_prereq(protocol)) {
	case 1:
		/* network not configured */
		eth_halt();
		return -1;

	case 2:
		/* network device not configured */
		break;

	case 0:
		NetDevExists = 1;
		NetBootFileXferSize = 0;
		switch (protocol) {
		case TFTPGET:
#ifdef CONFIG_CMD_TFTPPUT
		case TFTPPUT:
#endif
			/* always use ARP to get server ethernet address */
			TftpStart(protocol);
			break;
#ifdef CONFIG_CMD_TFTPSRV
		case TFTPSRV:
			TftpStartServer();
			break;
#endif
#if defined(CONFIG_CMD_DHCP)
		case DHCP:
			BootpReset();
			NetOurIP = 0;
			DhcpRequest();		/* Basically same as BOOTP */
			break;
#endif

		case BOOTP:
			BootpReset();
			NetOurIP = 0;
			BootpRequest();
			break;

#if defined(CONFIG_CMD_RARP)
		case RARP:
			RarpTry = 0;
			NetOurIP = 0;
			RarpRequest();
			break;
#endif
#if defined(CONFIG_CMD_PING)
		case PING:
			ping_start();
			break;
#endif
#if defined(CONFIG_CMD_NFS)
		case NFS:
			NfsStart();
			break;
#endif
#if defined(CONFIG_CMD_CDP)
		case CDP:
			CDPStart();
			break;
#endif
#if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD)
		case NETCONS:
			NcStart();
			break;
#endif
#if defined(CONFIG_CMD_SNTP)
		case SNTP:
			SntpStart();
			break;
#endif
#if defined(CONFIG_CMD_DNS)
		case DNS:
			DnsStart();
			break;
#endif
#if defined(CONFIG_CMD_LINK_LOCAL)
		case LINKLOCAL:
			link_local_start();
			break;
#endif
		default:
			break;
		}

		break;
	}

#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
#if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
	defined(CONFIG_STATUS_LED)			&& \
	defined(STATUS_LED_RED)
	/*
	 * Echo the inverted link state to the fault LED.
	 */
	if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
		status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
	else
		status_led_set(STATUS_LED_RED, STATUS_LED_ON);
#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
#endif /* CONFIG_MII, ... */
#ifdef CONFIG_USB_KEYBOARD
	net_busy_flag = 1;
#endif

	/*
	 *	Main packet reception loop.  Loop receiving packets until
	 *	someone sets `net_state' to a state that terminates.
	 */
	for (;;) {
		WATCHDOG_RESET();
#ifdef CONFIG_SHOW_ACTIVITY
		show_activity(1);
#endif
		/*
		 *	Check the ethernet for a new packet.  The ethernet
		 *	receive routine will process it.
		 */
		eth_rx();

		/*
		 *	Abort if ctrl-c was pressed.
		 */
		if (ctrlc()) {
			/* cancel any ARP that may not have completed */
			NetArpWaitPacketIP = 0;

			net_cleanup_loop();
			eth_halt();
			/* Invalidate the last protocol */
			eth_set_last_protocol(BOOTP);

			puts("\nAbort\n");
			/* include a debug print as well incase the debug
			   messages are directed to stderr */
			debug_cond(DEBUG_INT_STATE, "--- NetLoop Abort!\n");
			goto done;
		}

		ArpTimeoutCheck();

		/*
		 *	Check for a timeout, and run the timeout handler
		 *	if we have one.
		 */
		if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
			thand_f *x;

#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
#if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
	defined(CONFIG_STATUS_LED)			&& \
	defined(STATUS_LED_RED)
			/*
			 * Echo the inverted link state to the fault LED.
			 */
			if (miiphy_link(eth_get_dev()->name,
				       CONFIG_SYS_FAULT_MII_ADDR)) {
				status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
			} else {
				status_led_set(STATUS_LED_RED, STATUS_LED_ON);
			}
#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
#endif /* CONFIG_MII, ... */
			debug_cond(DEBUG_INT_STATE, "--- NetLoop timeout\n");
			x = timeHandler;
			timeHandler = (thand_f *)0;
			(*x)();
		}


		switch (net_state) {

		case NETLOOP_RESTART:
			NetRestarted = 1;
			goto restart;

		case NETLOOP_SUCCESS:
			net_cleanup_loop();
			if (NetBootFileXferSize > 0) {
				printf("Bytes transferred = %ld (%lx hex)\n",
					NetBootFileXferSize,
					NetBootFileXferSize);
				setenv_hex("filesize", NetBootFileXferSize);
				setenv_hex("fileaddr", load_addr);
			}
			if (protocol != NETCONS)
				eth_halt();
			else
				eth_halt_state_only();

			eth_set_last_protocol(protocol);

			ret = NetBootFileXferSize;
			debug_cond(DEBUG_INT_STATE, "--- NetLoop Success!\n");
			goto done;

		case NETLOOP_FAIL:
			net_cleanup_loop();
			/* Invalidate the last protocol */
			eth_set_last_protocol(BOOTP);
			debug_cond(DEBUG_INT_STATE, "--- NetLoop Fail!\n");
			goto done;

		case NETLOOP_CONTINUE:
			continue;
		}
	}

done:
#ifdef CONFIG_USB_KEYBOARD
	net_busy_flag = 0;
#endif
#ifdef CONFIG_CMD_TFTPPUT
	/* Clear out the handlers */
	net_set_udp_handler(NULL);
	net_set_icmp_handler(NULL);
#endif
	return ret;
}
Example #21
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();
}
Example #22
0
static void nc_timeout_handler(void)
{
	net_set_state(NETLOOP_SUCCESS);
}
Example #23
0
static void ping_timeout_handler(void)
{
	eth_halt();
	net_set_state(NETLOOP_FAIL);	/* we did not get the reply */
}
Example #24
0
File: dns.c Project: Noltari/u-boot
static void dns_handler(uchar *pkt, unsigned dest, struct in_addr sip,
			unsigned src, unsigned len)
{
	struct header *header;
	const unsigned char *p, *e, *s;
	u16 type, i;
	int found, stop, dlen;
	char ip_str[22];
	struct in_addr ip_addr;


	debug("%s\n", __func__);
	if (dest != dns_our_port)
		return;

	for (i = 0; i < len; i += 4)
		debug("0x%p - 0x%.2x  0x%.2x  0x%.2x  0x%.2x\n",
		      pkt+i, pkt[i], pkt[i+1], pkt[i+2], pkt[i+3]);

	/* We sent one query. We want to have a single answer: */
	header = (struct header *)pkt;
	if (ntohs(header->nqueries) != 1)
		return;

	/* Received 0 answers */
	if (header->nanswers == 0) {
		puts("DNS: host not found\n");
		net_set_state(NETLOOP_SUCCESS);
		return;
	}

	/* Skip host name */
	s = &header->data[0];
	e = pkt + len;
	for (p = s; p < e && *p != '\0'; p++)
		continue;

	/* We sent query class 1, query type 1 */
	if (&p[5] > e || get_unaligned_be16(p+1) != DNS_A_RECORD) {
		puts("DNS: response was not an A record\n");
		net_set_state(NETLOOP_SUCCESS);
		return;
	}

	/* Go to the first answer section */
	p += 5;

	/* Loop through the answers, we want A type answer */
	for (found = stop = 0; !stop && &p[12] < e; ) {
		/* Skip possible name in CNAME answer */
		if (*p != 0xc0) {
			while (*p && &p[12] < e)
				p++;
			p--;
		}
		debug("Name (Offset in header): %d\n", p[1]);

		type = get_unaligned_be16(p+2);
		debug("type = %d\n", type);
		if (type == DNS_CNAME_RECORD) {
			/* CNAME answer. shift to the next section */
			debug("Found canonical name\n");
			dlen = get_unaligned_be16(p+10);
			debug("dlen = %d\n", dlen);
			p += 12 + dlen;
		} else if (type == DNS_A_RECORD) {
			debug("Found A-record\n");
			found = 1;
			stop = 1;
		} else {
			debug("Unknown type\n");
			stop = 1;
		}
	}

	if (found && &p[12] < e) {
		dlen = get_unaligned_be16(p+10);
		p += 12;
		memcpy(&ip_addr, p, 4);

		if (p + dlen <= e) {
			ip_to_string(ip_addr, ip_str);
			printf("%s\n", ip_str);
			if (net_dns_env_var)
				env_set(net_dns_env_var, ip_str);
		} else {
			puts("server responded with invalid IP number\n");
		}
	}

	net_set_state(NETLOOP_SUCCESS);
}
Example #25
0
static void bootme_timeout_handler(void)
{
	net_set_state(NETLOOP_SUCCESS);
	bootme_timed_out++;
}
Example #26
0
static void nc_handler(uchar *pkt, unsigned dest, struct in_addr sip,
		       unsigned src, unsigned len)
{
	if (input_size)
		net_set_state(NETLOOP_SUCCESS); /* got input - quit net loop */
}
Example #27
0
File: dns.c Project: Noltari/u-boot
static void dns_timeout_handler(void)
{
	puts("Timeout\n");
	net_set_state(NETLOOP_FAIL);
}
Example #28
0
static void
startAgainTimeout(void)
{
	net_set_state(NETLOOP_RESTART);
}
Example #29
0
static void
TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
	    unsigned len)
{
	__be16 proto;
	__be16 *s;
	int i;

	if (dest != TftpOurPort) {
#ifdef CONFIG_MCAST_TFTP
		if (Multicast
		 && (!Mcast_port || (dest != Mcast_port)))
#endif
			return;
	}
	if (TftpState != STATE_SEND_RRQ && src != TftpRemotePort &&
	    TftpState != STATE_RECV_WRQ && TftpState != STATE_SEND_WRQ)
		return;

	if (len < 2)
		return;
	len -= 2;
	/* warning: don't use increment (++) in ntohs() macros!! */
	s = (__be16 *)pkt;
	proto = *s++;
	pkt = (uchar *)s;
	switch (ntohs(proto)) {

	case TFTP_RRQ:
		break;

	case TFTP_ACK:
#ifdef CONFIG_CMD_TFTPPUT
		if (TftpWriting) {
			if (TftpFinalBlock) {
				tftp_complete();
			} else {
				/*
				 * Move to the next block. We want our block
				 * count to wrap just like the other end!
				 */
				int block = ntohs(*s);
				int ack_ok = (TftpBlock == block);

				TftpBlock = (unsigned short)(block + 1);
				update_block_number();
				if (ack_ok)
					TftpSend(); /* Send next data block */
			}
		}
#endif
		break;

	default:
		break;

#ifdef CONFIG_CMD_TFTPSRV
	case TFTP_WRQ:
		debug("Got WRQ\n");
		TftpRemoteIP = sip;
		TftpRemotePort = src;
		TftpOurPort = 1024 + (get_timer(0) % 3072);
		new_transfer();
		TftpSend(); /* Send ACK(0) */
		break;
#endif

	case TFTP_OACK:
		debug("Got OACK: %s %s\n",
			pkt,
			pkt + strlen((char *)pkt) + 1);
		TftpState = STATE_OACK;
		TftpRemotePort = src;
		/*
		 * Check for 'blksize' option.
		 * Careful: "i" is signed, "len" is unsigned, thus
		 * something like "len-8" may give a *huge* number
		 */
		for (i = 0; i+8 < len; i++) {
			if (strcmp((char *)pkt+i, "blksize") == 0) {
				TftpBlkSize = (unsigned short)
					simple_strtoul((char *)pkt+i+8, NULL,
						       10);
				debug("Blocksize ack: %s, %d\n",
					(char *)pkt+i+8, TftpBlkSize);
			}
#ifdef CONFIG_TFTP_TSIZE
			if (strcmp((char *)pkt+i, "tsize") == 0) {
				TftpTsize = simple_strtoul((char *)pkt+i+6,
							   NULL, 10);
				debug("size = %s, %d\n",
					 (char *)pkt+i+6, TftpTsize);
			}
#endif
		}
#ifdef CONFIG_MCAST_TFTP
		parse_multicast_oack((char *)pkt, len-1);
		if ((Multicast) && (!MasterClient))
			TftpState = STATE_DATA;	/* passive.. */
		else
#endif
#ifdef CONFIG_CMD_TFTPPUT
		if (TftpWriting) {
			/* Get ready to send the first block */
			TftpState = STATE_DATA;
			TftpBlock++;
		}
#endif
		TftpSend(); /* Send ACK or first data block */
		break;
	case TFTP_DATA:
		if (len < 2)
			return;
		len -= 2;
		TftpBlock = ntohs(*(__be16 *)pkt);

		update_block_number();

		if (TftpState == STATE_SEND_RRQ)
			debug("Server did not acknowledge timeout option!\n");

		if (TftpState == STATE_SEND_RRQ || TftpState == STATE_OACK ||
		    TftpState == STATE_RECV_WRQ) {
			/* first block received */
			TftpState = STATE_DATA;
			TftpRemotePort = src;
			new_transfer();

#ifdef CONFIG_MCAST_TFTP
			if (Multicast) { /* start!=1 common if mcast */
				TftpLastBlock = TftpBlock - 1;
			} else
#endif
			if (TftpBlock != 1) {	/* Assertion */
				printf("\nTFTP error: "
				       "First block is not block 1 (%ld)\n"
				       "Starting again\n\n",
					TftpBlock);
				NetStartAgain();
				break;
			}
		}

		if (TftpBlock == TftpLastBlock) {
			/*
			 *	Same block again; ignore it.
			 */
			break;
		}

		TftpLastBlock = TftpBlock;
		TftpTimeoutCountMax = TIMEOUT_COUNT;
		NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);

		store_block(TftpBlock - 1, pkt + 2, len);

		/*
		 *	Acknowledge the block just received, which will prompt
		 *	the remote for the next one.
		 */
#ifdef CONFIG_MCAST_TFTP
		/* if I am the MasterClient, actively calculate what my next
		 * needed block is; else I'm passive; not ACKING
		 */
		if (Multicast) {
			if (len < TftpBlkSize)  {
				TftpEndingBlock = TftpBlock;
			} else if (MasterClient) {
				TftpBlock = PrevBitmapHole =
					ext2_find_next_zero_bit(
						Bitmap,
						(Mapsize*8),
						PrevBitmapHole);
				if (TftpBlock > ((Mapsize*8) - 1)) {
					printf("tftpfile too big\n");
					/* try to double it and retry */
					Mapsize <<= 1;
					mcast_cleanup();
					NetStartAgain();
					return;
				}
				TftpLastBlock = TftpBlock;
			}
		}
#endif
		TftpSend();

#ifdef CONFIG_MCAST_TFTP
		if (Multicast) {
			if (MasterClient && (TftpBlock >= TftpEndingBlock)) {
				puts("\nMulticast tftp done\n");
				mcast_cleanup();
				net_set_state(NETLOOP_SUCCESS);
			}
		} else
#endif
		if (len < TftpBlkSize)
			tftp_complete();
		break;

	case TFTP_ERROR:
		printf("\nTFTP error: '%s' (%d)\n",
		       pkt + 2, ntohs(*(__be16 *)pkt));

		switch (ntohs(*(__be16 *)pkt)) {
		case TFTP_ERR_FILE_NOT_FOUND:
		case TFTP_ERR_ACCESS_DENIED:
			puts("Not retrying...\n");
			eth_halt();
			net_set_state(NETLOOP_FAIL);
			break;
		case TFTP_ERR_UNDEFINED:
		case TFTP_ERR_DISK_FULL:
		case TFTP_ERR_UNEXPECTED_OPCODE:
		case TFTP_ERR_UNKNOWN_TRANSFER_ID:
		case TFTP_ERR_FILE_ALREADY_EXISTS:
		default:
			puts("Starting again\n\n");
#ifdef CONFIG_MCAST_TFTP
			mcast_cleanup();
#endif
			NetStartAgain();
			break;
		}
		break;
	}
}
Example #30
0
static void
NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
{
	int rlen;

	debug("%s\n", __func__);

	if (dest != NfsOurPort)
		return;

	switch (NfsState) {
	case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
		rpc_lookup_reply(PROG_MOUNT, pkt, len);
		NfsState = STATE_PRCLOOKUP_PROG_NFS_REQ;
		NfsSend();
		break;

	case STATE_PRCLOOKUP_PROG_NFS_REQ:
		rpc_lookup_reply(PROG_NFS, pkt, len);
		NfsState = STATE_MOUNT_REQ;
		NfsSend();
		break;

	case STATE_MOUNT_REQ:
		if (nfs_mount_reply(pkt, len)) {
			puts("*** ERROR: Cannot mount\n");
			/* just to be sure... */
			NfsState = STATE_UMOUNT_REQ;
			NfsSend();
		} else {
			NfsState = STATE_LOOKUP_REQ;
			NfsSend();
		}
		break;

	case STATE_UMOUNT_REQ:
		if (nfs_umountall_reply(pkt, len)) {
			puts("*** ERROR: Cannot umount\n");
			net_set_state(NETLOOP_FAIL);
		} else {
			puts("\ndone\n");
			net_set_state(nfs_download_state);
		}
		break;

	case STATE_LOOKUP_REQ:
		if (nfs_lookup_reply(pkt, len)) {
			puts("*** ERROR: File lookup fail\n");
			NfsState = STATE_UMOUNT_REQ;
			NfsSend();
		} else {
			NfsState = STATE_READ_REQ;
			nfs_offset = 0;
			nfs_len = NFS_READ_SIZE;
			NfsSend();
		}
		break;

	case STATE_READLINK_REQ:
		if (nfs_readlink_reply(pkt, len)) {
			puts("*** ERROR: Symlink fail\n");
			NfsState = STATE_UMOUNT_REQ;
			NfsSend();
		} else {
			debug("Symlink --> %s\n", nfs_path);
			nfs_filename = basename(nfs_path);
			nfs_path     = dirname(nfs_path);

			NfsState = STATE_MOUNT_REQ;
			NfsSend();
		}
		break;

	case STATE_READ_REQ:
		rlen = nfs_read_reply(pkt, len);
		NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
		if (rlen > 0) {
			nfs_offset += rlen;
			NfsSend();
		} else if ((rlen == -NFSERR_ISDIR) || (rlen == -NFSERR_INVAL)) {
			/* symbolic link */
			NfsState = STATE_READLINK_REQ;
			NfsSend();
		} else {
			if (!rlen)
				nfs_download_state = NETLOOP_SUCCESS;
			NfsState = STATE_UMOUNT_REQ;
			NfsSend();
		}
		break;
	}
}