]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
Reworking of TFTP code; use ARP request to get TFTP server's
authorwdenk <wdenk>
Thu, 28 Dec 2000 11:02:28 +0000 (11:02 +0000)
committerwdenk <wdenk>
Thu, 28 Dec 2000 11:02:28 +0000 (11:02 +0000)
ethernet address

19 files changed:
CHANGELOG
README
common/board.c
common/cmd_boot.c
common/cmd_net.c
common/cmd_nvedit.c
include/config_Sandpoint8240.h
include/net.h
include/version.h
net/Makefile
net/arp.c [new file with mode: 0644]
net/arp.h [new file with mode: 0644]
net/bootp.c
net/bootp.h
net/net.c
net/rarp.c
net/rarp.h
net/tftp.c
net/tftp.h

index 77ce92ef7840673190c8b2016c3f65955e3a574c..bec3af0bee842f52151fcd33ab73aec2053c06ef 100644 (file)
--- 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 12bc96474d44cfaed958b003e0a6f47fafecc805..61f21f740d09abe304b1de4b5d0f229fb91728fb 100644 (file)
--- 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 :-).
 
 
 
index 22f06b04a3c055de977a71cb13d7de0e2277c1e8..7ce6770ae620d47f3cf4a4cef9d95adede4639b9 100644 (file)
@@ -35,6 +35,9 @@
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
 #endif
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#include <net.h>
+#endif
 #include <version.h>
 
 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
     /*
index 693f8dee9c6c15921bbba00eb7ba4904ce39d82c..6213c5a848cece03c02d7bb44fef829a727d8a0b 100644 (file)
@@ -28,6 +28,7 @@
 #include <command.h>
 #include <cmd_boot.h>
 #include <s_record.h>
+#include <net.h>
 
 
 #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);
index aafe673d25c988bad7ad4391cff1e98b22e65f69..2819156b1522454765f7eb28af62f902fe6ed157 100644 (file)
@@ -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)) {
index 2f901922f4fbe7261834597c5ede52bf70d0a181..2ea1f5285e1e06afc9062ae3c9722de53291e32e 100644 (file)
@@ -28,6 +28,9 @@
 #include <command.h>
 #include <cmd_nvedit.h>
 #include <linux/stddef.h>
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#include <net.h>
+#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)
index 44bc77ea986066654870a1a40e23bca7a01e00de..580fe438afbfc9f98505d500bce0b81d8bfc9c93 100644 (file)
@@ -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   */
 
index 685e3709b8316bab493638b4523fb9c9cf1addb8..5243aaae73793bf235b65e6dc90b342ef9f1a6dd 100644 (file)
@@ -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);
 
 /**********************************************************************/
 
index f6f4bcb70aa842ff2fecef4149b5f003abd3198a..00a2f09929a54c7e4208490b8375b7283a1d6794 100644 (file)
@@ -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__ */
index e0d3446c1d65e1f7a78fe7bd90e057f20ef9c6fa..a87b81b856d198154b9da0f030f96e1c110eb889 100644 (file)
@@ -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 (file)
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 <ppcboot.h>
+#include <command.h>
+#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 (file)
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__ */
+
index 30a9e04a81dd8c434b5be4aa352cb61a719e5de4..ba83d7c1580059bf930ad9c752013a593e1d12ce 100644 (file)
@@ -14,6 +14,7 @@
 #include "net.h"
 #include "bootp.h"
 #include "tftp.h"
+#include "arp.h"
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
 #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.
index 0e7dc18a422999d990edc54eb8b542867f5b62c2..cf9a77e4a34586250d01fdf8313ebffb86f0fca9 100644 (file)
@@ -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);
 
 /**********************************************************************/
 
index 9fd82dfb54599e656b1a9861c6cb625dfc5b6111..e84164995ec022693f0e7f770d26b4c7ce42126f 100644 (file)
--- 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 <ppcboot.h>
 #include <command.h>
 #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 */
index 8b4cfa781973f5e4e0ada9934ab5e7317628fdd3..cb43baa1a26499a045bfbdb3689ec0fd471d0772 100644 (file)
@@ -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);
 
index 6c1a129e3c60a57a8fe07b4b03c877fad20855e7..13b07901cfc6c0c9c9f7f1b37e2a27e6b652007a 100644 (file)
@@ -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 */
 
 /**********************************************************************/
 
index e9d47afd0db81a2debc9c273112146200a921e5c..2a8f3d448087ef6ac7cf452f63e91b0c5890ce98 100644 (file)
@@ -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 <ppcboot.h>
@@ -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");
 
index f8089b13754991e62d273bf61d0e20054ebfb71e..e3dfb2628aa51bf140d2df6b2e32995aa53fce01 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 /* tftp.c */
-extern void    TftpStart(ulong loadAdr);       /* Begin TFTP get */
+extern void    TftpStart (void);       /* Begin TFTP get */
 
 /**********************************************************************/