#endif
/* Network loop state */
int NetState;
-#ifdef CONFIG_NET_MULTI
/* Tried all network devices */
int NetRestartWrap;
/* Network loop restarted */
static int NetRestarted;
/* At least one device configured */
static int NetDevExists;
-#endif
/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
/* default is without VLAN */
/* Current RX packet handler */
static rxhand_f *packetHandler;
+#ifdef CONFIG_CMD_TFTPPUT
+static rxhand_icmp_f *packet_icmp_handler; /* Current ICMP rx handler */
+#endif
/* Current timeout handler */
static thand_f *timeHandler;
/* Time base value */
/* THE transmit packet */
volatile uchar *NetTxPacket;
-static int net_check_prereq(proto_t protocol);
+static int net_check_prereq(enum proto_t protocol);
static int NetTryCount;
void ArpRequest(void)
{
- int i;
volatile uchar *pkt;
ARP_t *arp;
memcpy(&arp->ar_data[0], NetOurEther, 6);
/* source IP addr */
NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
- for (i = 10; i < 16; ++i) {
- /* dest ET addr = 0 */
- arp->ar_data[i] = 0;
- }
-
+ /* dest ET addr = 0 */
+ memset(&arp->ar_data[10], '\0', 6);
if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
(NetOurIP & NetOurSubnetMask)) {
if (NetOurGatewayIP == 0) {
}
}
-static void
-NetInitLoop(proto_t protocol)
+/*
+ * Check if autoload is enabled. If so, use either NFS or TFTP to download
+ * the boot file.
+ */
+void net_auto_load(void)
+{
+ const char *s = getenv("autoload");
+
+ if (s != NULL) {
+ if (*s == 'n') {
+ /*
+ * Just use BOOTP/RARP to configure system;
+ * Do not use TFTP to load the bootfile.
+ */
+ NetState = NETLOOP_SUCCESS;
+ return;
+ }
+#if defined(CONFIG_CMD_NFS)
+ if (strcmp(s, "NFS") == 0) {
+ /*
+ * Use NFS to load the bootfile.
+ */
+ NfsStart();
+ return;
+ }
+#endif
+ }
+ TftpStart(TFTPGET);
+}
+
+static void NetInitLoop(enum proto_t protocol)
{
static int env_changed_id;
bd_t *bd = gd->bd;
* Main network processing loop.
*/
-int
-NetLoop(proto_t protocol)
+int NetLoop(enum proto_t protocol)
{
bd_t *bd = gd->bd;
+ int ret = -1;
-#ifdef CONFIG_NET_MULTI
NetRestarted = 0;
NetDevExists = 0;
-#endif
/* XXX problem with bss workaround */
NetArpWaitPacketMAC = NULL;
NetArpWaitTxPacketSize = 0;
}
+ bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
eth_halt();
-#ifdef CONFIG_NET_MULTI
eth_set_current();
-#endif
if (eth_init(bd) < 0) {
eth_halt();
return -1;
}
restart:
-#ifdef CONFIG_NET_MULTI
memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
-#else
- eth_getenv_enetaddr("ethaddr", NetOurEther);
-#endif
NetState = NETLOOP_CONTINUE;
eth_halt();
return -1;
-#ifdef CONFIG_NET_MULTI
case 2:
/* network device not configured */
break;
-#endif /* CONFIG_NET_MULTI */
case 0:
-#ifdef CONFIG_NET_MULTI
NetDevExists = 1;
-#endif
+ NetBootFileXferSize = 0;
switch (protocol) {
- case TFTP:
+ case TFTPGET:
+#ifdef CONFIG_CMD_TFTPPUT
+ case TFTPPUT:
+#endif
/* always use ARP to get server ethernet address */
- TftpStart();
+ TftpStart(protocol);
break;
#ifdef CONFIG_CMD_TFTPSRV
case TFTPSRV:
break;
}
- NetBootFileXferSize = 0;
break;
}
if (ctrlc()) {
eth_halt();
puts("\nAbort\n");
- return -1;
+ goto done;
}
ArpTimeoutCheck();
switch (NetState) {
case NETLOOP_RESTART:
-#ifdef CONFIG_NET_MULTI
NetRestarted = 1;
-#endif
goto restart;
case NETLOOP_SUCCESS:
setenv("fileaddr", buf);
}
eth_halt();
- return NetBootFileXferSize;
+ ret = NetBootFileXferSize;
+ goto done;
case NETLOOP_FAIL:
- return -1;
+ goto done;
}
}
+
+done:
+#ifdef CONFIG_CMD_TFTPPUT
+ /* Clear out the handlers */
+ NetSetHandler(NULL);
+ net_set_icmp_handler(NULL);
+#endif
+ return ret;
}
/**********************************************************************/
NetTryCount++;
-#ifndef CONFIG_NET_MULTI
- NetSetTimeout(10000UL, startAgainTimeout);
- NetSetHandler(startAgainHandler);
-#else /* !CONFIG_NET_MULTI*/
eth_halt();
#if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
eth_try_another(!NetRestarted);
} else {
NetState = NETLOOP_RESTART;
}
-#endif /* CONFIG_NET_MULTI */
}
/**********************************************************************/
packetHandler = f;
}
+#ifdef CONFIG_CMD_TFTPPUT
+void net_set_icmp_handler(rxhand_icmp_f *f)
+{
+ packet_icmp_handler = f;
+}
+#endif
void
NetSetTimeout(ulong iv, thand_f *f)
*/
if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
- debug("sending ARP for %08lx\n", dest);
+ debug("sending ARP for %08x\n", dest);
NetArpWaitPacketIP = dest;
NetArpWaitPacketMAC = ether;
return 1; /* waiting */
}
- debug("sending UDP to %08lx/%pM\n", dest, ether);
+ debug("sending UDP to %08x/%pM\n", dest, ether);
pkt = (uchar *)NetTxPacket;
pkt += NetSetEther(pkt, ether, PROT_IP);
memcpy(mac, NetEtherNullAddr, 6);
- debug("sending ARP for %08lx\n", NetPingIP);
+ debug("sending ARP for %08x\n", NetPingIP);
NetArpWaitPacketIP = NetPingIP;
NetArpWaitPacketMAC = mac;
static void PingStart(void)
{
-#if defined(CONFIG_NET_MULTI)
printf("Using %s device\n", eth_get_name());
-#endif /* CONFIG_NET_MULTI */
NetSetTimeout(10000UL, PingTimeout);
NetSetHandler(PingHandler);
const uchar *t;
const ushort *ss;
ushort type, tlen;
- uchar applid;
ushort vlan, nvlan;
/* minimum size? */
if (tlen < 3)
goto pkt_short;
- applid = t[0];
ss = (const ushort *)(t + 1);
#ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE
- if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
+ if (t[0] == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
vlan = *ss;
#else
/* XXX will this work; dunno */
static void CDPStart(void)
{
-#if defined(CONFIG_NET_MULTI)
printf("Using %s device\n", eth_get_name());
-#endif
CDPSeq = 0;
CDPOK = 0;
}
#endif
+/**
+ * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
+ * drop others.
+ *
+ * @parma ip IP packet containing the ICMP
+ */
+static void receive_icmp(IP_t *ip, int len, IPaddr_t src_ip, Ethernet_t *et)
+{
+ ICMP_t *icmph = (ICMP_t *)&ip->udp_src;
+
+ switch (icmph->type) {
+ case ICMP_REDIRECT:
+ if (icmph->code != ICMP_REDIR_HOST)
+ return;
+ printf(" ICMP Host Redirect to %pI4 ",
+ &icmph->un.gateway);
+ break;
+#if defined(CONFIG_CMD_PING)
+ case ICMP_ECHO_REPLY:
+ /*
+ * IP header OK. Pass the packet to the
+ * current handler.
+ */
+ /*
+ * XXX point to ip packet - should this use
+ * packet_icmp_handler?
+ */
+ (*packetHandler)((uchar *)ip, 0, src_ip, 0, 0);
+ break;
+ case ICMP_ECHO_REQUEST:
+ debug("Got ICMP ECHO REQUEST, return %d bytes\n",
+ ETHER_HDR_SIZE + len);
+
+ memcpy(&et->et_dest[0], &et->et_src[0], 6);
+ memcpy(&et->et_src[0], NetOurEther, 6);
+
+ 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_NO_UDP >> 1);
+
+ icmph->type = ICMP_ECHO_REPLY;
+ icmph->checksum = 0;
+ icmph->checksum = ~NetCksum((uchar *)icmph,
+ (len - IP_HDR_SIZE_NO_UDP) >> 1);
+ (void) eth_send((uchar *)et,
+ ETHER_HDR_SIZE + len);
+ break;
+#endif
+ default:
+#ifdef CONFIG_CMD_TFTPPUT
+ if (packet_icmp_handler)
+ packet_icmp_handler(icmph->type, icmph->code,
+ ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src),
+ icmph->un.data, ntohs(ip->udp_len));
+#endif
+ break;
+ }
+}
+
void
NetReceive(volatile uchar *inpkt, int len)
{
* subnet. So this is probably a warning that your
* configuration might be wrong. But I'm not really
* sure if there aren't any other situations.
+ *
+ * Simon Glass <sjg@chromium.org>: We get an ICMP when
+ * we send a tftp packet to a dead connection, or when
+ * there is no server at the other end.
*/
if (ip->ip_p == IPPROTO_ICMP) {
- ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
-
- switch (icmph->type) {
- case ICMP_REDIRECT:
- if (icmph->code != ICMP_REDIR_HOST)
- return;
- printf(" ICMP Host Redirect to %pI4 ",
- &icmph->un.gateway);
- return;
-#if defined(CONFIG_CMD_PING)
- case ICMP_ECHO_REPLY:
- /*
- * IP header OK. Pass the packet to the
- * current handler.
- */
- /* XXX point to ip packet */
- (*packetHandler)((uchar *)ip, 0, src_ip, 0, 0);
- return;
- case ICMP_ECHO_REQUEST:
- debug("Got ICMP ECHO REQUEST, return %d bytes\n",
- ETHER_HDR_SIZE + len);
-
- memcpy(&et->et_dest[0], &et->et_src[0], 6);
- memcpy(&et->et_src[0], NetOurEther, 6);
-
- 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_NO_UDP >> 1);
-
- icmph->type = ICMP_ECHO_REPLY;
- icmph->checksum = 0;
- icmph->checksum = ~NetCksum((uchar *)icmph,
- (len - IP_HDR_SIZE_NO_UDP) >> 1);
- (void) eth_send((uchar *)et,
- ETHER_HDR_SIZE + len);
- return;
-#endif
- default:
- return;
- }
+ receive_icmp(ip, len, src_ip, et);
+ return;
} else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
return;
}
/**********************************************************************/
-static int net_check_prereq(proto_t protocol)
+static int net_check_prereq(enum proto_t protocol)
{
switch (protocol) {
/* Fall through */
#if defined(CONFIG_CMD_NFS)
case NFS:
#endif
- case TFTP:
+ case TFTPGET:
+ case TFTPPUT:
if (NetServerIP == 0) {
puts("*** ERROR: `serverip' not set\n");
return 1;
case CDP:
case DHCP:
if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
-#ifdef CONFIG_NET_MULTI
extern int eth_get_dev_index(void);
int num = eth_get_dev_index();
NetStartAgain();
return 2;
-#else
- puts("*** ERROR: `ethaddr' not set\n");
- return 1;
-#endif
}
/* Fall through */
default: