From a4cbe53912b24a314839dce742359edffbf49b1f Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 19 Oct 2016 13:26:07 +0000 Subject: [PATCH] MFC: 304677, 304680, 305125, 305770, 305769 r304677: Add tftpfs support for the EFI loader Allow netbooting on efi without having to setup any NFS server by rebuilding the loader with LOADER_TFTP_SUPPORT like for the i386 pxeloader r305125: Netboot: allow both tftpfs and nfs in both pxeboot and loader.efi Add a new 'netproto' variable which can be set for now to NET_TFTP or NET_NFS (default to NET_NONE) From the dhcp options if one sets the root-path option to: "ip:path", the loader will consider it is booting over NFS (meaning same behaviour as the default current behaviour) if the dhcp option "tftp server address" is set (option 150) the loader will consider it is booting over tftpfs, it will then consider the root-path options with 2 possible case 1. "path" then the IP of the tftp server will be the one passed by the option 150, and the files will be retrieved under "path" on the tftp server 2. "ip:path" then the IP of the tftp server will be the one passed in the option "overwritting the IP from the option 150. We could not "abuse" the rootpath option in the form or tftp://ip:path because this is already used for other purpose by iPXE preventing any chainload from iPXE to the FreeBSD loader. Given at each open(), the loader loops over all available filesystems and keep the "best" error, we needed to prevent tftpfs to fallback on nfs and vice versa. the tftpfs and nfs implementation in libstand now return EINVAL early if 'netproto' for that purpose. Relnotes: yes Sponsored by: Gandi.net --- lib/libstand/bootp.c | 4 ++++ lib/libstand/bootp.h | 1 + lib/libstand/globals.c | 2 ++ lib/libstand/net.h | 11 +++++++++++ lib/libstand/nfs.c | 6 ++++++ lib/libstand/tftp.c | 3 +++ sys/boot/common/dev_net.c | 18 ++++++++++++++++-- sys/boot/efi/loader/conf.c | 1 + sys/boot/i386/libi386/pxe.c | 35 +++++++++++++++++++---------------- sys/boot/i386/loader/conf.c | 4 ---- sys/boot/pc98/loader/conf.c | 4 ---- 11 files changed, 63 insertions(+), 26 deletions(-) diff --git a/lib/libstand/bootp.c b/lib/libstand/bootp.c index f3bc81697911..7474f8f971d5 100644 --- a/lib/libstand/bootp.c +++ b/lib/libstand/bootp.c @@ -411,6 +411,10 @@ vend_rfc1048(cp, len) bcopy(cp, &dhcp_serverip.s_addr, sizeof(dhcp_serverip.s_addr)); } + if (tag == TAG_TFTP_SERVER) { + bcopy(cp, &tftpip.s_addr, + sizeof(tftpip.s_addr)); + } #endif cp += size; } diff --git a/lib/libstand/bootp.h b/lib/libstand/bootp.h index 47e5649ce9a0..9f4d4139a5b1 100644 --- a/lib/libstand/bootp.h +++ b/lib/libstand/bootp.h @@ -106,6 +106,7 @@ struct bootp { #define TAG_T2 ((unsigned char) 59) #define TAG_CLASSID ((unsigned char) 60) #define TAG_CLIENTID ((unsigned char) 61) +#define TAG_TFTP_SERVER ((unsigned char) 150) #endif #define TAG_END ((unsigned char) 255) diff --git a/lib/libstand/globals.c b/lib/libstand/globals.c index f2c624083c27..83b9f777a857 100644 --- a/lib/libstand/globals.c +++ b/lib/libstand/globals.c @@ -25,12 +25,14 @@ char hostname[FNAME_SIZE]; /* our hostname */ int hostnamelen; char domainname[FNAME_SIZE]; /* our DNS domain */ int domainnamelen; +int netproto = NET_NONE; /* Network prototol */ char ifname[IFNAME_SIZE]; /* name of interface (e.g. "le0") */ struct in_addr myip; /* my ip address */ struct in_addr nameip; /* DNS server ip address */ struct in_addr rootip; /* root ip address */ struct in_addr swapip; /* swap ip address */ struct in_addr gateip; /* gateway ip address */ +struct in_addr tftpip; /* TFTP ip address */ n_long netmask = 0xffffff00; /* subnet or net mask */ u_int intf_mtu; /* interface mtu from bootp/dhcp */ int errno; /* our old friend */ diff --git a/lib/libstand/net.h b/lib/libstand/net.h index ce7df49f2de2..2c7fd4c9715f 100644 --- a/lib/libstand/net.h +++ b/lib/libstand/net.h @@ -36,6 +36,8 @@ * $FreeBSD$ */ +#ifndef _STAND_NET_H +#define _STAND_NET_H #ifndef _KERNEL /* XXX - see */ #undef __IPADDR #define __IPADDR(x) htonl((u_int32_t)(x)) @@ -45,6 +47,12 @@ #define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } +enum net_proto { + NET_NONE, + NET_NFS, + NET_TFTP +}; + /* Returns true if n_long's on the same net */ #define SAMENET(a1, a2, m) ((a1.s_addr & m) == (a2.s_addr & m)) @@ -74,6 +82,7 @@ extern char hostname[FNAME_SIZE]; extern int hostnamelen; extern char domainname[FNAME_SIZE]; extern int domainnamelen; +extern int netproto; extern char ifname[IFNAME_SIZE]; /* All of these are in network order. */ @@ -82,6 +91,7 @@ extern struct in_addr rootip; extern struct in_addr swapip; extern struct in_addr gateip; extern struct in_addr nameip; +extern struct in_addr tftpip; extern n_long netmask; extern u_int intf_mtu; @@ -120,3 +130,4 @@ n_long inet_addr(char *); /* Machine-dependent functions: */ time_t getsecs(void); +#endif /* ! _STAND_NET_H */ diff --git a/lib/libstand/nfs.c b/lib/libstand/nfs.c index 36986db55762..19bc73c77a80 100644 --- a/lib/libstand/nfs.c +++ b/lib/libstand/nfs.c @@ -473,6 +473,9 @@ nfs_open(const char *upath, struct open_file *f) int error; char *path; + if (netproto != NET_NFS) + return (EINVAL); + #ifdef NFS_DEBUG if (debug) printf("nfs_open: %s (rootpath=%s)\n", upath, rootpath); @@ -1115,6 +1118,9 @@ nfs_open(const char *upath, struct open_file *f) int error; char *path; + if (netproto != NET_NFS) + return (EINVAL); + #ifdef NFS_DEBUG if (debug) printf("nfs_open: %s (rootpath=%s)\n", upath, rootpath); diff --git a/lib/libstand/tftp.c b/lib/libstand/tftp.c index 001cbfd6d1f0..621cfd8a15d2 100644 --- a/lib/libstand/tftp.c +++ b/lib/libstand/tftp.c @@ -402,6 +402,9 @@ tftp_open(const char *path, struct open_file *f) size_t pathsize; const char *extraslash; + if (netproto != NET_TFTP) + return (EINVAL); + if (strcmp(f->f_dev->dv_name, "net") != 0) { #ifdef __i386__ if (strcmp(f->f_dev->dv_name, "pxe") != 0) diff --git a/sys/boot/common/dev_net.c b/sys/boot/common/dev_net.c index ed07a2cfc15b..09583d0c831c 100644 --- a/sys/boot/common/dev_net.c +++ b/sys/boot/common/dev_net.c @@ -167,8 +167,14 @@ net_open(struct open_file *f, ...) 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); + setenv("boot.netif.server", inet_ntoa(rootip), 1); + if (netproto == NET_TFTP) { + setenv("boot.tftproot.server", inet_ntoa(rootip), 1); + setenv("boot.tftproot.path", rootpath, 1); + } else if (netproto == NET_NFS) { + setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); + setenv("boot.nfsroot.path", rootpath, 1); + } if (intf_mtu != 0) { char mtu[16]; sprintf(mtu, "%u", intf_mtu); @@ -365,6 +371,13 @@ net_parse_rootpath() int i; n_long addr = INADDR_NONE; + netproto = NET_NFS; + + if (tftpip.s_addr != 0) { + netproto = NET_TFTP; + addr = tftpip.s_addr; + } + for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) if (rootpath[i] == ':') break; @@ -373,5 +386,6 @@ net_parse_rootpath() addr = inet_addr(&rootpath[0]); bcopy(&rootpath[i], rootpath, strlen(&rootpath[i])+1); } + return (addr); } diff --git a/sys/boot/efi/loader/conf.c b/sys/boot/efi/loader/conf.c index ecbf8b02c8e3..3596a6360c3b 100644 --- a/sys/boot/efi/loader/conf.c +++ b/sys/boot/efi/loader/conf.c @@ -51,6 +51,7 @@ struct fs_ops *file_system[] = { &dosfs_fsops, &ufs_fsops, &cd9660_fsops, + &tftp_fsops, &nfs_fsops, &gzipfs_fsops, &bzipfs_fsops, diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c index 096ebc4d58a2..28046f3ba1d1 100644 --- a/sys/boot/i386/libi386/pxe.c +++ b/sys/boot/i386/libi386/pxe.c @@ -288,10 +288,15 @@ pxe_open(struct open_file *f, ...) bootp(pxe_sock, BOOTP_PXE); if (rootip.s_addr == 0) rootip.s_addr = bootplayer.sip; -#ifdef LOADER_NFS_SUPPORT - if (!rootpath[0]) + + netproto = NET_NFS; + if (tftpip.s_addr != 0) { + netproto = NET_TFTP; + rootip.s_addr = tftpip.s_addr; + } + + if (netproto == NET_NFS && !rootpath[0]) strcpy(rootpath, PXENFSROOTPATH); -#endif for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) if (rootpath[i] == ':') @@ -315,17 +320,17 @@ pxe_open(struct open_file *f, ...) sprintf(mtu, "%u", intf_mtu); setenv("boot.netif.mtu", mtu, 1); } -#ifdef LOADER_NFS_SUPPORT printf("pxe_open: server addr: %s\n", inet_ntoa(rootip)); printf("pxe_open: server path: %s\n", rootpath); printf("pxe_open: gateway ip: %s\n", inet_ntoa(gateip)); - setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); - setenv("boot.nfsroot.path", rootpath, 1); -#else - setenv("boot.netif.server", inet_ntoa(rootip), 1); - setenv("boot.tftproot.path", rootpath, 1); -#endif + if (netproto == NET_NFS) { + setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); + setenv("boot.nfsroot.path", rootpath, 1); + } else if (netproto == NET_TFTP) { + setenv("boot.netif.server", inet_ntoa(rootip), 1); + setenv("boot.tftproot.path", rootpath, 1); + } setenv("dhcp.host-name", hostname, 1); setenv("pxeboot.ip", inet_ntoa(myip), 1); @@ -359,10 +364,10 @@ pxe_close(struct open_file *f) if (pxe_opens > 0) return(0); -#ifdef LOADER_NFS_SUPPORT - /* get an NFS filehandle for our root filesystem */ - pxe_setnfshandle(rootpath); -#endif + if (netproto == NET_NFS) { + /* get an NFS filehandle for our root filesystem */ + pxe_setnfshandle(rootpath); + } if (pxe_sock >= 0) { @@ -422,7 +427,6 @@ pxe_perror(int err) return; } -#ifdef LOADER_NFS_SUPPORT /* * Reach inside the libstand NFS code and dig out an NFS handle * for the root filesystem. @@ -533,7 +537,6 @@ pxe_setnfshandle(char *rootpath) setenv("boot.nfsroot.nfshandlelen", buf, 1); } #endif /* OLD_NFSV2 */ -#endif /* LOADER_NFS_SUPPORT */ void pxenv_call(int func) diff --git a/sys/boot/i386/loader/conf.c b/sys/boot/i386/loader/conf.c index 38df74d18be0..29ce1e332605 100644 --- a/sys/boot/i386/loader/conf.c +++ b/sys/boot/i386/loader/conf.c @@ -45,10 +45,6 @@ __FBSDID("$FreeBSD$"); * XXX as libi386 and biosboot merge, some of these can become linker sets. */ -#if defined(LOADER_NFS_SUPPORT) && defined(LOADER_TFTP_SUPPORT) -#error "Cannot have both tftp and nfs support yet." -#endif - #if defined(LOADER_FIREWIRE_SUPPORT) extern struct devsw fwohci; #endif diff --git a/sys/boot/pc98/loader/conf.c b/sys/boot/pc98/loader/conf.c index d05cd13f9b20..695c2604c03a 100644 --- a/sys/boot/pc98/loader/conf.c +++ b/sys/boot/pc98/loader/conf.c @@ -42,10 +42,6 @@ __FBSDID("$FreeBSD$"); * XXX as libi386 and biosboot merge, some of these can become linker sets. */ -#if defined(LOADER_NFS_SUPPORT) && defined(LOADER_TFTP_SUPPORT) -#error "Cannot have both tftp and nfs support yet." -#endif - /* Exported for libstand */ struct devsw *devsw[] = { &bioscd,