git: e6b997c73c41 - main - loader: add standalone network configuration

From: Warner Losh <imp_at_FreeBSD.org>
Date: Fri, 11 Sep 2026 05:04:26 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=e6b997c73c41dd8cf42afbc86215fe9c312d5096

commit e6b997c73c41dd8cf42afbc86215fe9c312d5096
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2026-09-11 04:14:06 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-09-11 04:15:28 +0000

    loader: add standalone network configuration
    
    Allow callers to obtain DHCP configuration without opening a network
    file, enabling loader.efi to discover an initmd URL before handing the
    interface back to firmware HTTP.
    
    Differential Revision:  https://reviews.freebsd.org/D59429
    Sponsored by:           Netflix
---
 stand/common/dev_net.c | 83 ++++++++++++++++++++++++++++++++++----------------
 stand/common/dev_net.h |  1 +
 2 files changed, 57 insertions(+), 27 deletions(-)

diff --git a/stand/common/dev_net.c b/stand/common/dev_net.c
index d1c48d40691a..897b09c648eb 100644
--- a/stand/common/dev_net.c
+++ b/stand/common/dev_net.c
@@ -82,6 +82,7 @@ static int	net_strategy(void *, int, daddr_t, size_t, char *, size_t *);
 static int	net_print(int);
 
 static int net_getparams(int sock);
+static void net_setparams(int sock);
 
 struct devsw netdev = {
 	.dv_name = "net",
@@ -118,7 +119,6 @@ net_init(void)
 static int
 net_open(struct open_file *f, ...)
 {
-	struct iodesc *d;
 	va_list args;
 	struct devdesc *dev;
 	const char *devname;	/* Device part of file name (or NULL). */
@@ -161,38 +161,36 @@ 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);
-		setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 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.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];
-			snprintf(mtu, sizeof(mtu), "%u", intf_mtu);
-			setenv("boot.netif.mtu", mtu, 1);
-		}
-
-		DEBUG_PRINTF(1,("%s: netproto=%d\n", __func__, netproto));
+		net_setparams(netdev_sock);
 	}
 	netdev_opens++;
 	dev->d_opendata = &netdev_sock;
 	return (error);
 }
 
+/*
+ * Configure a network interface without opening a file on it.  This is used
+ * by consumers which need DHCP configuration before switching to a firmware
+ * network protocol.
+ */
+int
+net_configure(struct devdesc *dev)
+{
+	int error, sock;
+
+	sock = netif_open(dev);
+	if (sock < 0)
+		return (ENXIO);
+
+	error = 0;
+	if (rootip.s_addr == 0)
+		error = net_getparams(sock);
+	if (error == 0)
+		net_setparams(sock);
+	netif_close(sock);
+	return (error);
+}
+
 static int
 net_close(struct open_file *f)
 {
@@ -319,6 +317,37 @@ exit:
 	return (0);
 }
 
+static void
+net_setparams(int sock)
+{
+	struct iodesc *d;
+
+	/*
+	 * Set the variables required by the kernel's nfs_diskless mechanism.
+	 */
+	d = socktodesc(sock);
+	setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 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.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];
+
+		snprintf(mtu, sizeof(mtu), "%u", intf_mtu);
+		setenv("boot.netif.mtu", mtu, 1);
+	}
+
+	DEBUG_PRINTF(1,("%s: netproto=%d\n", __func__, netproto));
+}
+
 static int
 net_print(int verbose)
 {
diff --git a/stand/common/dev_net.h b/stand/common/dev_net.h
index 189508854dc5..5cf6652c96af 100644
--- a/stand/common/dev_net.h
+++ b/stand/common/dev_net.h
@@ -29,6 +29,7 @@
 
 extern struct devsw netdev;
 
+int net_configure(struct devdesc *);
 uint32_t net_parse_rootpath(void);
 
 #endif