Module Name:    src
Committed By:   martin
Date:           Fri Sep 27 09:32:22 UTC 2019

Modified Files:
        src/sys/arch/i386/stand/efiboot [netbsd-9]: boot.c conf.c dev_net.c
            devopen.c devopen.h

Log Message:
Pull up following revision(s) (requested by nonaka in ticket #253):

        sys/arch/i386/stand/efiboot/conf.c: revision 1.3
        sys/arch/i386/stand/efiboot/devopen.h: revision 1.5
        sys/arch/i386/stand/efiboot/devopen.c: revision 1.8
        sys/arch/i386/stand/efiboot/boot.c: revision 1.17
        sys/arch/i386/stand/efiboot/dev_net.c: revision 1.3

x86 efiboot: pass a filename to BOOTP and parse a DHCP server provided filename.


To generate a diff of this commit:
cvs rdiff -u -r1.13.2.2 -r1.13.2.3 src/sys/arch/i386/stand/efiboot/boot.c
cvs rdiff -u -r1.2 -r1.2.6.1 src/sys/arch/i386/stand/efiboot/conf.c
cvs rdiff -u -r1.2 -r1.2.2.1 src/sys/arch/i386/stand/efiboot/dev_net.c
cvs rdiff -u -r1.5.6.1 -r1.5.6.2 src/sys/arch/i386/stand/efiboot/devopen.c
cvs rdiff -u -r1.3.6.1 -r1.3.6.2 src/sys/arch/i386/stand/efiboot/devopen.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/i386/stand/efiboot/boot.c
diff -u src/sys/arch/i386/stand/efiboot/boot.c:1.13.2.2 src/sys/arch/i386/stand/efiboot/boot.c:1.13.2.3
--- src/sys/arch/i386/stand/efiboot/boot.c:1.13.2.2	Tue Sep 17 19:32:00 2019
+++ src/sys/arch/i386/stand/efiboot/boot.c	Fri Sep 27 09:32:22 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: boot.c,v 1.13.2.2 2019/09/17 19:32:00 martin Exp $	*/
+/*	$NetBSD: boot.c,v 1.13.2.3 2019/09/27 09:32:22 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -111,6 +111,7 @@ const struct bootblk_command commands[] 
 	{ NULL,		NULL },
 };
 
+static char *default_fsname;
 static char *default_devname;
 static int default_unit, default_partition;
 static const char *default_filename;
@@ -125,8 +126,11 @@ parsebootfile(const char *fname, char **
 {
 	const char *col;
 	static char savedevname[MAXDEVNAME+1];
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
+	const struct netboot_fstab *nf;
+#endif
 
-	*fsname = "ufs";
+	*fsname = default_fsname;
 	if (default_part_name == NULL) {
 		*devname = default_devname;
 	} else {
@@ -152,6 +156,7 @@ parsebootfile(const char *fname, char **
 
 		if (strstr(fname, "NAME=") == fname) {
 			strlcpy(savedevname, fname, devlen + 1);
+			*fsname = "ufs";
 			*devname = savedevname;
 			*unit = -1;
 			*partition = -1;
@@ -188,6 +193,13 @@ parsebootfile(const char *fname, char **
 		if (i != devlen)
 			return ENXIO;
 
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
+		nf = netboot_fstab_find(savedevname);
+		if (nf != NULL)
+			*fsname = (char *)nf->name;
+		else
+#endif
+		*fsname = "ufs";
 		*devname = savedevname;
 		*unit = u;
 		*partition = p;
@@ -278,6 +290,9 @@ boot(void)
 {
 	int currname;
 	int c;
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
+	const struct netboot_fstab *nf;
+#endif
 
 	boot_modules_enabled = !(boot_params.bp_flags & X86_BP_FLAGS_NOMODULES);
 
@@ -288,6 +303,14 @@ boot(void)
 	/* if the user types "boot" without filename */
 	default_filename = DEFFILENAME;
 
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
+	nf = netboot_fstab_find(default_devname);
+	if (nf != NULL)
+		default_fsname = (char *)nf->name;
+	else
+#endif
+	default_fsname = "ufs";
+
 	if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
 #ifdef EFIBOOTCFG_FILENAME
 		int rv = EINVAL;
@@ -456,7 +479,7 @@ command_dev(char *arg)
 {
 	static char savedevname[MAXDEVNAME + 1];
 	char buf[80];
-	char *fsname, *devname;
+	char *devname;
 	const char *file; /* dummy */
 
 	if (*arg == '\0') {
@@ -474,7 +497,7 @@ command_dev(char *arg)
 	}
 
 	if (strchr(arg, ':') == NULL ||
-	    parsebootfile(arg, &fsname, &devname, &default_unit,
+	    parsebootfile(arg, &default_fsname, &devname, &default_unit,
 	      &default_partition, &file)) {
 		command_help(NULL);
 		return;

Index: src/sys/arch/i386/stand/efiboot/conf.c
diff -u src/sys/arch/i386/stand/efiboot/conf.c:1.2 src/sys/arch/i386/stand/efiboot/conf.c:1.2.6.1
--- src/sys/arch/i386/stand/efiboot/conf.c:1.2	Wed Apr 11 10:32:09 2018
+++ src/sys/arch/i386/stand/efiboot/conf.c	Fri Sep 27 09:32:22 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: conf.c,v 1.2 2018/04/11 10:32:09 nonaka Exp $	 */
+/*	$NetBSD: conf.c,v 1.2.6.1 2019/09/27 09:32:22 martin Exp $	 */
 
 /*
  * Copyright (c) 1997
@@ -54,20 +54,23 @@
 #endif
 #endif
 #include <biosdisk.h>
+#include "devopen.h"
 #include "efinet.h"
 
 struct devsw devsw[] = {
 	{ "disk", biosdisk_strategy, biosdisk_open, biosdisk_close, biosdisk_ioctl },
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
 	{ "net", net_strategy, net_open, net_close, net_ioctl },
+#endif
 };
 int ndevs = __arraycount(devsw);
 
-#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
 struct netif_driver *netif_drivers[] = {
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
 	&efinetif,
+#endif
 };
 int n_netif_drivers = __arraycount(netif_drivers);
-#endif
 
 struct fs_ops file_system[] = {
 #ifdef SUPPORT_CD9660
@@ -113,3 +116,15 @@ struct fs_ops file_system_nfs = FS_OPS(n
 #ifdef SUPPORT_TFTP
 struct fs_ops file_system_tftp = FS_OPS(tftp);
 #endif
+
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
+const struct netboot_fstab netboot_fstab[] = {
+#ifdef SUPPORT_NFS
+	{ "nfs", &file_system_nfs },
+#endif
+#ifdef SUPPORT_TFTP
+	{ "tftp", &file_system_tftp },
+#endif
+};
+const int nnetboot_fstab = __arraycount(netboot_fstab);
+#endif

Index: src/sys/arch/i386/stand/efiboot/dev_net.c
diff -u src/sys/arch/i386/stand/efiboot/dev_net.c:1.2 src/sys/arch/i386/stand/efiboot/dev_net.c:1.2.2.1
--- src/sys/arch/i386/stand/efiboot/dev_net.c:1.2	Fri Jul 26 11:30:31 2019
+++ src/sys/arch/i386/stand/efiboot/dev_net.c	Fri Sep 27 09:32:22 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: dev_net.c,v 1.2 2019/07/26 11:30:31 nonaka Exp $	*/
+/*	$NetBSD: dev_net.c,v 1.2.2.1 2019/09/27 09:32:22 martin Exp $	*/
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -76,23 +76,23 @@ int
 net_open(struct open_file *f, ...)
 {
 	va_list ap;
-	char *devname;		/* Device part of file name (or NULL). */
+	struct devdesc *dev;
 	int error = 0;
 
 	va_start(ap, f);
-	devname = va_arg(ap, char *);
+	dev = va_arg(ap, struct devdesc *);
 	va_end(ap);
 
 #ifdef	NETIF_DEBUG
 	if (debug)
-		printf("%s\n", devname);
+		printf("%s\n", dev->devname);
 #endif
 
 	/* On first open, do netif open, mount, etc. */
 	if (netdev_opens == 0) {
 		/* Find network interface. */
 		if (netdev_sock < 0) {
-			netdev_sock = netif_open(devname);
+			netdev_sock = netif_open(dev);
 			if (netdev_sock < 0) {
 				printf("netif_open() failed\n");
 				return ENXIO;

Index: src/sys/arch/i386/stand/efiboot/devopen.c
diff -u src/sys/arch/i386/stand/efiboot/devopen.c:1.5.6.1 src/sys/arch/i386/stand/efiboot/devopen.c:1.5.6.2
--- src/sys/arch/i386/stand/efiboot/devopen.c:1.5.6.1	Fri Sep 13 07:00:13 2019
+++ src/sys/arch/i386/stand/efiboot/devopen.c	Fri Sep 27 09:32:22 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: devopen.c,v 1.5.6.1 2019/09/13 07:00:13 martin Exp $	 */
+/*	$NetBSD: devopen.c,v 1.5.6.2 2019/09/27 09:32:22 martin Exp $	 */
 
 /*-
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -57,6 +57,7 @@
 #include "efiboot.h"
 
 #include <lib/libsa/dev_net.h>
+#include <lib/libsa/net.h>
 
 #include <biosdisk.h>
 #include "devopen.h"
@@ -106,6 +107,40 @@ bios2dev(int biosdev, daddr_t sector, ch
 	}
 }
 
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
+const struct netboot_fstab *
+netboot_fstab_find(const char *name)
+{
+	int i;
+
+	if (strcmp(name, "net") == 0)
+		return &netboot_fstab[0];
+
+	for (i = 0; i < nnetboot_fstab; i++) {
+		if (strcmp(name, netboot_fstab[i].name) == 0)
+			return &netboot_fstab[i];
+	}
+
+	return NULL;
+}
+
+static const struct netboot_fstab *
+netboot_fstab_findn(const char *name, size_t len)
+{
+	int i;
+
+	if (strncmp(name, "net", len) == 0)
+		return &netboot_fstab[0];
+
+	for (i = 0; i < nnetboot_fstab; i++) {
+		if (strncmp(name, netboot_fstab[i].name, len) == 0)
+			return &netboot_fstab[i];
+	}
+
+	return NULL;
+}
+#endif
+
 struct btinfo_bootpath bibp;
 extern bool kernel_loaded;
 
@@ -115,28 +150,27 @@ extern bool kernel_loaded;
 int
 devopen(struct open_file *f, const char *fname, char **file)
 {
-#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
-	static const char *net_devnames[] = {
-#if defined(SUPPORT_NFS)
-	    "nfs",
-#endif
-#if defined(SUPPORT_TFTP)
-	    "tftp",
-#endif
-	};
-#endif
-	struct devdesc desc;
-	struct devsw *dev;
 	char *fsname, *devname;
 	int unit, partition;
 	int biosdev;
-	int i, n, error;
+	int i, error;
+#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
+	struct devdesc desc;
+	const struct netboot_fstab *nf;
+	char *filename;
+	size_t fsnamelen;
+	int n;
+#endif
 
 	error = parsebootfile(fname, &fsname, &devname, &unit, &partition,
 	    (const char **) file);
 	if (error)
 		return error;
 
+	memcpy(file_system, file_system_disk,
+	    sizeof(struct fs_ops) * nfsys_disk);
+	nfsys = nfsys_disk;
+
 	/* Search by GPT label or raidframe name */
 	if ((strstr(devname, "NAME=") == devname) ||
 	    (strstr(devname, "raid") == devname)) {
@@ -151,64 +185,99 @@ devopen(struct open_file *f, const char 
 		return error;
 	}
 
-	memcpy(file_system, file_system_disk, sizeof(*file_system) * nfsys);
-	nfsys = nfsys_disk;
-
+	/*
+	 * Network
+	 */
 #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
-	for (i = 0; i < __arraycount(net_devnames); i++) {
-		if (strcmp(devname, net_devnames[i]) == 0) {
-			fsname = devname;
-			devname = "net";
-			break;
+	nf = netboot_fstab_find(devname);
+	if (nf != NULL) {
+		n = 0;
+		if (strcmp(devname, "net") == 0) {
+			for (i = 0; i < nnetboot_fstab; i++) {
+				memcpy(&file_system[n++], netboot_fstab[i].ops,
+				    sizeof(struct fs_ops));
+			}
+		} else {
+			memcpy(&file_system[n++], nf->ops,
+			    sizeof(struct fs_ops));
 		}
-	}
-#endif
+		nfsys = n;
 
-	for (i = 1; i < ndevs; i++) {
-		dev = &devsw[i];
-		if (strcmp(devname, DEV_NAME(dev)) == 0) {
-			if (strcmp(devname, "net") == 0) {
-				n = 0;
-#if defined(SUPPORT_NFS)
-				if (strcmp(fsname, "nfs") == 0) {
-					memcpy(&file_system[n++], &file_system_nfs,
-					    sizeof(file_system_nfs));
-				} else
-#endif
-#if defined(SUPPORT_TFTP)
-				if (strcmp(fsname, "tftp") == 0) {
-					memcpy(&file_system[n++], &file_system_tftp,
-					    sizeof(file_system_tftp));
-				} else
-#endif
-				{
-#if defined(SUPPORT_NFS)
-					memcpy(&file_system[n++], &file_system_nfs,
-					    sizeof(file_system_nfs));
+#ifdef SUPPORT_BOOTP
+		try_bootp = 1;
 #endif
-#if defined(SUPPORT_TFTP)
-					memcpy(&file_system[n++], &file_system_tftp,
-					    sizeof(file_system_tftp));
-#endif
-				}
-				nfsys = n;
 
-				try_bootp = 1;
-			}
+		/* If we got passed a filename, pass it to the BOOTP server. */
+		if (fname) {
+			filename = strchr(fname, ':');
+			if (filename != NULL)
+				filename++;
+			else
+				filename = (char *)fname;
+			strlcpy(bootfile, filename, sizeof(bootfile));
+		}
 
-			memset(&desc, 0, sizeof(desc));
-			strlcpy(desc.d_name, devname, sizeof(desc.d_name));
-			desc.d_unit = unit;
-
-			f->f_dev = dev;
-			if (!kernel_loaded) {
-				strncpy(bibp.bootpath, *file,
-				    sizeof(bibp.bootpath));
-				BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
+		memset(&desc, 0, sizeof(desc));
+		strlcpy(desc.d_name, "net", sizeof(desc.d_name));
+		desc.d_unit = unit;
+
+		f->f_dev = &devsw[1];		/* must be net */
+		if (!kernel_loaded) {
+			strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath));
+			BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
+		}
+		error = DEV_OPEN(f->f_dev)(f, &desc);
+		if (error)
+			return error;
+
+		/*
+		 * If the DHCP server provided a file name:
+		 * - If it contains a ":", assume it points to a NetBSD kernel.
+		 * - If not, assume that the DHCP server was not able to pass
+		 *   a separate filename for the kernel. (The name probably was
+		 *   the same as used to load "efiboot".) Ignore it and use
+		 *   the default in this case.
+		 * So we cater to simple DHCP servers while being able to use
+		 * the power of conditional behaviour in modern ones.
+		 */
+		filename = strchr(bootfile, ':');
+		if (filename != NULL) {
+			fname = bootfile;
+
+			fsnamelen = filename - fname;
+			nf = netboot_fstab_findn(fname, fsnamelen);
+			if (nf == NULL ||
+			    strncmp(fname, "net", fsnamelen) == 0) {
+				printf("Invalid file system type specified in "
+				    "%s\n", fname);
+				error = EINVAL;
+				goto neterr;
 			}
-			return DEV_OPEN(f->f_dev)(f, &desc);
+
+			memcpy(file_system, nf->ops, sizeof(struct fs_ops));
+			nfsys = 1;
 		}
+
+		filename = fname ? strchr(fname, ':') : NULL;
+		if (filename != NULL) {
+			filename++;
+			if (*filename == '\0') {
+				printf("No file specified in %s\n", fname);
+				error = EINVAL;
+				goto neterr;
+			}
+		} else
+			filename = (char *)fname;
+
+		*file = filename;
+		return 0;
+
+neterr:
+		DEV_CLOSE(f->f_dev)(f);
+		f->f_dev = NULL;
+		return error;
 	}
+#endif
 
 	/*
 	 * biosdisk

Index: src/sys/arch/i386/stand/efiboot/devopen.h
diff -u src/sys/arch/i386/stand/efiboot/devopen.h:1.3.6.1 src/sys/arch/i386/stand/efiboot/devopen.h:1.3.6.2
--- src/sys/arch/i386/stand/efiboot/devopen.h:1.3.6.1	Fri Sep 13 07:00:13 2019
+++ src/sys/arch/i386/stand/efiboot/devopen.h	Fri Sep 27 09:32:22 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: devopen.h,v 1.3.6.1 2019/09/13 07:00:13 martin Exp $	*/
+/*	$NetBSD: devopen.h,v 1.3.6.2 2019/09/27 09:32:22 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -42,3 +42,13 @@ struct devdesc {
 	char	d_name[MAXDEVNAME];
 	char	d_unit;
 };
+
+struct netboot_fstab {
+	const char *name;
+	struct fs_ops *ops;
+};
+
+extern const struct netboot_fstab netboot_fstab[];
+extern const int nnetboot_fstab;
+
+const struct netboot_fstab *netboot_fstab_find(const char *);

Reply via email to