summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2015-05-25 01:29:45 +0000
committerian <ian@FreeBSD.org>2015-05-25 01:29:45 +0000
commita210991c80fcf1fa0c50759a6fd214d1c6a0790e (patch)
tree835f2696301f7059c806f7b64d7a336fd70d6b69 /sys/boot
parente82e4a2984f477320d58c14411c8586e21927e7f (diff)
downloadFreeBSD-src-a210991c80fcf1fa0c50759a6fd214d1c6a0790e.zip
FreeBSD-src-a210991c80fcf1fa0c50759a6fd214d1c6a0790e.tar.gz
MFC r283033, r283062, r283066, r283069:
Do not set preload_addr_relocate for ARM. Refactor net_getparams() to make it easier to get params from sources other than bootp and rarp. Add a routine to obtain netboot parameters from the U-Boot env vars Enable the NETIF_OPEN_CLOSE_ONCE option for ubldr.
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/arm/uboot/Makefile2
-rw-r--r--sys/boot/common/dev_net.c73
-rw-r--r--sys/boot/common/dev_net.h6
-rw-r--r--sys/boot/uboot/lib/net.c109
4 files changed, 162 insertions, 28 deletions
diff --git a/sys/boot/arm/uboot/Makefile b/sys/boot/arm/uboot/Makefile
index b4c5463..1e073b2 100644
--- a/sys/boot/arm/uboot/Makefile
+++ b/sys/boot/arm/uboot/Makefile
@@ -77,6 +77,8 @@ LIBUBOOT_FDT= ${.OBJDIR}/../../uboot/fdt/libuboot_fdt.a
LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a
.endif
+CFLAGS+= -DNETIF_OPEN_CLOSE_ONCE
+
.if ${MK_FORTH} != "no"
# Enable BootForth
BOOT_FORTH= yes
diff --git a/sys/boot/common/dev_net.c b/sys/boot/common/dev_net.c
index 147a809..091ed02 100644
--- a/sys/boot/common/dev_net.c
+++ b/sys/boot/common/dev_net.c
@@ -111,6 +111,8 @@ net_init(void)
static int
net_open(struct open_file *f, ...)
{
+ char temp[FNAME_SIZE];
+ struct iodesc *d;
va_list args;
char *devname; /* Device part of file name (or NULL). */
int error = 0;
@@ -140,6 +142,10 @@ net_open(struct open_file *f, ...)
printf("net_open: netif_open() succeeded\n");
#endif
}
+ /*
+ * If network params were not set by netif_open(), try to get
+ * them via bootp, rarp, etc.
+ */
if (rootip.s_addr == 0) {
/* Get root IP address, and path, etc. */
error = net_getparams(netdev_sock);
@@ -151,6 +157,20 @@ net_open(struct open_file *f, ...)
return (error);
}
}
+ /*
+ * Set the variables required by the kernel's nfs_diskless
+ * mechanism. This is the minimum set of variables required to
+ * mount a root filesystem without needing to obtain additional
+ * info from bootp or other sources.
+ */
+ d = socktodesc(netdev_sock);
+ sprintf(temp, "%6D", d->myea, ":");
+ setenv("boot.netif.hwaddr", temp, 1);
+ setenv("boot.netif.ip", inet_ntoa(myip), 1);
+ setenv("boot.netif.netmask", intoa(netmask), 1);
+ setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
+ setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
+ setenv("boot.nfsroot.path", rootpath, 1);
}
netdev_opens++;
f->f_devdata = &netdev_sock;
@@ -232,10 +252,7 @@ static int
net_getparams(int sock)
{
char buf[MAXHOSTNAMELEN];
- char temp[FNAME_SIZE];
- struct iodesc *d;
- int i;
- n_long smask;
+ n_long rootaddr, smask;
#ifdef SUPPORT_BOOTP
/*
@@ -302,21 +319,9 @@ net_getparams(int sock)
return (EIO);
}
exit:
- /*
- * If present, strip the server's address off of the rootpath
- * before passing it along. This allows us to be compatible with
- * the kernel's diskless (BOOTP_NFSROOT) booting conventions
- */
- for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++)
- if (rootpath[i] == ':')
- break;
- if (i && i != FNAME_SIZE && rootpath[i] == ':') {
- rootpath[i++] = '\0';
- if (inet_addr(&rootpath[0]) != INADDR_NONE)
- rootip.s_addr = inet_addr(&rootpath[0]);
- bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1);
- bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1);
- }
+ if ((rootaddr = net_parse_rootpath()) != INADDR_NONE)
+ rootip.s_addr = rootaddr;
+
#ifdef NETIF_DEBUG
if (debug) {
printf("net_open: server addr: %s\n", inet_ntoa(rootip));
@@ -324,15 +329,6 @@ exit:
}
#endif
- d = socktodesc(sock);
- sprintf(temp, "%6D", d->myea, ":");
- setenv("boot.netif.ip", inet_ntoa(myip), 1);
- setenv("boot.netif.netmask", intoa(netmask), 1);
- setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
- setenv("boot.netif.hwaddr", temp, 1);
- setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
- setenv("boot.nfsroot.path", rootpath, 1);
-
return (0);
}
@@ -354,3 +350,24 @@ net_print(int verbose)
}
printf("\n");
}
+
+/*
+ * Strip the server's address off of the rootpath if present and return it in
+ * network byte order, leaving just the pathname part in the global rootpath.
+ */
+uint32_t
+net_parse_rootpath()
+{
+ int i;
+ n_long addr = INADDR_NONE;
+
+ for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++)
+ if (rootpath[i] == ':')
+ break;
+ if (i && i != FNAME_SIZE && rootpath[i] == ':') {
+ rootpath[i++] = '\0';
+ addr = inet_addr(&rootpath[0]);
+ bcopy(&rootpath[i], rootpath, strlen(&rootpath[i])+1);
+ }
+ return (addr);
+}
diff --git a/sys/boot/common/dev_net.h b/sys/boot/common/dev_net.h
index 3b3d107..995b672 100644
--- a/sys/boot/common/dev_net.h
+++ b/sys/boot/common/dev_net.h
@@ -26,5 +26,11 @@
* $FreeBSD$
*/
+#ifndef _BOOT_DEV_NET_H_
+#define _BOOT_DEV_NET_H_
+
extern struct devsw netdev;
+uint32_t net_parse_rootpath(void);
+
+#endif
diff --git a/sys/boot/uboot/lib/net.c b/sys/boot/uboot/lib/net.c
index 902e372..20a26b7 100644
--- a/sys/boot/uboot/lib/net.c
+++ b/sys/boot/uboot/lib/net.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include "api_public.h"
#include "glue.h"
#include "libuboot.h"
+#include "dev_net.h"
static int net_probe(struct netif *, void *);
static int net_match(struct netif *, void *);
@@ -84,6 +85,109 @@ struct uboot_softc {
static struct uboot_softc uboot_softc;
+/*
+ * get_env_net_params()
+ *
+ * Attempt to obtain all the parms we need for netbooting from the U-Boot
+ * environment. If we fail to obtain the values it may still be possible to
+ * netboot; the net_dev code will attempt to get the values from bootp, rarp,
+ * and other such sources.
+ *
+ * If rootip.s_addr is non-zero net_dev assumes the required global variables
+ * are set and skips the bootp inquiry. For that reason, we don't set rootip
+ * until we've verified that we have at least the minimum required info.
+ *
+ * This is called from netif_init() which can result in it getting called
+ * multiple times, by design. The network code at higher layers zeroes out
+ * rootip when it closes a network interface, so if it gets opened again we have
+ * to obtain all this info again.
+ */
+static void
+get_env_net_params()
+{
+ char *envstr;
+ in_addr_t rootaddr, serveraddr;
+
+ /* Silently get out right away if we don't have rootpath. */
+ if (ub_env_get("rootpath") == NULL)
+ return;
+
+ /*
+ * Our own IP address must be valid. Silently get out if it's not set,
+ * but whine if it's there and we can't parse it.
+ */
+ if ((envstr = ub_env_get("ipaddr")) == NULL)
+ return;
+ if ((myip.s_addr = inet_addr(envstr)) == INADDR_NONE) {
+ printf("Could not parse ipaddr '%s'\n", envstr);
+ return;
+ }
+
+ /*
+ * Netmask is optional, default to the "natural" netmask for our IP, but
+ * whine if it was provided and we couldn't parse it.
+ */
+ if ((envstr = ub_env_get("netmask")) != NULL &&
+ (netmask = inet_addr(envstr)) == INADDR_NONE) {
+ printf("Could not parse netmask '%s'\n", envstr);
+ }
+ if (netmask == INADDR_NONE) {
+ if (IN_CLASSA(myip.s_addr))
+ netmask = IN_CLASSA_NET;
+ else if (IN_CLASSB(myip.s_addr))
+ netmask = IN_CLASSB_NET;
+ else
+ netmask = IN_CLASSC_NET;
+ }
+
+ /*
+ * Get optional serverip before rootpath; the latter can override it.
+ * Whine only if it's present but can't be parsed.
+ */
+ serveraddr = INADDR_NONE;
+ if ((envstr = ub_env_get("serverip")) != NULL) {
+ if ((serveraddr = inet_addr(envstr)) == INADDR_NONE)
+ printf("Could not parse serverip '%s'\n", envstr);
+ }
+
+ /*
+ * There must be a rootpath. It may be ip:/path or it may be just the
+ * path in which case the ip needs to be in serverip.
+ */
+ if ((envstr = ub_env_get("rootpath")) == NULL)
+ return;
+ strncpy(rootpath, envstr, sizeof(rootpath) - 1);
+ rootaddr = net_parse_rootpath();
+ if (rootaddr == INADDR_NONE)
+ rootaddr = serveraddr;
+ if (rootaddr == INADDR_NONE) {
+ printf("No server address for rootpath '%s'\n", envstr);
+ return;
+ }
+ rootip.s_addr = rootaddr;
+
+ /*
+ * Gateway IP is optional unless rootip is on a different net in which
+ * case whine if it's missing or we can't parse it, and set rootip addr
+ * to zero, which signals to other network code that network params
+ * aren't set (so it will try dhcp, bootp, etc).
+ */
+ envstr = ub_env_get("gatewayip");
+ if (!SAMENET(myip, rootip, netmask)) {
+ if (envstr == NULL) {
+ printf("Need gatewayip for a root server on a "
+ "different network.\n");
+ rootip.s_addr = 0;
+ return;
+ }
+ if ((gateip.s_addr = inet_addr(envstr) == INADDR_NONE)) {
+ printf("Could not parse gatewayip '%s'\n", envstr);
+ rootip.s_addr = 0;
+ return;
+ }
+ }
+}
+
static int
net_match(struct netif *nif, void *machdep_hint)
{
@@ -222,6 +326,11 @@ net_init(struct iodesc *desc, void *machdep_hint)
nif->nif_driver->netif_bname, nif->nif_unit);
}
+ /* Attempt to get netboot params from the u-boot env. */
+ get_env_net_params();
+ if (myip.s_addr != 0)
+ desc->myip = myip;
+
#if defined(NETIF_DEBUG)
printf("network: %s%d attached to %s\n", nif->nif_driver->netif_bname,
nif->nif_unit, ether_sprintf(desc->myea));
OpenPOWER on IntegriCloud