diff options
author | ian <ian@FreeBSD.org> | 2015-05-25 01:29:45 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2015-05-25 01:29:45 +0000 |
commit | a210991c80fcf1fa0c50759a6fd214d1c6a0790e (patch) | |
tree | 835f2696301f7059c806f7b64d7a336fd70d6b69 /sys/boot | |
parent | e82e4a2984f477320d58c14411c8586e21927e7f (diff) | |
download | FreeBSD-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/Makefile | 2 | ||||
-rw-r--r-- | sys/boot/common/dev_net.c | 73 | ||||
-rw-r--r-- | sys/boot/common/dev_net.h | 6 | ||||
-rw-r--r-- | sys/boot/uboot/lib/net.c | 109 |
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)); |