(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
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:
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
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 :-).
#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";
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;
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
/*
#include <command.h>
#include <cmd_boot.h>
#include <s_record.h>
+#include <net.h>
#if (CONFIG_COMMANDS & CFG_CMD_LOADS)
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 );
#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);
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);
}
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);
}
}
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)) {
#include <command.h>
#include <cmd_nvedit.h>
#include <linux/stddef.h>
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#include <net.h>
+#endif
/************************************************************************
*
/* 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) {
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)
#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 */
#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);
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);
/**********************************************************************/
#ifndef __VERSION_H__
#define __VERSION_H__
-#define PPCBOOT_VERSION "ppcboot 0.7.0"
+#define PPCBOOT_VERSION "ppcboot 0.7.1"
#endif /* __VERSION_H__ */
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)
--- /dev/null
+/*
+ * (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 */
--- /dev/null
+/*
+ * (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__ */
+
#include "net.h"
#include "bootp.h"
#include "tftp.h"
+#include "arp.h"
#ifdef CONFIG_STATUS_LED
#include <status_led.h>
#endif
#define PORT_BOOTPC 68 /* BOOTP client UDP port */
ulong BootpID;
-char BootFile[128];
int BootpTry;
-static ulong lAddr;
static int BootpExtended (u8 *e);
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');
}
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",
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)
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();
}
static void
BootpTimeout(void)
{
- BootpRequest(BootFile, lAddr);
+ BootpRequest ();
}
/*
}
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;
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);
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.
extern int BootpTry;
/* Send a BOOTP request */
-extern void BootpRequest(char *fileName, ulong loadAdr);
+extern void BootpRequest (void);
/**********************************************************************/
* (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) */
/** 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 */
{ 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 */
static ulong timeValue; /* Current timeout value */
volatile uchar *NetTxPacket = 0; /* THE transmit packet */
+static int net_check_prereq (proto_t protocol);
/**********************************************************************/
/*
*/
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;
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;
* 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");
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 ();
+ }
}
* Check the keyboard for a Key. Quit if we get one.
*/
if (tstc()) {
+ (void) getc();
printf("\nAbort\n");
return 0;
}
void
NetStartAgain(void)
{
- NetServerIP = 0;
- NetOurIP = 0;
NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
NetSetHandler(startAgainHandler);
}
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");
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
/**********************************************************************/
+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)
{
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",
);
}
-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 */
int RarpTry;
-static ulong lAddr;
/*
* Handle a RARP received packet.
static void
RarpHandler(uchar * dummi0, unsigned dummi1, unsigned dummi2, unsigned dummi3)
{
+#ifdef DEBUG
printf("Got good RARP\n");
-
- TftpStart(lAddr);
+#endif
+ TftpStart ();
}
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;
*(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);
extern int RarpTry;
-extern void RarpRequest(char *fileName, ulong loadAdr); /* Send a RARP request */
+extern void RarpRequest (void); /* Send a RARP request */
/**********************************************************************/
/*
- * LiMon - TFTP.
- *
* Copyright 1994, 1995, 2000 Neil Russell.
* (See License)
+ * Copyright 2000 DENX Software Engineering, Wolfgang Denk, wd@denx.de
*/
#include <ppcboot.h>
#include "tftp.h"
#include "bootp.h"
+#undef ET_DEBUG
+
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
#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;
#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);
/**********************************************************************/
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;
void
-TftpStart (ulong loadAdr)
+TftpStart (void)
{
#ifdef ET_DEBUG
printf ("\nServer ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n",
);
#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) {
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");
*/
/* tftp.c */
-extern void TftpStart(ulong loadAdr); /* Begin TFTP get */
+extern void TftpStart (void); /* Begin TFTP get */
/**********************************************************************/