X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=net%2Fnet.c;h=8f55281f406dc0bf97e71b66b990795db353d7cc;hb=7f732099a6f70689f589c40b50f8387df0f3831a;hp=67df3c9a9979fe7ab4256fb60fcaa3a710d5d0fb;hpb=92895de9782e17172deca2ad0b6fff6d7425ed38;p=u-boot diff --git a/net/net.c b/net/net.c index 67df3c9a99..8f55281f40 100644 --- a/net/net.c +++ b/net/net.c @@ -169,14 +169,12 @@ uchar NetCDPAddr[6] = { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc }; #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 */ @@ -217,6 +215,9 @@ volatile uchar *NetRxPackets[PKTBUFSRX]; /* 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 */ @@ -226,7 +227,7 @@ static ulong timeDelta; /* 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; @@ -245,7 +246,6 @@ int NetArpWaitTry; void ArpRequest(void) { - int i; volatile uchar *pkt; ARP_t *arp; @@ -267,11 +267,8 @@ void ArpRequest(void) 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) { @@ -312,8 +309,37 @@ void ArpTimeoutCheck(void) } } -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; @@ -321,7 +347,8 @@ NetInitLoop(proto_t protocol) /* update only when the environment has changed */ if (env_changed_id != env_id) { - NetCopyIP(&NetOurIP, &bd->bi_ip_addr); + NetOurIP = getenv_IPaddr("ipaddr"); + NetCopyIP(&bd->bi_ip_addr, &NetOurIP); NetOurGatewayIP = getenv_IPaddr("gatewayip"); NetOurSubnetMask = getenv_IPaddr("netmask"); NetServerIP = getenv_IPaddr("serverip"); @@ -341,15 +368,13 @@ NetInitLoop(proto_t protocol) * 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; @@ -378,20 +403,14 @@ NetLoop(proto_t protocol) } 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; @@ -408,22 +427,26 @@ restart: 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: + TftpStartServer(); + break; +#endif #if defined(CONFIG_CMD_DHCP) case DHCP: BootpTry = 0; @@ -479,7 +502,6 @@ restart: break; } - NetBootFileXferSize = 0; break; } @@ -521,7 +543,7 @@ restart: if (ctrlc()) { eth_halt(); puts("\nAbort\n"); - return -1; + goto done; } ArpTimeoutCheck(); @@ -557,9 +579,7 @@ restart: switch (NetState) { case NETLOOP_RESTART: -#ifdef CONFIG_NET_MULTI NetRestarted = 1; -#endif goto restart; case NETLOOP_SUCCESS: @@ -575,12 +595,21 @@ restart: 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; } /**********************************************************************/ @@ -625,10 +654,6 @@ void NetStartAgain(void) 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); @@ -645,7 +670,6 @@ void NetStartAgain(void) } else { NetState = NETLOOP_RESTART; } -#endif /* CONFIG_NET_MULTI */ } /**********************************************************************/ @@ -659,6 +683,12 @@ NetSetHandler(rxhand_f *f) 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) @@ -811,9 +841,7 @@ PingHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, 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); @@ -1103,51 +1131,50 @@ CDPHandler(const uchar *pkt, unsigned len) tlen -= 4; switch (type) { - case CDP_DEVICE_ID_TLV: - break; - case CDP_ADDRESS_TLV: - break; - case CDP_PORT_ID_TLV: - break; - case CDP_CAPABILITIES_TLV: - break; - case CDP_VERSION_TLV: - break; - case CDP_PLATFORM_TLV: - break; - case CDP_NATIVE_VLAN_TLV: - nvlan = *ss; - break; - case CDP_APPLIANCE_VLAN_TLV: - t = (const uchar *)ss; - while (tlen > 0) { - if (tlen < 3) - goto pkt_short; + case CDP_DEVICE_ID_TLV: + break; + case CDP_ADDRESS_TLV: + break; + case CDP_PORT_ID_TLV: + break; + case CDP_CAPABILITIES_TLV: + break; + case CDP_VERSION_TLV: + break; + case CDP_PLATFORM_TLV: + break; + case CDP_NATIVE_VLAN_TLV: + nvlan = *ss; + break; + case CDP_APPLIANCE_VLAN_TLV: + t = (const uchar *)ss; + while (tlen > 0) { + if (tlen < 3) + goto pkt_short; - applid = t[0]; - ss = (const ushort *)(t + 1); + applid = t[0]; + ss = (const ushort *)(t + 1); #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE - if (applid == - CONFIG_CDP_APPLIANCE_VLAN_TYPE) - vlan = *ss; + if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE) + vlan = *ss; #else - /* XXX will this work; dunno */ - vlan = ntohs(*ss); + /* XXX will this work; dunno */ + vlan = ntohs(*ss); #endif - t += 3; tlen -= 3; - } - break; - case CDP_TRIGGER_TLV: - break; - case CDP_POWER_CONSUMPTION_TLV: - break; - case CDP_SYSNAME_TLV: - break; - case CDP_SYSOBJECT_TLV: - break; - case CDP_MANAGEMENT_ADDRESS_TLV: - break; + t += 3; tlen -= 3; + } + break; + case CDP_TRIGGER_TLV: + break; + case CDP_POWER_CONSUMPTION_TLV: + break; + case CDP_SYSNAME_TLV: + break; + case CDP_SYSOBJECT_TLV: + break; + case CDP_MANAGEMENT_ADDRESS_TLV: + break; } } @@ -1164,9 +1191,7 @@ CDPHandler(const uchar *pkt, unsigned len) static void CDPStart(void) { -#if defined(CONFIG_NET_MULTI) printf("Using %s device\n", eth_get_name()); -#endif CDPSeq = 0; CDPOK = 0; @@ -1352,6 +1377,68 @@ static inline IP_t *NetDefragment(IP_t *ip, int *lenp) } #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) { @@ -1608,7 +1695,7 @@ NetReceive(volatile uchar *inpkt, int len) #ifdef CONFIG_MCAST_TFTP if (Mcast_addr != tmp) #endif - return; + return; } /* Read source IP address for later use */ src_ip = NetReadIP(&ip->ip_src); @@ -1617,7 +1704,8 @@ NetReceive(volatile uchar *inpkt, int len) * a fragment, and either the complete packet or NULL if * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL) */ - if (!(ip = NetDefragment(ip, &len))) + ip = NetDefragment(ip, &len); + if (!ip) return; /* * watch for ICMP host redirects @@ -1635,51 +1723,14 @@ 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 : 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; } @@ -1748,7 +1799,7 @@ NetReceive(volatile uchar *inpkt, int len) /**********************************************************************/ -static int net_check_prereq(proto_t protocol) +static int net_check_prereq(enum proto_t protocol) { switch (protocol) { /* Fall through */ @@ -1779,7 +1830,8 @@ static int net_check_prereq(proto_t protocol) #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; @@ -1791,6 +1843,7 @@ common: /* Fall through */ case NETCONS: + case TFTPSRV: if (NetOurIP == 0) { puts("*** ERROR: `ipaddr' not set\n"); return 1; @@ -1804,7 +1857,6 @@ common: 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(); @@ -1823,10 +1875,6 @@ common: NetStartAgain(); return 2; -#else - puts("*** ERROR: `ethaddr' not set\n"); - return 1; -#endif } /* Fall through */ default: @@ -1883,7 +1931,7 @@ NetSetEther(volatile uchar *xet, uchar * addr, uint prot) memcpy(et->et_dest, addr, 6); memcpy(et->et_src, NetOurEther, 6); if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) { - et->et_protlen = htons(prot); + et->et_protlen = htons(prot); return ETHER_HDR_SIZE; } else { VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;