Modifications for 0.9.3:
======================================================================
+* Added DHCP Support
+ (Patch by Chris Hallinan: 8 May 2001)
+
* Added FLAGADM Configuration
(Patch by Kári Davíðsson: 8 May 2001)
E: yooth@ipone.co.kr
D: Added port to the RPXlite board
+N: Chris Hallinan
+E: clh@net1plus.com
+D: DHCP Support
+
N: Anne-Sophie Harnois
E: Anne-Sophie.Harnois@nextream.fr
D: Port to Walnut405 board
netboot_common (RARP, cmdtp, bd, argc, argv);
}
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+void do_dhcp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ netboot_common(DHCP, cmdtp, bd, argc, argv);
+}
+#endif /* CFG_CMD_DHCP */
+
static void netboot_update_env(void)
{
char tmp[12] ;
CMD_TBL_BOOTP
CMD_TBL_TFTPB
CMD_TBL_RARPB
+ CMD_TBL_DHCP
CMD_TBL_DISK
CMD_TBL_BOOTD
CMD_TBL_LOADS
#define CFG_CMD_REGINFO 0x00200000 /* Register dump */
#define CFG_CMD_IMMAP 0x00400000 /* IMMR dump support */
#define CFG_CMD_DATE 0x00800000 /* support for RTC, date/time...*/
-#define CFG_CMD_BSP 0x01000000 /* Board SPecific functions */
+#define CFG_CMD_DHCP 0x01000000 /* DHCP Support */
+#define CFG_CMD_BSP 0x02000000 /* Board SPecific functions */
#define CFG_CMD_ALL 0xFFFFFFFF /* ALL commands */
#define CFG_CMD_NONSTD (CFG_CMD_KGDB | \
CFG_CMD_IDE | \
CFG_CMD_PCMCIA | \
+ CFG_CMD_DHCP | \
CFG_CMD_PCI | \
CFG_CMD_IRQ | \
CFG_CMD_EEPROM | \
void do_rarpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+#define CMD_TBL_DHCP MK_CMD_TBL_ENTRY( \
+ "dhcp", 4, 3, 1, do_dhcp, \
+ "dhcp - invoke DHCP client to obtain IP/boot params\n", \
+ "Help line 2 - FIXME\n" \
+),
+
+
+void do_dhcp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+#else
+#define CMD_TBL_DHCP
+#endif /* CFG_CMD_DHCP */
+
#else
#define CMD_TBL_BOOTP
#define CMD_TBL_TFTPB
#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */
-#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_IDE | CFG_CMD_DATE)
+#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \
+ CFG_CMD_DHCP | \
+ CFG_CMD_IDE | \
+ CFG_CMD_DATE )
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */
-#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_IDE | CFG_CMD_DATE)
+#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \
+ CFG_CMD_DHCP | \
+ CFG_CMD_IDE | \
+ CFG_CMD_DATE )
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */
-#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_IDE | CFG_CMD_DATE)
+#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \
+ CFG_CMD_DHCP | \
+ CFG_CMD_IDE | \
+ CFG_CMD_DATE )
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */
-#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_IDE | CFG_CMD_DATE)
+#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \
+ CFG_CMD_DHCP | \
+ CFG_CMD_IDE | \
+ CFG_CMD_DATE )
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
/*
- * (C) Copyright 2000
+ * (C) Copyright 2000, 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
#define CONFIG_PHY_ADDR 1 /* PHY address */
-#define CONFIG_COMMANDS \
- (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_IRQ | CFG_CMD_KGDB)
-/* CFG_CMD_ENV est definie */
-/* ((CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_IRQ | CFG_CMD_KGDB) & ~(CFG_CMD_ENV))
-*/
+#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \
+ CFG_CMD_PCI | \
+ CFG_CMD_IRQ | \
+ CFG_CMD_KGDB | \
+ CFG_CMD_IDE | \
+ CFG_CMD_DHCP)
+
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
*
* 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
+ * 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
#define CONFIG_LWMON 1 /* ...on a LWMON board */
#if 1
-#define CONFIG_8xx_CONS_SMC2 1 /* Console is on SMC2 */
+#define CONFIG_8xx_CONS_SMC2 1 /* Console is on SMC2 */
#else
-#define CONFIG_8xx_CONS_SCC2
+#define CONFIG_8xx_CONS_SCC2
#endif
#define CONFIG_BAUDRATE 19200
#undef CONFIG_STATUS_LED /* Status LED disabled */
-#define CONFIG_SOFT_I2C /* Software I2C support enabled */
+#define CONFIG_SOFT_I2C /* Software I2C support enabled */
# define CFG_I2C_SPEED 50000
# define CFG_I2C_SLAVE 0xFE
# define CFG_EEPROM_PAGE_WRITE_BITS 4 /* The Atmel 24C164 has 16 byte */
/* page write mode using last */
/* 4 bits of the address */
-#define CONFIG_RTC_PCF8563 /* use Philips PCF8563 RTC */
+#define CONFIG_RTC_PCF8563 /* use Philips PCF8563 RTC */
#ifdef CONFIG_8xx_CONS_SCC2 /* Can't use ethernet, then */
-#define CONFIG_COMMANDS ((CONFIG_CMD_DFL & ~CFG_CMD_NET) | \
- CFG_CMD_EEPROM | \
- CFG_CMD_DATE | \
- CFG_CMD_IDE | \
- CFG_CMD_BSP )
+#define CONFIG_COMMANDS ( (CONFIG_CMD_DFL & ~CFG_CMD_NET) | \
+ CFG_CMD_EEPROM | \
+ CFG_CMD_DATE | \
+ CFG_CMD_IDE | \
+ CFG_CMD_BSP )
#else
-#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \
- CFG_CMD_EEPROM | \
- CFG_CMD_DATE | \
- CFG_CMD_IDE | \
- CFG_CMD_BSP )
+#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \
+ CFG_CMD_DHCP | \
+ CFG_CMD_EEPROM | \
+ CFG_CMD_DATE | \
+ CFG_CMD_IDE | \
+ CFG_CMD_BSP )
#endif
#define CONFIG_MAC_PARTITION
#define CONFIG_DOS_PARTITION
/*
* Miscellaneous configurable options
*/
-#define CFG_LONGHELP /* undef to save memory */
-#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+#define CFG_LONGHELP /* undef to save memory */
+#define CFG_PROMPT "=> " /* Monitor Command Prompt */
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
-#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
#else
-#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
#endif
-#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
-#define CFG_MAXARGS 16 /* max number of command args */
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS 16 /* max number of command args */
#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
#define CFG_MEMTEST_START 0x00100000 /* memtest works on */
#define CFG_MEMTEST_END 0x00F00000 /* 1 ... 15MB in DRAM */
-#define CFG_LOAD_ADDR 0x00100000 /* default load address */
+#define CFG_LOAD_ADDR 0x00100000 /* default load address */
-#define CFG_PIO_MODE 0 /* IDE interface in PIO Mode 0 */
+#define CFG_PIO_MODE 0 /* IDE interface in PIO Mode 0 */
-#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
+#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
* Definitions for initial stack pointer and data area (in DPRAM)
*/
#define CFG_INIT_RAM_ADDR CFG_IMMR
-#define CFG_INIT_RAM_END 0x3000 /* End of used area in DPRAM */
-#define CFG_INIT_DATA_SIZE 64 /* size in bytes reserved for initial data */
+#define CFG_INIT_RAM_END 0x3000 /* End of used area in DPRAM */
+#define CFG_INIT_DATA_SIZE 64 /* size in bytes reserved for initial data */
#define CFG_INIT_DATA_OFFSET (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE)
-#define CFG_INIT_SP_OFFSET CFG_INIT_DATA_OFFSET
+#define CFG_INIT_SP_OFFSET CFG_INIT_DATA_OFFSET
/*-----------------------------------------------------------------------
* Start addresses for the final memory configuration
* (Set up by the startup code)
* Please note that CFG_SDRAM_BASE _must_ start at 0
*/
-#define CFG_SDRAM_BASE 0x00000000
+#define CFG_SDRAM_BASE 0x00000000
#define CFG_FLASH_BASE 0x40000000
#if defined(DEBUG) || (CONFIG_COMMANDS & CFG_CMD_IDE)
-#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */
+#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */
#else
-#define CFG_MONITOR_LEN (128 << 10) /* Reserve 128 kB for Monitor */
+#define CFG_MONITOR_LEN (128 << 10) /* Reserve 128 kB for Monitor */
#endif
#define CFG_MONITOR_BASE CFG_FLASH_BASE
-#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */
+#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */
/*
* For booting Linux, the board info and command line data
* have to be in the first 8 MB of memory, since this is
* the maximum mapped by the Linux kernel during initialization.
*/
-#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
+#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
/*-----------------------------------------------------------------------
* FLASH organization
*/
#if 0
/* Start port with environment in flash; switch to EEPROM later */
-#define CFG_ENV_IS_IN_FLASH 1
-#define CFG_ENV_ADDR 0x407E0000 /* Address of Environment Sector */
-#define CFG_ENV_SIZE 0x1000 /* Total Size of Environment */
-#define CFG_ENV_SECT_SIZE 0x20000 /* we have BIG sectors only :-( */
+#define CFG_ENV_IS_IN_FLASH 1
+#define CFG_ENV_ADDR 0x407E0000 /* Address of Environment Sector */
+#define CFG_ENV_SIZE 0x1000 /* Total Size of Environment */
+#define CFG_ENV_SECT_SIZE 0x20000 /* we have BIG sectors only :-( */
#else
/* Final version: environment in EEPROM */
#define CFG_ENV_IS_IN_EEPROM 1
#define CFG_I2C_POWER_B_ADDR 0x53 /* PCMCIA/USB power switch, channel B */
#define CFG_I2C_KEYBD_ADDR 0x56 /* PIC LWE keyboard */
#define CFG_I2C_PICIO_ADDR 0x57 /* PIC IO Expander */
-#define CFG_I2C_EEPROM_ADDR 0x58 /* EEPROM AT24C164 */
+#define CFG_I2C_EEPROM_ADDR 0x58 /* EEPROM AT24C164 */
/*-----------------------------------------------------------------------
* Cache Configuration
* interrupt status bit, set PLL multiplication factor !
*/
/* 0x00405000 */
-#define CFG_PLPRCR_MF 4 /* (4+1) * 13.2 = 66 MHz Clock */
+#define CFG_PLPRCR_MF 4 /* (4+1) * 13.2 = 66 MHz Clock */
#define CFG_PLPRCR \
( (CFG_PLPRCR_MF << PLPRCR_MF_SHIFT) | \
PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST | \
PLPRCR_CSR /*| PLPRCR_LOLRE|PLPRCR_FIOPD*/ \
)
-#define CONFIG_8xx_GCLK_FREQ ((CFG_PLPRCR_MF+1)*13200000)
+#define CONFIG_8xx_GCLK_FREQ ((CFG_PLPRCR_MF+1)*13200000)
/*-----------------------------------------------------------------------
* SCCR - System Clock and reset Control Register 15-27
/* 0x01800000 */
#define CFG_SCCR (SCCR_COM00 | /*SCCR_TBS|*/ \
SCCR_RTDIV | SCCR_RTSEL | \
- /*SCCR_CRQEN|*/ /*SCCR_PRQEN|*/ \
- SCCR_EBDF00 | SCCR_DFSYNC00 | \
+ /*SCCR_CRQEN|*/ /*SCCR_PRQEN|*/ \
+ SCCR_EBDF00 | SCCR_DFSYNC00 | \
SCCR_DFBRG00 | SCCR_DFNL000 | \
SCCR_DFNH000 | SCCR_DFLCD100 | \
SCCR_DFALCD01)
*-----------------------------------------------------------------------
*/
-#define CONFIG_IDE_PCCARD 1 /* Use IDE with PC Card Adapter */
+#define CONFIG_IDE_PCCARD 1 /* Use IDE with PC Card Adapter */
-#undef CONFIG_IDE_PCMCIA /* Direct IDE not supported */
-#undef CONFIG_IDE_LED /* LED for ide not supported */
+#undef CONFIG_IDE_PCMCIA /* Direct IDE not supported */
+#undef CONFIG_IDE_LED /* LED for ide not supported */
#undef CONFIG_IDE_RESET /* reset for ide not supported */
#define CFG_IDE_MAXBUS 1 /* max. 1 IDE bus */
*-----------------------------------------------------------------------
*
*/
-/*#define CFG_DER 0x2002000F*/
-#define CFG_DER 0
+/*#define CFG_DER 0x2002000F*/
+#define CFG_DER 0
/*
* Init Memory Controller:
#define TOUCHPNL_OR_AM 0xFFFF8000
#define TOUCHPNL_TIMING OR_SCY_0_CLK
-#define CFG_OR5 (TOUCHPNL_OR_AM | OR_CSNT_SAM | OR_ACS_DIV1 | OR_BI | \
+#define CFG_OR5 (TOUCHPNL_OR_AM | OR_CSNT_SAM | OR_ACS_DIV1 | OR_BI | \
TOUCHPNL_TIMING )
-#define CFG_BR5 ((TOUCHPNL_BASE & BR_BA_MSK) | BR_PS_32 | BR_V )
+#define CFG_BR5 ((TOUCHPNL_BASE & BR_BA_MSK) | BR_PS_32 | BR_V )
/*
* Memory Periodic Timer Prescaler
*
* Boot Flags
*/
-#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */
#define BOOTFLAG_WARM 0x02 /* Software reboot */
#endif /* __CONFIG_H */
#define NETLOOP_FAIL 4
-typedef enum { BOOTP, RARP, ARP, TFTP } proto_t;
+typedef enum { BOOTP, RARP, ARP, TFTP, DHCP } proto_t;
/* from net/net.c */
extern char BootFile[128]; /* Boot File name */
ulong seed1, seed2;
#endif
-static int BootpExtended (u8 *e);
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+dhcp_state_t dhcp_state = INIT;
+unsigned int dhcp_leasetime = 0;
+static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
+/* For Debug */
+char *dhcpmsg2str(int type)
+{
+ switch (type) {
+ case 1: return "DHCPDISCOVER"; break;
+ case 2: return "DHCPOFFER"; break;
+ case 3: return "DHCPREQUEST"; break;
+ case 4: return "DHCPDECLINE"; break;
+ case 5: return "DHCPACK"; break;
+ case 6: return "DHCPNACK"; break;
+ case 7: return "DHCPRELEASE"; break;
+ default: return "UNKNOWN/INVALID MSG TYPE"; break;
+ }
+}
+#endif
+
+static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
+{
+ Bootp_t *bp = (Bootp_t *) pkt;
+ int retval = 0;
+
+ if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
+ retval = -1;
+ if (len < sizeof (Bootp_t) - OPT_SIZE)
+ retval = -2;
+ if (bp->bp_op != OP_BOOTREQUEST &&
+ bp->bp_op != OP_BOOTREPLY &&
+ bp->bp_op != DHCP_OFFER &&
+ bp->bp_op != DHCP_ACK &&
+ bp->bp_op != DHCP_NAK ) {
+ retval = -3;
+ }
+ if (bp->bp_htype != HWT_ETHER)
+ retval = -4;
+ if (bp->bp_hlen != HWL_ETHER)
+ retval = -5;
+ if (bp->bp_id != BootpID)
+ retval = -6;
+
+ // printf("Filtering pkt = %d\n", retval);
+ return retval;
+}
+
+/*
+ * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
+ */
+void BootpCopyNetParams(Bootp_t *bp)
+{
+ NetOurIP = bp->bp_yiaddr;
+ NetServerIP = bp->bp_siaddr;
+ NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
+ copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
+#ifdef DEBUG
+ printf("Bootfile: %s\n", BootFile);
+#endif
+
+ /* Propagate to environment */
+ setenv ("bootfile", BootFile);
+}
+
+#if !(CONFIG_COMMANDS & CFG_CMD_DHCP)
static void BootpVendorFieldProcess(u8 *ext)
{
int size = *(ext+1) ;
putc('\n');
}
- if (NetOurGatewaysIP[0]) {
- puts ("NetOurGatewaysIP : ");
- print_IPaddr (NetOurGatewaysIP[0]);
+ if (NetOurGatewayIP) {
+ puts ("NetOurGatewayIP : ");
+ print_IPaddr (NetOurGatewayIP);
putc('\n');
}
bp = (Bootp_t *)pkt;
- if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
- return;
- if (len < sizeof (Bootp_t))
- return;
- if (bp->bp_op != OP_BOOTREPLY)
- return;
- if (bp->bp_htype != HWT_ETHER)
- return;
- if (bp->bp_hlen != HWL_ETHER)
- return;
- if (bp->bp_id != BootpID)
+ if ( BootpCheckPkt(pkt, dest, src, len) ) /* Filter out pkts we don't want */
return;
/*
#ifdef CONFIG_STATUS_LED
status_led_set (STATUS_LED_BOOT, STATUS_LED_OFF);
#endif
- NetOurIP = bp->bp_yiaddr;
- NetServerIP = bp->bp_siaddr;
- NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
- copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
- /* Propagate to environment (only for BOOTP!) */
- setenv ("bootfile", BootFile);
+ BootpCopyNetParams(bp); /* Store net parameters from reply */
/* Retrieve extended informations (we must parse the vendor area) */
if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
*/
ArpRequest();
}
-
+#endif /* !CFG_CMD_DHCP */
/*
- * Timeout on BOOTP request. Try again, forever.
+ * Timeout on BOOTP/DHCP request. Try again, forever.
*/
static void
BootpTimeout(void)
/*
* Initialize BOOTP extension fields in the request.
- *
+ */
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
+{
+ u8 *start = e ;
+
+ *e++ = 99; /* RFC1048 Magic Cookie */
+ *e++ = 130;
+ *e++ = 83;
+ *e++ = 99;
+
+ *e++ = 53; /* DHCP Message Type */
+ *e++ = 1;
+ *e++ = message_type;
+
+ *e++ = 57; /* Maximum DHCP Message Size */
+ *e++ = 2;
+ *e++ = (576-312+OPT_SIZE) >> 8;
+ *e++ = (576-312+OPT_SIZE) & 0xff;
+
+ if ( ServerID ) {
+ *e++ = 54; /* ServerID */
+ *e++ = 4;
+ *e++ = ServerID >> 24;
+ *e++ = ServerID >> 16;
+ *e++ = ServerID >> 8;
+ *e++ = ServerID & 0xff;
+ }
+
+ if ( RequestedIP ) {
+ *e++ = 50; /* Requested IP */
+ *e++ = 4;
+ *e++ = RequestedIP >> 24;
+ *e++ = RequestedIP >> 16;
+ *e++ = RequestedIP >> 8;
+ *e++ = RequestedIP & 0xff;
+ }
+
+ *e++ = 55; /* Parameter Request List */
+ *e++ = 5; /* Requesting 5 items */
+ *e++ = 1; /* Subnet Mask */
+ *e++ = 3; /* Router Option */
+ *e++ = 6; /* DNS Server(s) */
+ *e++ = 12; /* Hostname */
+ *e++ = 13; /* Boot File Size */
+
+ *e++ = 255; /* End of the list */
+
+ return e - start ;
+}
+
+#else /* CFG_CMD_DHCP */
+/*
* Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
*/
static int BootpExtended (u8 *e)
*e++ = 83;
*e++ = 99;
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+ *e++ = 53; /* DHCP Message Type */
+ *e++ = 1;
+ *e++ = DHCP_DISCOVER;
+
+ *e++ = 57; /* Maximum DHCP Message Size */
+ *e++ = 2;
+ *e++ = (576-312+OPT_SIZE) >> 16;
+ *e++ = (576-312+OPT_SIZE) & 0xff;
+#endif /* CFG_CMD_DHCP */
+
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
*e++ = 1; /* Subnet mask request */
*e++ = 4;
return e - start ;
}
+#endif /* CFG_CMD_DHCP */
void
BootpRequest (void)
{
- volatile uchar *pkt;
+ volatile uchar *pkt, *iphdr;
Bootp_t *bp;
- int ext_len;
+ int ext_len, pktlen, iplen;
+
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+ dhcp_state = INIT;
+#endif
#ifdef CONFIG_BOOTP_RANDOM_DELAY /* Random BOOTP delay */
bd_t *bis;
NetSetEther(pkt, NetBcastAddr, PROT_IP);
pkt += ETHER_HDR_SIZE;
- NetSetIP(pkt, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t));
+ /*
+ * Next line results in incorrect packet size being transmitted, resulting
+ * in errors in some DHCP servers, reporting missing bytes. Size must be
+ * set in packet header after extension length has been determined.
+ * C. Hallinan, DS4.COM, Inc.
+ */
+ /* NetSetIP(pkt, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
+ iphdr = pkt; /* We need this later for NetSetIP() */
pkt += IP_HDR_SIZE;
bp = (Bootp_t *)pkt;
NetCopyEther(bp->bp_chaddr, NetOurEther);
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);
- if (ext_len < 0) {
- ext_len = 0;
- }
+ /* Request additional information from the BOOTP/DHCP server */
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+ ext_len = DhcpExtended(bp->bp_vend, DHCP_DISCOVER, 0, 0);
+#else
+ ext_len = BootpExtended(bp->bp_vend);
+#endif /* CFG_CMD_DHCP */
/*
* Bootp ID is the lower 4 bytes of our ethernet address
BootpID += get_timer(0);
bp->bp_id = BootpID;
- NetSendPacket(NetTxPacket, BOOTP_SIZE + ext_len);
-
- NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
+ /*
+ * Calculate proper packet lengths taking into account the
+ * variable size of the options field
+ */
+ pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
+ iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
+ NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
+ NetSetTimeout(SELECT_TIMEOUT * CFG_HZ, BootpTimeout);
+
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+ dhcp_state = SELECTING;
+ NetSetHandler(DhcpHandler);
+#else
NetSetHandler(BootpHandler);
+#endif /* CFG_CMD_DHCP */
+ NetSendPacket(NetTxPacket, pktlen);
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+void DhcpOptionsProcess(char *popt)
+{
+ char *end = popt + BOOTP_HDR_SIZE;
+ int oplen;
+
+ while ( popt < end && *popt != 0xff ) {
+ oplen = *(popt + 1);
+ switch(*popt) {
+ case 1: NetOurSubnetMask = *(IPaddr_t *)(popt + 2); break;
+ case 3: NetOurGatewayIP = *(IPaddr_t *)(popt + 2); break;
+ case 53: break; /* Ignore Message Type Option */
+ case 54: NetServerIP = *(IPaddr_t *)(popt+2); break;
+ case 51: dhcp_leasetime = *(unsigned int *)(popt + 2); break;
+ default:
+ printf("******* Unhandled DHCP Option present in OFFER/ACK: %d\n", *popt);
+ break;
+ }
+ popt += oplen + 2; /* Process next option */
+ }
+}
+
+static int DhcpMessageType(unsigned char *popt)
+{
+ if ((*(uint *)popt) != BOOTP_VENDOR_MAGIC)
+ return -1;
+
+ popt += 4;
+ while ( *popt != 0xff ) {
+ if ( *popt == 53 ) /* DHCP Message Type */
+ return *(popt + 2);
+ popt += *(popt + 1) + 2; /* Scan through all options */
+ }
+ return -1;
+}
+
+/*
+ * Scan string for filename str within fname
+ */
+static int strfind(char *fname, char *str)
+{
+ int lf = strlen(fname);
+ int ls = strlen(str);
+ char *p = fname;
+ if ( ls > lf )
+ return -1;
+
+ while ( p - fname < lf ) {
+ if ( strncmp(p, str, ls) == 0 )
+ return 0;
+ p++;
+ }
+ return -1;
+}
+
+void DhcpSendRequestPkt(Bootp_t *bp_offer)
+{
+ volatile uchar *pkt, *iphdr;
+ Bootp_t *bp;
+ int pktlen, iplen, extlen;
+
+ printf("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
+ pkt = NetTxPacket;
+ memset ((void*)pkt, 0, PKTSIZE);
+
+ NetSetEther(pkt, NetBcastAddr, PROT_IP);
+ pkt += ETHER_HDR_SIZE;
+
+ iphdr = pkt; /* We'll need this later to set proper pkt size */
+ pkt += IP_HDR_SIZE;
+
+ bp = (Bootp_t *)pkt;
+ bp->bp_op = OP_BOOTREQUEST;
+ bp->bp_htype = HWT_ETHER;
+ bp->bp_hlen = HWL_ETHER;
+ bp->bp_hops = 0;
+ bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
+ bp->bp_ciaddr = bp_offer->bp_ciaddr;
+ bp->bp_yiaddr = bp_offer->bp_yiaddr;
+ bp->bp_siaddr = bp_offer->bp_siaddr;
+ bp->bp_giaddr = bp_offer->bp_giaddr;
+ NetCopyEther(bp->bp_chaddr, NetOurEther);
+
+ /*
+ * ID is the id of the OFFER packet
+ */
+
+ bp->bp_id = bp_offer->bp_id;
+
+ /*
+ * Copy options from OFFER packet if present
+ */
+ extlen = DhcpExtended(bp->bp_vend, DHCP_REQUEST, NetServerIP, bp->bp_yiaddr);
+
+ pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
+ iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
+ NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
+
+ printf("Transmitting packet: len = %d\n", pktlen);
+ NetSendPacket(NetTxPacket, pktlen);
+}
+
+/*
+ * Handle DHCP received packets.
+ */
+static void
+DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
+{
+ Bootp_t *bp = (Bootp_t *)pkt;
+ if ( BootpCheckPkt(pkt, dest, src, len) ) /* Filter out pkts we don't want */
+ return;
+
+#ifdef DEBUG
+ printf("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d)\n",
+ src, dest, len);
+#endif /* DEBUG */
+
+ switch (dhcp_state) {
+ case SELECTING:
+ /*
+ * Wait an appropriate time for any potential DHCPOFFER packets
+ * to arrive. Then select one, and generate DHCPREQUEST response.
+ * If filename is in format we recognize, assume it is a valid
+ * OFFER from a server we want.
+ */
+ if ( strfind(bp->bp_file, BOOT_FILE_PREFIX) == 0 ) {
+ printf("TRANSITIONING TO REQUESTING STATE\n");
+ dhcp_state = REQUESTING;
+ if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
+ DhcpOptionsProcess(&bp->bp_vend[4]);
+
+ BootpCopyNetParams(bp); /* Store net params from reply */
+
+ NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
+ DhcpSendRequestPkt(bp);
+ }
+ return;
+ break;
+ case REQUESTING:
+ printf("DHCP State: REQUESTING\n");
+ if ( DhcpMessageType(bp->bp_vend) == DHCP_ACK ) {
+ dhcp_state = BOUND;
+ printf("DhcpHandler: Client BOUND to address ");
+ print_IPaddr(NetOurIP);
+ printf("\n");
+#if 0 /* Not much point in configuring PPCBoot w/o loading boot file - CLH */
+ NetState = NETLOOP_SUCCESS;
+ return;
+#endif
+ /* Send ARP request to get TFTP server ethernet address.
+ * This automagically starts TFTP, too.
+ */
+ ArpRequest();
+ return;
+ }
+ break;
+ default:
+ printf("DHCP State: INVALID STATE\n");
+ break;
+ }
+
+}
+
+void DhcpRequest(void)
+{
+ BootpRequest();
}
+#endif /* CFG_CMD_DHCP */
#endif /* CFG_CMD_NET */
/*
* BOOTP header.
*/
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+#define OPT_SIZE 312 /* Minimum DHCP Options size per RFC2131 - results in 576 byte pkt */
+#else
+#define OPT_SIZE 64
+#endif
+
typedef struct
{
uchar bp_op; /* Operation */
uchar bp_chaddr[16]; /* Client hardware address */
char bp_sname[64]; /* Server host name */
char bp_file[128]; /* Boot file name */
- char bp_vend[64]; /* Vendor information */
+ char bp_vend[OPT_SIZE]; /* Vendor information */
} Bootp_t;
#define BOOTP_HDR_SIZE sizeof (Bootp_t)
/* Send a BOOTP request */
extern void BootpRequest (void);
+/****************** DHCP Support *********************/
+extern void DhcpRequest(void);
+
+/* DHCP States */
+typedef enum { INIT,
+ INIT_REBOOT,
+ REBOOTING,
+ SELECTING,
+ REQUESTING,
+ REBINDING,
+ BOUND,
+ RENEWING } dhcp_state_t;
+
+#define DHCP_DISCOVER 1
+#define DHCP_OFFER 2
+#define DHCP_REQUEST 3
+#define DHCP_DECLINE 4
+#define DHCP_ACK 5
+#define DHCP_NAK 6
+#define DHCP_RELEASE 7
+
+#define SELECT_TIMEOUT 3 /* Seconds to wait for offers */
+#define BOOT_FILE_PREFIX "image-"
+
/**********************************************************************/
#endif /* __BOOTP_H__ */
* (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
+ * Copyright 2000, 2001 Wolfgang Denk
*/
/*
* We want: - TFTP server ethernet address
* Next step: TFTP
*
+ * DHCP:
+ *
+ * Prerequisites: - own ethernet address
+ * We want: - IP, Netmask, ServerIP, Gateway IP
+ * - bootfilename, lease time
+ * Next step: - TFTP
+ *
* TFTP:
*
* Prerequisites: - own ethernet address
ArpTry = 0;
ArpRequest ();
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+ } else if (protocol == DHCP) {
+ if (net_check_prereq (protocol) != 0) {
+ return 0;
+ }
+
+ /* Start with a clean slate... */
+ NetOurIP = 0;
+ NetServerIP = 0;
+ DhcpRequest(); /* Basically same as BOOTP */
+
+#endif /* CFG_CMD_DHCP */
+
} else { /* BOOTP or RARP */
/*
}
/* Fall through */
+ case DHCP:
case RARP:
case BOOTP:
if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {