From: wdenk Date: Thu, 28 Dec 2000 11:02:28 +0000 (+0000) Subject: Reworking of TFTP code; use ARP request to get TFTP server's X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=a9194fa95d9c9a1a0feda1a16637639b6cfed215;p=users%2Frw%2Fppcboot.git Reworking of TFTP code; use ARP request to get TFTP server's ethernet address --- diff --git a/CHANGELOG b/CHANGELOG index 77ce92e..bec3af0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -58,9 +58,40 @@ To do: (and it uses default address). ====================================================================== -Modifications since 0.7.0: +Modifications for 0.7.1: ====================================================================== +* TFTP now uses ARP to get the ethernet address of the TFTP server + (until now the TFTP request packet used the ethernet broadcast + address which confused some [broken or badly configured?] switches) + +* You can now set the environment variables "loadaddr" and/or + "bootfile" to provide default settings for commands like "tftpboot" + +* "tftpboot" now supports more command formats; you can omit both the + load address and/or the boot file name. If you omit the load + address, but want to specify a boot file name, you have to put it + between apostrophes; the following commands are all equivalent: + + tftp 200000 /tftpboot/pImage.new + + setenv loadaddr 200000 ; tftp "/tftpboot/pImage.new" + + setenv loadaddr 200000 ; setenv bootfile /tftpboot/pImage.new ; tftp + +* You can now explicitely request the IP address based default file + name by specifying an empty load file name: + + tftp "" + or + setenv bootfile "" ; tftp + +* There is a new environment variable "autoload"; if set to a string + beginning with 'n' ("no autoload") the "bootp" command will issue a + BOOTP request to detremine the system configuration parameters from + the BOOTP server, but it will not automatically start TFTP to + download the boot file + * Added support for PPC405CR (Stefan Roese) * Fixes in environment code; better detection of CRC errors; fixes diff --git a/README b/README index 12bc964..61f21f7 100644 --- a/README +++ b/README @@ -375,7 +375,7 @@ following configurations: beginning of flash memory; for instance, with bottom boot type flash chips the second sector can be used: the offset for this sector is given here. - + CFG_ENV_OFFSET is used relative to CFG_FLASH_BASE. - CFG_ENV_ADDR: @@ -628,19 +628,27 @@ environment is erased by accident, a default environment is provided. Some configuration options can be set using Environment Variables: -bootdelay - see CONFIG_BOOTDELAY -bootcmd - see CONFIG_BOOTCOMMAND -baudrate - see CONFIG_BAUDRATE -bootargs - Boot arguments when booting an RTOS image -loads_echo - see CONFIG_LOADS_ECHO -ipaddr - IP address; needed for tftpboot command -serverip - TFTP server IP address; needed for tftpboot command -autostart - if set to "yes", an image loaded using the "bootp", - "rarpboot" or "tftpboot" commands will be - automatically started (by internally calling - "bootm") - -initrd_high - restrict positioning of initrd images: + baudrate - see CONFIG_BAUDRATE + + bootdelay - see CONFIG_BOOTDELAY + + bootcmd - see CONFIG_BOOTCOMMAND + + bootargs - Boot arguments when booting an RTOS image + + bootfile - Name of the image to load with TFTP + + autoload - if set to "no" (any string beginning with 'n'), + "bootp" will just load perform a lookup of the + configuration from the BOOTP server, but not try to + load any image using TFTP + + autostart - if set to "yes", an image loaded using the "bootp", + "rarpboot", "tftpboot" or "diskboot" commands will + be automatically started (by internally calling + "bootm") + + initrd_high - restrict positioning of initrd images: If this variable is not set, initrd images will be copied to the highest possible address in RAM; this is usually what you want since it allows for @@ -660,20 +668,45 @@ initrd_high - restrict positioning of initrd images: 12 MB as well - this can be done with setenv initrd_high 00c00000 - + + ipaddr - IP address; needed for tftpboot command + + loadaddr - Default load address for commands like "bootp", + "rarpboot", "tftpboot" or "diskboot" + + loads_echo - see CONFIG_LOADS_ECHO + + serverip - TFTP server IP address; needed for tftpboot command + + +The following environment variables may be used and automatically +updated by the network boot commands ("bootp" and "rarpboot"), +depending the information provided by your boot server: + + bootfile - see above + dnsip - IP address of your Domain Name Server + gatewayip - IP address of the Gateway (Router) to use + hostname - Target hostname + ipaddr - see above + netmask - Subnet Mask + rootpath - Pathname of the root filesystem on the NFS server + serverip - see above + There are two special Environment Variables: -serial# - contains hardware identification information such + serial# - contains hardware identification information such as type string and/or serial number -ethaddr - Ethernet address + ethaddr - Ethernet address These variables can be set only once (usually during manufacturing of the board). PPCBoot refuses to delete or overwrite these variables once they have been set once. -Please note that changes to configuration parameters usually take -only effect after the next boot (yes, that's just like Windoze :-). + +Please note that changes to some configuration parameters (like +console baudrate) may take only effect after the next boot (yes, +that's just like Windoze :-). diff --git a/common/board.c b/common/board.c index 22f06b0..7ce6770 100644 --- a/common/board.c +++ b/common/board.c @@ -35,6 +35,9 @@ #ifdef CONFIG_STATUS_LED #include #endif +#if (CONFIG_COMMANDS & CFG_CMD_NET) +#include +#endif #include static char *failed = "*** failed ***\n"; @@ -370,6 +373,7 @@ board_init_f (ulong bootflag) void board_init_r (bd_t *bd, ulong dest_addr) { + char *s; cmd_tbl_t *cmdtp; ulong flash_size; ulong reloc_off = dest_addr - CFG_MONITOR_BASE; @@ -508,6 +512,16 @@ void board_init_r (bd_t *bd, ulong dest_addr) bd->bi_mon_fnc->install_hdlr = irq_install_handler; bd->bi_mon_fnc->free_hdlr = irq_free_handler; + /* Initialize from environment */ + if ((s = getenv("loadaddr")) != NULL) { + load_addr = simple_strtoul(s, NULL, 16); + } +#if (CONFIG_COMMANDS & CFG_CMD_NET) + if ((s = getenv("bootfile")) != NULL) { + copy_filename (BootFile, s, sizeof(BootFile)); + } +#endif /* CFG_CMD_NET */ + /* Initialize other board modules */ #ifdef CONFIG_PCI_PNP /* diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 693f8de..6213c5a 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -28,6 +28,7 @@ #include #include #include +#include #if (CONFIG_COMMANDS & CFG_CMD_LOADS) @@ -42,7 +43,6 @@ static int do_echo = 1; void do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) { int i; - ulong ip = bd->bi_ip_addr; char buf[32]; printf (" memstart = 0x%08lx\n", bd->bi_memstart ); @@ -70,11 +70,7 @@ void do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #ifdef CONFIG_HERMES printf (" ethspeed = %6d MHz\n", bd->bi_ethspeed); #endif - printf ("\n IP addr ="); - for (i=0; i<4; ++i) { - printf ("%c%ld", i ? '.' : ' ', (ip >> 24) & 0xFF); - ip <<= 8; - } + printf ("\n IP addr ="); print_IPaddr (bd->bi_ip_addr); printf ("\n baudrate = %6ld bps\n", bd->bi_baudrate ); printf (" getc = 0x%08lx\n",(ulong)bd->bi_mon_fnc->getc); printf (" tstc = 0x%08lx\n",(ulong)bd->bi_mon_fnc->tstc); diff --git a/common/cmd_net.c b/common/cmd_net.c index aafe673..2819156 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -55,12 +55,12 @@ static void netboot_update_env(void) char tmp[12] ; if (NetOurGatewayIP) { - NetIPaddr (NetOurGatewayIP, tmp); + ip_to_string (NetOurGatewayIP, tmp); setenv("gatewayip", tmp); } if (NetOurSubnetMask) { - NetIPaddr (NetOurSubnetMask, tmp); + ip_to_string (NetOurSubnetMask, tmp); setenv("netmask", tmp); } @@ -71,17 +71,17 @@ static void netboot_update_env(void) setenv("rootpath", NetOurRootPath); if (NetOurIP) { - NetIPaddr (NetOurIP, tmp); + ip_to_string (NetOurIP, tmp); setenv("ipaddr", tmp); } if (NetServerIP) { - NetIPaddr (NetServerIP, tmp); + ip_to_string (NetServerIP, tmp); setenv("serverip", tmp); } if (NetOurDNSIP) { - NetIPaddr (NetOurDNSIP, tmp); + ip_to_string (NetOurDNSIP, tmp); setenv("dnsip", tmp); } } @@ -89,27 +89,37 @@ static void netboot_update_env(void) static void netboot_common (int proto, cmd_tbl_t *cmdtp, bd_t *bd, int argc, char *argv[]) { - ulong addr; - int rc; char *s; switch (argc) { - case 1: rc = NetLoop(bd, proto, "", -1); + case 1: break; - case 2: addr = simple_strtoul(argv[1], NULL, 16); - rc = NetLoop(bd, proto, "", addr); + + case 2: /* only one arg - accept two forms: + * just load address, or just boot file name. + * The latter form must be written "filename" here. + */ + if (argv[1][0] == '"') { /* just boot filename */ + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } else { /* load address */ + load_addr = simple_strtoul(argv[1], NULL, 16); + } break; - case 3: addr = simple_strtoul(argv[1], NULL, 16); - rc = NetLoop(bd, proto, argv[2], addr); + + case 3: load_addr = simple_strtoul(argv[1], NULL, 16); + copy_filename (BootFile, argv[2], sizeof(BootFile)); + break; + default: printf ("Usage:\n%s\n", cmdtp->usage); return; } - if (rc == 0) - return; - else - netboot_update_env(); + if (NetLoop(bd, proto) == 0) + return; + + /* NetLoop ok, update environment */ + netboot_update_env(); /* Loading ok, check if we should attempt an auto-start */ if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) { diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 2f90192..2ea1f52 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -28,6 +28,9 @@ #include #include #include +#if (CONFIG_COMMANDS & CFG_CMD_NET) +#include +#endif /************************************************************************ * @@ -444,8 +447,9 @@ void _do_setenv (bd_t *bd, int flag, int argc, char *argv[]) /* Update CRC */ env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); - /* Changes of the Ethernet or IP address should be reflected - * in the board info structure. + /* + * Some variables should be updated when the corresponding + * entry in the enviornment is changed */ if (strcmp(argv[1],"ethaddr") == 0) { @@ -468,7 +472,18 @@ void _do_setenv (bd_t *bd, int flag, int argc, char *argv[]) bd->bi_ip_addr |= (val & 0xFF); if (s) s = (*e) ? e+1 : e; } + return; + } + if (strcmp(argv[1],"loadaddr") == 0) { + load_addr = simple_strtoul(argv[2], NULL, 16); + return; + } +#if (CONFIG_COMMANDS & CFG_CMD_NET) + if (strcmp(argv[1],"bootfile") == 0) { + copy_filename (BootFile, argv[2], sizeof(BootFile)); + return; } +#endif /* CFG_CMD_NET */ } void setenv (char *varname, char *varvalue) diff --git a/include/config_Sandpoint8240.h b/include/config_Sandpoint8240.h index 44bc77e..580fe43 100644 --- a/include/config_Sandpoint8240.h +++ b/include/config_Sandpoint8240.h @@ -62,8 +62,6 @@ #endif #define CFG_MALLOC_LEN (512 << 10) /* Reserve 512 kB for malloc() */ -#define CFG_TFTP_LOADADDR 0x00100000 /* default load address */ - #define CFG_MEMTEST_START 0x00000000 /* memtest works on */ #define CFG_MEMTEST_END 0x02000000 /* 0 ... 32 MB in DRAM */ diff --git a/include/net.h b/include/net.h index 685e370..5243aaa 100644 --- a/include/net.h +++ b/include/net.h @@ -194,10 +194,13 @@ extern int NetState; /* Network loop state */ #define NETLOOP_FAIL 4 -typedef enum { BOOTP, TFTP, RARP } proto_t; +typedef enum { BOOTP, RARP, ARP, TFTP } proto_t; + +/* from net/net.c */ +extern char BootFile[128]; /* Boot File name */ /* Initialize the network adapter */ -extern int NetLoop(bd_t *bis, proto_t protocol, char *fileName, ulong loadAdr); +extern int NetLoop(bd_t *bis, proto_t protocol); /* Shutdown adapters and cleanup */ extern void NetStop(void); @@ -229,10 +232,13 @@ extern void NetSendPacket(volatile uchar *, int); extern void NetReceive(volatile uchar *, int); /* Print an IP address on the console */ -extern void NetPrintIPaddr(IPaddr_t); +extern void print_IPaddr (IPaddr_t); /* Convert a IP address to a string */ -extern void NetIPaddr (IPaddr_t x, char *s); +extern void ip_to_string (IPaddr_t x, char *s); + +/* copy a filename (allow for "..." notation, limit length) */ +extern void copy_filename (uchar *dst, uchar *src, int size); /**********************************************************************/ diff --git a/include/version.h b/include/version.h index f6f4bcb..00a2f09 100644 --- a/include/version.h +++ b/include/version.h @@ -24,6 +24,6 @@ #ifndef __VERSION_H__ #define __VERSION_H__ -#define PPCBOOT_VERSION "ppcboot 0.7.0" +#define PPCBOOT_VERSION "ppcboot 0.7.1" #endif /* __VERSION_H__ */ diff --git a/net/Makefile b/net/Makefile index e0d3446..a87b81b 100644 --- a/net/Makefile +++ b/net/Makefile @@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk LIB = libnet.a -OBJS = net.o tftp.o bootp.o rarp.o +OBJS = net.o tftp.o bootp.o rarp.o arp.o all: $(LIB) $(LIB): $(START) $(OBJS) diff --git a/net/arp.c b/net/arp.c new file mode 100644 index 0000000..c9fffdb --- /dev/null +++ b/net/arp.c @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include "net.h" +#include "bootp.h" +#include "tftp.h" +#include "arp.h" + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +#define TIMEOUT 5 /* Seconds before trying ARP again */ + +static void ArpHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len); +static void ArpTimeout(void); + +int ArpTry; + +/* + * Handle a ARP received packet. + */ +static void +ArpHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len) +{ +#ifdef DEBUG + printf("Got good ARP - start TFTP\n"); +#endif + TftpStart (); +} + + +/* + * Timeout on ARP request. Try again, forever. + */ +static void +ArpTimeout(void) +{ + ArpRequest (); +} + + +void +ArpRequest (void) +{ + int i; + volatile uchar *pkt; + ARP_t * arp; + + printf("ARP broadcast %d\n", ++ArpTry); + pkt = NetTxPacket; + + NetSetEther(pkt, NetBcastAddr, PROT_ARP); + pkt += ETHER_HDR_SIZE; + + arp = (ARP_t *)pkt; + + arp->ar_hrd = ARP_ETHER; + arp->ar_pro = PROT_IP; + arp->ar_hln = 6; + arp->ar_pln = 4; + arp->ar_op = ARPOP_REQUEST; + NetCopyEther(&arp->ar_data[0], NetOurEther); /* source ET addr */ + *(IPaddr_t *)(&arp->ar_data[6]) = NetOurIP; /* source IP addr */ + for (i=10; i<16; ++i) { + arp->ar_data[i] = 0; /* dest ET addr = 0 */ + } + *(IPaddr_t *)(&arp->ar_data[16]) = NetServerIP; /* dest IP addr */ + + NetSendPacket(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE); + + NetSetTimeout(TIMEOUT * CFG_HZ, ArpTimeout); + NetSetHandler(ArpHandler); +} + +#endif /* CFG_CMD_NET */ diff --git a/net/arp.h b/net/arp.h new file mode 100644 index 0000000..b835334 --- /dev/null +++ b/net/arp.h @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#ifndef __ARP_H__ +#define __ARP_H__ + +/**********************************************************************/ +/* + * Global functions and variables. + */ + +extern int ArpTry; + +extern void ArpRequest (void); /* Send a ARP request */ + +/**********************************************************************/ + +#endif /* __ARP_H__ */ + diff --git a/net/bootp.c b/net/bootp.c index 30a9e04..ba83d7c 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -14,6 +14,7 @@ #include "net.h" #include "bootp.h" #include "tftp.h" +#include "arp.h" #ifdef CONFIG_STATUS_LED #include #endif @@ -28,9 +29,7 @@ #define PORT_BOOTPC 68 /* BOOTP client UDP port */ ulong BootpID; -char BootFile[128]; int BootpTry; -static ulong lAddr; static int BootpExtended (u8 *e); @@ -144,13 +143,13 @@ static void BootpVendorProcess(u8 *ext, int size) printf("[BOOTP] Received fields: \n"); if (NetOurSubnetMask) { puts ("NetOurSubnetMask : "); - NetPrintIPaddr (NetOurSubnetMask); + print_IPaddr (NetOurSubnetMask); putc('\n'); } if (NetOurGatewaysIP[0]) { puts ("NetOurGatewaysIP : "); - NetPrintIPaddr (NetOurGatewaysIP[0]); + print_IPaddr (NetOurGatewaysIP[0]); putc('\n'); } @@ -178,7 +177,8 @@ static void BootpVendorProcess(u8 *ext, int size) static void BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) { - Bootp_t * bp; + Bootp_t *bp; + char *s; #ifdef DEBUG printf("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n", @@ -209,7 +209,10 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) NetOurIP = bp->bp_yiaddr; NetServerIP = bp->bp_siaddr; NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src); - memcpy(BootFile, bp->bp_file, sizeof bp->bp_file); + copy_filename (BootFile, bp->bp_file, sizeof(BootFile)); + + /* Propagate to environment (only for BOOTP!) */ + setenv ("bootfile", BootFile); /* Retrieve extended informations (we must parse the vendor area) */ if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC) @@ -221,7 +224,19 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) printf("Got good BOOTP\n"); #endif /* DEBUG */ - TftpStart(lAddr); + if (((s = getenv("autoload")) != NULL) && (*s == 'n')) { + /* + * Just use BOOTP to configure system; + * Do not use TFTP to load the bootfile. + */ + NetState = NETLOOP_SUCCESS; + return; + } + + /* Send ARP request to get TFTP server ethernet address. + * This automagically starts TFTP, too. + */ + ArpRequest(); } @@ -231,7 +246,7 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) static void BootpTimeout(void) { - BootpRequest(BootFile, lAddr); + BootpRequest (); } /* @@ -296,14 +311,12 @@ static int BootpExtended (u8 *e) } void -BootpRequest(char *fileName, ulong loadAdr) +BootpRequest (void) { volatile uchar *pkt; Bootp_t *bp; int ext_len; - lAddr = loadAdr; - printf("BOOTP broadcast %d\n", ++BootpTry); pkt = NetTxPacket; @@ -324,7 +337,7 @@ BootpRequest(char *fileName, ulong loadAdr) bp->bp_siaddr = 0; bp->bp_giaddr = 0; NetCopyEther(bp->bp_chaddr, NetOurEther); - strcpy(bp->bp_file, fileName); + copy_filename (bp->bp_file, BootFile, sizeof(bp->bp_file)); /* Request additional information from the BOOTP server */ ext_len = BootpExtended (bp->bp_vend) - sizeof(bp->bp_vend); @@ -332,9 +345,6 @@ BootpRequest(char *fileName, ulong loadAdr) ext_len = 0; } - /* store boot file name for repetitions in case of bootp timeout */ - strcpy(BootFile, fileName); - /* * Bootp ID is the lower 4 bytes of our ethernet address * plus the current time in HZ. diff --git a/net/bootp.h b/net/bootp.h index 0e7dc18..cf9a77e 100644 --- a/net/bootp.h +++ b/net/bootp.h @@ -55,7 +55,7 @@ extern char BootFile[128]; /* Boot file name */ extern int BootpTry; /* Send a BOOTP request */ -extern void BootpRequest(char *fileName, ulong loadAdr); +extern void BootpRequest (void); /**********************************************************************/ diff --git a/net/net.c b/net/net.c index 9fd82df..e841649 100644 --- a/net/net.c +++ b/net/net.c @@ -5,20 +5,67 @@ * (See License) * Copyright 2000 Roland Borde * Copyright 2000 Paolo Scaffardi + * Copyright 2000 Wolfgang Denk * * History * 9/16/00 bor adapted to TQM823L/STK8xxL board, RARP/TFTP boot added */ +/* + * General Desription: + * + * The user interface supports commands for BOOTP, RARP, and TFTP. + * Also, we support ARP internally. Depending on available data, + * these interact as follows: + * + * BOOTP: + * + * Prerequisites: - own ethernet address + * We want: - own IP address + * - TFTP server IP address + * - name of bootfile + * Next step: ARP + * + * RARP: + * + * Prerequisites: - own ethernet address + * We want: - own IP address + * - TFTP server IP address + * Next step: ARP + * + * ARP: + * + * Prerequisites: - own ethernet address + * - own IP address + * - TFTP server IP address + * We want: - TFTP server ethernet address + * Next step: TFTP + * + * TFTP: + * + * Prerequisites: - own ethernet address + * - own IP address + * - TFTP server IP address + * - TFTP server ethernet address + * - name of bootfile (if unknown, we use a default name + * derived from our own IP address) + * We want: - load the boot file + * Next step: none + */ + + #include #include #include "net.h" #include "bootp.h" #include "tftp.h" #include "rarp.h" +#include "arp.h" #if (CONFIG_COMMANDS & CFG_CMD_NET) +#undef ET_DEBUG + /** BOOTP EXTENTIONS **/ IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */ @@ -32,7 +79,8 @@ ushort NetBootFileSize=0; /* Out bootfile size in blocks */ /** END OF BOOTP EXTENTIONS **/ uchar NetOurEther[6]; /* Our ethernet address */ -uchar NetServerEther[6]; /* Boot server enet address */ +uchar NetServerEther[6] = /* Boot server enet address */ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */ IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */ volatile uchar *NetRxPkt; /* Current receive packet */ @@ -42,6 +90,8 @@ uchar NetBcastAddr[6] = /* Ethernet bcast address */ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; int NetState; /* Network loop state */ +char BootFile[128]; /* Boot File name */ + volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE + PKTALIGN]; volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */ @@ -51,6 +101,7 @@ static thand_f *timeHandler; /* Current timeout handler */ static ulong timeValue; /* Current timeout value */ volatile uchar *NetTxPacket = 0; /* THE transmit packet */ +static int net_check_prereq (proto_t protocol); /**********************************************************************/ /* @@ -58,10 +109,10 @@ volatile uchar *NetTxPacket = 0; /* THE transmit packet */ */ int -NetLoop(bd_t *bis, proto_t protocol, char *fileName, ulong loadAdr) +NetLoop(bd_t *bis, proto_t protocol) { - char *s, *e; - ulong reg; + char *s, *e; + ulong reg; if (!NetTxPacket) { int i; @@ -81,14 +132,6 @@ NetLoop(bd_t *bis, proto_t protocol, char *fileName, ulong loadAdr) NetCopyEther(NetOurEther, bis->bi_enetaddr); - /* initialize our IP adr to 0 in order to accept ANY IP addr - assigned to us by the BOOTP server - */ - - NetOurIP = 0; - BootpTry = 0; - RarpTry = 0; - restart: NetState = NETLOOP_CONTINUE; @@ -97,11 +140,8 @@ restart: * here on, this code is a state machine driven by received * packets and timer events. */ - switch (protocol) { - case TFTP: - NetCopyEther(NetServerEther, NetBcastAddr); - strcpy(BootFile, fileName); + if (protocol == TFTP) { /* TFTP */ NetOurIP = bis->bi_ip_addr; NetServerIP = 0; s = getenv ("serverip"); @@ -111,24 +151,35 @@ restart: NetServerIP |= (val & 0xFF); if (s) s = (*e) ? e+1 : e; } - if (NetOurIP & NetServerIP) { - TftpStart(loadAdr); - } else { - printf ("\n" - "Environment variables `ipaddr' and `serverip'" - " needed for this command\n" - ); + + if (net_check_prereq (protocol) != 0) { return 0; } - break; - case RARP: - RarpRequest(fileName, loadAdr); - break; + /* always use ARP to get server ethernet address */ + ArpTry = 0; + ArpRequest (); - default: - BootpRequest(fileName, loadAdr); - break; + } else { /* BOOTP or RARP */ + + /* + * initialize our IP addr to 0 in order to accept ANY + * IP addr assigned to us by the BOOTP / RARP server + */ + NetOurIP = 0; + NetServerIP = 0; + + if (net_check_prereq (protocol) != 0) { + return 0; + } + + if (protocol == BOOTP) { + BootpTry = 0; + BootpRequest (); + } else { + RarpTry = 0; + RarpRequest (); + } } @@ -147,6 +198,7 @@ restart: * Check the keyboard for a Key. Quit if we get one. */ if (tstc()) { + (void) getc(); printf("\nAbort\n"); return 0; } @@ -199,8 +251,6 @@ startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) void NetStartAgain(void) { - NetServerIP = 0; - NetOurIP = 0; NetSetTimeout(10 * CFG_HZ, startAgainTimeout); NetSetHandler(startAgainHandler); } @@ -272,9 +322,13 @@ NetReceive(volatile uchar * pkt, int len) case PROT_ARP: /* - * The only type of ARP packet we deal with is a request - * for our ethernet address. We can only respond if we - * know our IP address. + * 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 ethernet address; so if we + * receive such a packet, we set the server + * ethernet address */ #ifdef ET_DEBUG printf("Got ARP\n"); @@ -284,31 +338,51 @@ NetReceive(volatile uchar * pkt, int len) printf("bad length %d < %d\n", len, ARP_HDR_SIZE); return; } - if (SWAP16(arp->ar_op) != ARPOP_REQUEST) + if (SWAP16(arp->ar_hrd) != ARP_ETHER) { return; - if (SWAP16(arp->ar_hrd) != ARP_ETHER) - return; - if (SWAP16(arp->ar_pro) != PROT_IP) + } + if (SWAP16(arp->ar_pro) != PROT_IP) { return; - if (arp->ar_hln != 6) + } + if (arp->ar_hln != 6) { return; - if (arp->ar_pln != 4) + } + if (arp->ar_pln != 4) { return; + } if (NetOurIP == 0 || *((IPaddr_t *)&arp->ar_data[16]) != NetOurIP) { return; } - NetSetEther((uchar *)et, et->et_src, PROT_ARP); - arp->ar_op = SWAP16(ARPOP_REPLY); - NetCopyEther(&arp->ar_data[10], &arp->ar_data[0]); - NetCopyEther(&arp->ar_data[0], NetOurEther); - *(IPaddr_t *)(&arp->ar_data[16]) = - *(IPaddr_t *)(&arp->ar_data[6]); - *(IPaddr_t *)(&arp->ar_data[6]) = NetOurIP; - NetSendPacket((uchar *)et, ((uchar *)arp - pkt) + ARP_HDR_SIZE); - break; + switch (SWAP16(arp->ar_op)) { + case ARPOP_REQUEST: /* reply with our IP address */ +#ifdef ET_DEBUG + printf("Got ARP REQUEST, return our IP\n"); +#endif + NetSetEther((uchar *)et, et->et_src, PROT_ARP); + arp->ar_op = SWAP16(ARPOP_REPLY); + NetCopyEther(&arp->ar_data[10], &arp->ar_data[0]); + NetCopyEther(&arp->ar_data[0], NetOurEther); + *(IPaddr_t *)(&arp->ar_data[16]) = + *(IPaddr_t *)(&arp->ar_data[6]); + *(IPaddr_t *)(&arp->ar_data[6]) = NetOurIP; + NetSendPacket((uchar *)et,((uchar *)arp-pkt)+ARP_HDR_SIZE); + return; + case ARPOP_REPLY: /* set TFTP server eth addr */ +#ifdef ET_DEBUG + printf("Got ARP REPLY, set TFTP server eth addr\n"); +#endif + NetCopyEther(NetServerEther, &arp->ar_data[0]); + (*packetHandler)(0,0,0,0); /* start TFTP */ + return; + default: +#ifdef ET_DEBUG + printf("Unexpected ARP opcode 0x%x\n", SWAP16(arp->ar_op)); +#endif + return; + } case PROT_RARP: #ifdef ET_DEBUG @@ -388,6 +462,36 @@ NetReceive(volatile uchar * pkt, int len) /**********************************************************************/ +static int net_check_prereq (proto_t protocol) +{ + switch (protocol) { + case ARP: /* nothing to do */ + break; + + case TFTP: + if (NetServerIP == 0) { + puts ("*** ERROR: `serverip' not set\n"); + return (1); + } + + if (NetOurIP == 0) { + puts ("*** ERROR: `ipaddr' not set\n"); + return (1); + } + /* Fall through */ + + case RARP: + case BOOTP: + if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) { + puts ("*** ERROR: `ethaddr' not set\n"); + return (1); + } + /* Fall through */ + } + return (0); /* OK */ +} +/**********************************************************************/ + int NetCksumOk(uchar * ptr, int len) { @@ -464,8 +568,21 @@ NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len) ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); } +void copy_filename (uchar *dst, uchar *src, int size) +{ + if (*src && (*src == '"')) { + ++src; + } + + while ((--size > 0) && *src && (*src != '"')) { + *dst++ = *src++; + } + *dst = '\0'; +} -void NetIPaddr (IPaddr_t x, char *s) +#endif /* CFG_CMD_NET */ + +void ip_to_string (IPaddr_t x, char *s) { x = SWAP32(x); sprintf (s,"%d.%d.%d.%d", @@ -476,13 +593,11 @@ void NetIPaddr (IPaddr_t x, char *s) ); } -void NetPrintIPaddr(IPaddr_t x) +void print_IPaddr (IPaddr_t x) { char tmp[12]; - NetIPaddr(x, tmp); + ip_to_string(x, tmp); puts(tmp); } - -#endif /* CFG_CMD_NET */ diff --git a/net/rarp.c b/net/rarp.c index 8b4cfa7..cb43baa 100644 --- a/net/rarp.c +++ b/net/rarp.c @@ -34,7 +34,6 @@ int RarpTry; -static ulong lAddr; /* * Handle a RARP received packet. @@ -42,9 +41,10 @@ static ulong lAddr; static void RarpHandler(uchar * dummi0, unsigned dummi1, unsigned dummi2, unsigned dummi3) { +#ifdef DEBUG printf("Got good RARP\n"); - - TftpStart(lAddr); +#endif + TftpStart (); } @@ -54,19 +54,17 @@ RarpHandler(uchar * dummi0, unsigned dummi1, unsigned dummi2, unsigned dummi3) static void RarpTimeout(void) { - RarpRequest(BootFile, lAddr); + RarpRequest (); } void -RarpRequest(char *fileName, ulong loadAdr) +RarpRequest (void) { int i; volatile uchar *pkt; ARP_t * rarp; - lAddr = loadAdr; - printf("RARP broadcast %d\n", ++RarpTry); pkt = NetTxPacket; @@ -84,12 +82,9 @@ RarpRequest(char *fileName, ulong loadAdr) *(IPaddr_t *)(&rarp->ar_data[6]) = NetOurIP; /* source IP addr */ NetCopyEther(&rarp->ar_data[10], NetOurEther); /* dest ET addr = source ET addr ??*/ /* dest. IP addr set to broadcast */ - for (i = 0; i <= 3; i++) rarp->ar_data[16 + i] = 0xff; - - - - /* store boot file name for TFTP */ - strcpy(BootFile, fileName); + for (i = 0; i <= 3; i++) { + rarp->ar_data[16 + i] = 0xff; + } NetSendPacket(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE); diff --git a/net/rarp.h b/net/rarp.h index 6c1a129..13b0790 100644 --- a/net/rarp.h +++ b/net/rarp.h @@ -37,7 +37,7 @@ extern int RarpTry; -extern void RarpRequest(char *fileName, ulong loadAdr); /* Send a RARP request */ +extern void RarpRequest (void); /* Send a RARP request */ /**********************************************************************/ diff --git a/net/tftp.c b/net/tftp.c index e9d47af..2a8f3d4 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -1,8 +1,7 @@ /* - * LiMon - TFTP. - * * Copyright 1994, 1995, 2000 Neil Russell. * (See License) + * Copyright 2000 DENX Software Engineering, Wolfgang Denk, wd@denx.de */ #include @@ -11,6 +10,8 @@ #include "tftp.h" #include "bootp.h" +#undef ET_DEBUG + #if (CONFIG_COMMANDS & CFG_CMD_NET) #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */ @@ -29,7 +30,6 @@ #define TFTP_ERROR 5 - static int TftpServerPort; /* The UDP port at their end */ static int TftpOurPort; /* The UDP port at our end */ static int TftpTimeoutCount; @@ -41,12 +41,17 @@ static int TftpState; #define STATE_TOO_LARGE 3 #define STATE_BAD_MAGIC 4 +#define DEFAULT_NAME_LEN (8 + 4 + 1) +static char default_filename[DEFAULT_NAME_LEN]; +static char *tftp_filename; + static __inline__ void store_block (unsigned block, uchar * src, unsigned len) { (void)memcpy((void *)(load_addr + block * 512), src, len); } +static void TftpSend (void); static void TftpTimeout (void); /**********************************************************************/ @@ -69,8 +74,8 @@ TftpSend (void) case STATE_RRQ: xp = pkt; *((ushort *)pkt)++ = SWAP16c(TFTP_RRQ); - strcpy ((char *)pkt, &BootFile[0]); - pkt += strlen(BootFile) + 1; + strcpy ((char *)pkt, tftp_filename); + pkt += strlen(tftp_filename) + 1; strcpy ((char *)pkt, "octet"); pkt += 5 /*strlen("octet")*/ + 1; len = pkt - xp; @@ -204,7 +209,7 @@ TftpTimeout (void) void -TftpStart (ulong loadAdr) +TftpStart (void) { #ifdef ET_DEBUG printf ("\nServer ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -217,8 +222,22 @@ TftpStart (ulong loadAdr) ); #endif /* DEBUG */ - puts ("TFTP from server "); NetPrintIPaddr (NetServerIP); - puts ("; our IP address is "); NetPrintIPaddr (NetOurIP); + if (BootFile[0] == '\0') { + sprintf(default_filename, "%02lX%02lX%02lX%02lX.img", + NetOurIP & 0xFF, + (NetOurIP >> 8) & 0xFF, + (NetOurIP >> 16) & 0xFF, + (NetOurIP >> 24) & 0xFF ); + tftp_filename = default_filename; + + printf ("*** Warning: no boot file name; using '%s'\n", + tftp_filename); + } else { + tftp_filename = BootFile; + } + + puts ("TFTP from server "); print_IPaddr (NetServerIP); + puts ("; our IP address is "); print_IPaddr (NetOurIP); // Check if we need to send across this subnet if (NetOurGatewayIP && NetOurSubnetMask) { @@ -227,44 +246,23 @@ TftpStart (ulong loadAdr) if (OurNet != ServerNet) { puts ("; sending throught gateway "); - NetPrintIPaddr (NetOurGatewayIP) ; + print_IPaddr (NetOurGatewayIP) ; } } putc ('\n'); - if (BootFile[0] == '\0') { - int i; - - for (i = 0; i < 4; i++) { - static char hex[] = "0123456789ABCDEF"; - int x; + printf ("Filename '%s'.", tftp_filename); - x = (NetOurIP >> (i * 8)) & 0xff; - BootFile[i*2+0] = hex[x >> 4]; - BootFile[i*2+1] = hex[x & 0xf]; - } - strcpy (&BootFile[8], ".img"); - - printf ("No file name; using '%s'.", BootFile); - } else { - printf ("Filename '%s'.", BootFile); - } - - if (NetBootFileSize) + if (NetBootFileSize) { printf (" Size is %d%s kB => %x Bytes", NetBootFileSize/2, (NetBootFileSize%2) ? ".5" : "", NetBootFileSize<<9); + } putc ('\n'); - if (loadAdr == ~0) { - load_addr = CFG_LOAD_ADDR; - printf ("No load address; using 0x%lx\n", load_addr); - } else { - load_addr = loadAdr; - printf ("Load address: 0x%lx\n", load_addr); - } + printf ("Load address: 0x%lx\n", load_addr); puts ("Loading: *\b"); diff --git a/net/tftp.h b/net/tftp.h index f8089b1..e3dfb26 100644 --- a/net/tftp.h +++ b/net/tftp.h @@ -14,7 +14,7 @@ */ /* tftp.c */ -extern void TftpStart(ulong loadAdr); /* Begin TFTP get */ +extern void TftpStart (void); /* Begin TFTP get */ /**********************************************************************/