summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2015-05-18 16:12:41 +0000
committerian <ian@FreeBSD.org>2015-05-18 16:12:41 +0000
commitbbcb77ec6f508b0b86c89c66da2ac6d70d07e288 (patch)
treeca0cda2b120f4c82aaf315b4d79000080015bc1b /sys/boot
parenta6c55c35fad1434a04983213809437b7e42388c8 (diff)
downloadFreeBSD-src-bbcb77ec6f508b0b86c89c66da2ac6d70d07e288.zip
FreeBSD-src-bbcb77ec6f508b0b86c89c66da2ac6d70d07e288.tar.gz
Add a routine to obtain netboot parameters from the U-Boot env vars. Call
it from the uboot net_init() implementation. The routine uses the standard U-Boot env vars plus a freebsd-specific variable named "rootpath" (the corresponding u-boot variable for that would be "bootfile" except that it refers to ubldr, so a new name was needed to communicate the path to ubldr). This allows ubldr to load a kernel from nfs without requiring a dhcp or bootp server to provide the server ip and rootpath parameters.
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/uboot/lib/net.c109
1 files changed, 109 insertions, 0 deletions
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