#include <common.h>
#include <command.h>
+#include <efi_loader.h>
#include <net.h>
#include <net/tftp.h>
#include "bootp.h"
char net_hostname[32] = {0,}; /* Our hostname */
char net_root_path[64] = {0,}; /* Our bootpath */
+static ulong time_taken_max;
+
#if defined(CONFIG_CMD_DHCP)
static dhcp_state_t dhcp_state = INIT;
static u32 dhcp_leasetime;
retval = -5;
else if (!bootp_match_id(net_read_u32(&bp->bp_id)))
retval = -6;
+ else if (memcmp(bp->bp_chaddr, net_ethaddr, HWL_ETHER) != 0)
+ retval = -7;
debug("Filtering pkt = %d\n", retval);
{
ulong time_taken = get_timer(bootp_start);
- if (time_taken >= TIMEOUT_MS) {
+ if (time_taken >= time_taken_max) {
#ifdef CONFIG_BOOTP_MAY_FAIL
puts("\nRetry time exceeded\n");
net_set_state(NETLOOP_FAIL);
e += vci_strlen; \
} while (0)
+static u8 *add_vci(u8 *e)
+{
+ char *vci = NULL;
+ char *env_vci = getenv("bootp_vci");
+
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING)
+ vci = CONFIG_SPL_NET_VCI_STRING;
+#elif defined(CONFIG_BOOTP_VCI_STRING)
+ vci = CONFIG_BOOTP_VCI_STRING;
+#endif
+
+ if (env_vci)
+ vci = env_vci;
+
+ if (vci)
+ put_vci(e, vci);
+
+ return e;
+}
+
/*
* Initialize BOOTP extension fields in the request.
*/
{
u8 *start = e;
u8 *cnt;
-#if defined(CONFIG_BOOTP_PXE)
+#ifdef CONFIG_LIB_UUID
char *uuid;
- u16 clientarch;
#endif
+ int clientarch = -1;
#if defined(CONFIG_BOOTP_VENDOREX)
u8 *x;
}
#endif
-#if defined(CONFIG_BOOTP_PXE)
+#ifdef CONFIG_BOOTP_PXE_CLIENTARCH
clientarch = CONFIG_BOOTP_PXE_CLIENTARCH;
- *e++ = 93; /* Client System Architecture */
- *e++ = 2;
- *e++ = (clientarch >> 8) & 0xff;
- *e++ = clientarch & 0xff;
+#endif
+
+ if (getenv("bootp_arch"))
+ clientarch = getenv_ulong("bootp_arch", 16, clientarch);
+
+ if (clientarch > 0) {
+ *e++ = 93; /* Client System Architecture */
+ *e++ = 2;
+ *e++ = (clientarch >> 8) & 0xff;
+ *e++ = clientarch & 0xff;
+ }
*e++ = 94; /* Client Network Interface Identifier */
*e++ = 3;
*e++ = 0; /* major revision */
*e++ = 0; /* minor revision */
+#ifdef CONFIG_LIB_UUID
uuid = getenv("pxeuuid");
if (uuid) {
}
#endif
-#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING)
- put_vci(e, CONFIG_SPL_NET_VCI_STRING);
-#elif defined(CONFIG_BOOTP_VCI_STRING)
- put_vci(e, CONFIG_BOOTP_VCI_STRING);
-#endif
+ e = add_vci(e);
#if defined(CONFIG_BOOTP_VENDOREX)
x = dhcp_vendorex_prep(e);
*e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff;
#endif
-#if defined(CONFIG_BOOTP_VCI_STRING) || \
- (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING))
-#ifdef CONFIG_SPL_BUILD
- put_vci(e, CONFIG_SPL_NET_VCI_STRING);
-#else
- put_vci(e, CONFIG_BOOTP_VCI_STRING);
-#endif
-#endif
+ add_vci(e);
#if defined(CONFIG_BOOTP_SUBNETMASK)
*e++ = 1; /* Subnet mask request */
*e++ = 255; /* End of the list */
+ /*
+ * If nothing in list, remove it altogether. Some DHCP servers get
+ * upset by this minor faux pas and do not respond at all.
+ */
+ if (e == start + 3) {
+ printf("*** Warning: no DHCP options requested\n");
+ e -= 3;
+ }
+
return e - start;
}
#endif
u32 bootp_id;
struct in_addr zero_ip;
struct in_addr bcast_ip;
+ char *ep; /* Environment pointer */
bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START, "bootp_start");
#if defined(CONFIG_CMD_DHCP)
dhcp_state = INIT;
#endif
+ ep = getenv("bootpretryperiod");
+ if (ep != NULL)
+ time_taken_max = simple_strtoul(ep, NULL, 10);
+ else
+ time_taken_max = TIMEOUT_MS;
+
#ifdef CONFIG_BOOTP_RANDOM_DELAY /* Random BOOTP delay */
if (bootp_try == 0)
srand_mac();
}
#if defined(CONFIG_CMD_DHCP)
-static void dhcp_process_options(uchar *popt, struct bootp_hdr *bp)
+static void dhcp_process_options(uchar *popt, uchar *end)
{
- uchar *end = popt + BOOTP_HDR_SIZE;
int oplen, size;
#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
int *to_ptr;
#endif
- dhcp_option_overload = 0;
while (popt < end && *popt != 0xff) {
oplen = *(popt + 1);
}
}
+static void dhcp_packet_process_options(struct bootp_hdr *bp)
+{
+ uchar *popt = (uchar *)&bp->bp_vend[4];
+ uchar *end = popt + BOOTP_HDR_SIZE;
+
+ if (net_read_u32((u32 *)&bp->bp_vend[0]) != htonl(BOOTP_VENDOR_MAGIC))
+ return;
+
+ dhcp_option_overload = 0;
+
+ /*
+ * The 'options' field MUST be interpreted first, 'file' next,
+ * 'sname' last.
+ */
+ dhcp_process_options(popt, end);
+
+ if (dhcp_option_overload & OVERLOAD_FILE) {
+ popt = (uchar *)bp->bp_file;
+ end = popt + sizeof(bp->bp_file);
+ dhcp_process_options(popt, end);
+ }
+
+ if (dhcp_option_overload & OVERLOAD_SNAME) {
+ popt = (uchar *)bp->bp_sname;
+ end = popt + sizeof(bp->bp_sname);
+ dhcp_process_options(popt, end);
+ }
+}
+
static int dhcp_message_type(unsigned char *popt)
{
if (net_read_u32((u32 *)popt) != htonl(BOOTP_VENDOR_MAGIC))
net_write_ip(&bp->bp_giaddr, zero_ip);
memcpy(bp->bp_chaddr, net_ethaddr, 6);
+ copy_filename(bp->bp_file, net_boot_file_name, sizeof(bp->bp_file));
/*
* ID is the id of the OFFER packet
debug("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: "
"%d\n", src, dest, len, dhcp_state);
+ if (net_read_ip(&bp->bp_yiaddr).s_addr == 0)
+ return;
+
switch (dhcp_state) {
case SELECTING:
/*
CONFIG_SYS_BOOTFILE_PREFIX,
strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) {
#endif /* CONFIG_SYS_BOOTFILE_PREFIX */
+ dhcp_packet_process_options(bp);
+ efi_net_set_dhcp_ack(pkt, len);
debug("TRANSITIONING TO REQUESTING STATE\n");
dhcp_state = REQUESTING;
- if (net_read_u32((u32 *)&bp->bp_vend[0]) ==
- htonl(BOOTP_VENDOR_MAGIC))
- dhcp_process_options((u8 *)&bp->bp_vend[4], bp);
-
net_set_timeout_handler(5000, bootp_timeout_handler);
dhcp_send_request_packet(bp);
#ifdef CONFIG_SYS_BOOTFILE_PREFIX
debug("DHCP State: REQUESTING\n");
if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) {
- if (net_read_u32((u32 *)&bp->bp_vend[0]) ==
- htonl(BOOTP_VENDOR_MAGIC))
- dhcp_process_options((u8 *)&bp->bp_vend[4], bp);
+ dhcp_packet_process_options(bp);
/* Store net params from reply */
store_net_params(bp);
dhcp_state = BOUND;