Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Apr 2018 20:04:06 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r332418 - in user/markj/netdump: . lib/libifconfig lib/libufs sbin/etherswitchcfg sbin/ifconfig share/man/man4 stand/efi/include stand/efi/libefi stand/efi/loader stand/forth stand/i386...
Message-ID:  <201804112004.w3BK46PL099026@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Wed Apr 11 20:04:06 2018
New Revision: 332418
URL: https://svnweb.freebsd.org/changeset/base/332418

Log:
  MFH at r332417.

Deleted:
  user/markj/netdump/share/man/man4/fpa.4
  user/markj/netdump/sys/dev/pdq/if_fpa.c
  user/markj/netdump/sys/dev/pdq/pdq.c
  user/markj/netdump/sys/dev/pdq/pdq_freebsd.h
  user/markj/netdump/sys/dev/pdq/pdq_ifsubr.c
  user/markj/netdump/sys/dev/pdq/pdqreg.h
  user/markj/netdump/sys/dev/pdq/pdqvar.h
  user/markj/netdump/sys/net/fddi.h
  user/markj/netdump/sys/net/if_fddisubr.c
Modified:
  user/markj/netdump/ObsoleteFiles.inc
  user/markj/netdump/UPDATING
  user/markj/netdump/lib/libifconfig/libifconfig_media.c
  user/markj/netdump/lib/libufs/inode.c
  user/markj/netdump/sbin/etherswitchcfg/ifmedia.c
  user/markj/netdump/sbin/ifconfig/ifmedia.c
  user/markj/netdump/share/man/man4/Makefile
  user/markj/netdump/stand/efi/include/efilib.h
  user/markj/netdump/stand/efi/include/efizfs.h
  user/markj/netdump/stand/efi/libefi/efipart.c
  user/markj/netdump/stand/efi/libefi/efizfs.c
  user/markj/netdump/stand/efi/loader/main.c
  user/markj/netdump/stand/forth/efi.4th
  user/markj/netdump/stand/forth/loader.4th
  user/markj/netdump/stand/forth/loader.rc
  user/markj/netdump/stand/i386/loader/loader.rc
  user/markj/netdump/sys/conf/NOTES
  user/markj/netdump/sys/conf/files
  user/markj/netdump/sys/dev/bnxt/bnxt_txrx.c
  user/markj/netdump/sys/dev/e1000/em_txrx.c
  user/markj/netdump/sys/dev/e1000/igb_txrx.c
  user/markj/netdump/sys/dev/ixgbe/ix_txrx.c
  user/markj/netdump/sys/net/if.c
  user/markj/netdump/sys/net/if_bridge.c
  user/markj/netdump/sys/net/if_media.c
  user/markj/netdump/sys/net/iflib.c
  user/markj/netdump/sys/netinet/if_ether.c
  user/markj/netdump/sys/netinet/ip_carp.c
  user/markj/netdump/sys/netinet6/in6.c
  user/markj/netdump/sys/netinet6/in6_ifattach.c
  user/markj/netdump/sys/netinet6/nd6.c
  user/markj/netdump/sys/netinet6/nd6_nbr.c
  user/markj/netdump/sys/nfs/bootp_subr.c
  user/markj/netdump/usr.bin/clang/clang/clang.1
Directory Properties:
  user/markj/netdump/   (props changed)

Modified: user/markj/netdump/ObsoleteFiles.inc
==============================================================================
--- user/markj/netdump/ObsoleteFiles.inc	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/ObsoleteFiles.inc	Wed Apr 11 20:04:06 2018	(r332418)
@@ -38,6 +38,8 @@
 #   xargs -n1 | sort | uniq -d;
 # done
 
+# 20180409: remove FDDI support
+OLD_FILES+=usr/include/net/fddi.h
 # 20180319: remove /boot/overlays, replaced by /boot/dtb/overlays
 OLD_DIRS+=boot/overlays
 # 20180311: remove sys/sys/i386/include/pcaudioio.h

Modified: user/markj/netdump/UPDATING
==============================================================================
--- user/markj/netdump/UPDATING	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/UPDATING	Wed Apr 11 20:04:06 2018	(r332418)
@@ -51,6 +51,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
 
 ****************************** SPECIAL WARNING: ******************************
 
+20180411:
+	Support for FDDI networks has been removed.  If you have device
+	fddi or device fpa in your kernel config file they must be
+	removed.
+	
 20180406:
 	In addition to supporting RFC 3164 formatted messages, the
 	syslogd(8) service is now capable of parsing RFC 5424 formatted

Modified: user/markj/netdump/lib/libifconfig/libifconfig_media.c
==============================================================================
--- user/markj/netdump/lib/libifconfig/libifconfig_media.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/lib/libifconfig/libifconfig_media.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -86,15 +86,6 @@ static struct ifmedia_description ifm_subtype_tokenrin
 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
     IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
 
-static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
-    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
-
-static struct ifmedia_description ifm_subtype_fddi_aliases[] =
-    IFM_SUBTYPE_FDDI_ALIASES;
-
-static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
-    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
-
 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
     IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
 
@@ -182,24 +173,6 @@ static struct ifmedia_type_to_subtype ifmedia_types_to
 			{ &ifm_shared_option_descriptions[0],		 0 },
 			{ &ifm_shared_option_aliases[0],		 1 },
 			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
-			{ NULL,						 0 },
-		},
-		{
-			{ NULL,						 0 },
-		},
-	},
-	{
-		{
-			{ &ifm_subtype_shared_descriptions[0],		 0 },
-			{ &ifm_subtype_shared_aliases[0],		 1 },
-			{ &ifm_subtype_fddi_descriptions[0],		 0 },
-			{ &ifm_subtype_fddi_aliases[0],			 1 },
-			{ NULL,						 0 },
-		},
-		{
-			{ &ifm_shared_option_descriptions[0],		 0 },
-			{ &ifm_shared_option_aliases[0],		 1 },
-			{ &ifm_subtype_fddi_option_descriptions[0],	 0 },
 			{ NULL,						 0 },
 		},
 		{

Modified: user/markj/netdump/lib/libufs/inode.c
==============================================================================
--- user/markj/netdump/lib/libufs/inode.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/lib/libufs/inode.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -60,7 +60,7 @@ getino(struct uufsd *disk, void **dino, ino_t inode, i
 	ERROR(disk, NULL);
 
 	fs = &disk->d_fs;
-	if (inode >= fs->fs_ipg * fs->fs_ncg) {
+	if (inode >= (ino_t)fs->fs_ipg * fs->fs_ncg) {
 		ERROR(disk, "inode number out of range");
 		return (-1);
 	}

Modified: user/markj/netdump/sbin/etherswitchcfg/ifmedia.c
==============================================================================
--- user/markj/netdump/sbin/etherswitchcfg/ifmedia.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sbin/etherswitchcfg/ifmedia.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -380,15 +380,6 @@ static struct ifmedia_description ifm_subtype_tokenrin
 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
     IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
 
-static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
-    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
-
-static struct ifmedia_description ifm_subtype_fddi_aliases[] =
-    IFM_SUBTYPE_FDDI_ALIASES;
-
-static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
-    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
-
 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
     IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
 
@@ -472,24 +463,6 @@ static struct ifmedia_type_to_subtype ifmedia_types_to
 			{ &ifm_shared_option_descriptions[0], 0 },
 			{ &ifm_shared_option_aliases[0], 1 },
 			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
-			{ NULL, 0 },
-		},
-		{
-			{ NULL, 0 },
-		},
-	},
-	{
-		{
-			{ &ifm_subtype_shared_descriptions[0], 0 },
-			{ &ifm_subtype_shared_aliases[0], 1 },
-			{ &ifm_subtype_fddi_descriptions[0], 0 },
-			{ &ifm_subtype_fddi_aliases[0], 1 },
-			{ NULL, 0 },
-		},
-		{
-			{ &ifm_shared_option_descriptions[0], 0 },
-			{ &ifm_shared_option_aliases[0], 1 },
-			{ &ifm_subtype_fddi_option_descriptions[0], 0 },
 			{ NULL, 0 },
 		},
 		{

Modified: user/markj/netdump/sbin/ifconfig/ifmedia.c
==============================================================================
--- user/markj/netdump/sbin/ifconfig/ifmedia.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sbin/ifconfig/ifmedia.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -397,15 +397,6 @@ static struct ifmedia_description ifm_subtype_tokenrin
 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
     IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
 
-static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
-    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
-
-static struct ifmedia_description ifm_subtype_fddi_aliases[] =
-    IFM_SUBTYPE_FDDI_ALIASES;
-
-static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
-    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
-
 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
     IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
 
@@ -489,24 +480,6 @@ static struct ifmedia_type_to_subtype ifmedia_types_to
 			{ &ifm_shared_option_descriptions[0], 0 },
 			{ &ifm_shared_option_aliases[0], 1 },
 			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
-			{ NULL, 0 },
-		},
-		{
-			{ NULL, 0 },
-		},
-	},
-	{
-		{
-			{ &ifm_subtype_shared_descriptions[0], 0 },
-			{ &ifm_subtype_shared_aliases[0], 1 },
-			{ &ifm_subtype_fddi_descriptions[0], 0 },
-			{ &ifm_subtype_fddi_aliases[0], 1 },
-			{ NULL, 0 },
-		},
-		{
-			{ &ifm_shared_option_descriptions[0], 0 },
-			{ &ifm_shared_option_aliases[0], 1 },
-			{ &ifm_subtype_fddi_option_descriptions[0], 0 },
 			{ NULL, 0 },
 		},
 		{

Modified: user/markj/netdump/share/man/man4/Makefile
==============================================================================
--- user/markj/netdump/share/man/man4/Makefile	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/share/man/man4/Makefile	Wed Apr 11 20:04:06 2018	(r332418)
@@ -170,7 +170,6 @@ MAN=	aac.4 \
 	ffclock.4 \
 	filemon.4 \
 	firewire.4 \
-	fpa.4 \
 	full.4 \
 	fwe.4 \
 	fwip.4 \

Modified: user/markj/netdump/stand/efi/include/efilib.h
==============================================================================
--- user/markj/netdump/stand/efi/include/efilib.h	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/efi/include/efilib.h	Wed Apr 11 20:04:06 2018	(r332418)
@@ -59,10 +59,13 @@ typedef struct pdinfo
 	uint32_t		pd_unit;	/* unit number */
 	uint32_t		pd_open;	/* reference counter */
 	void			*pd_bcache;	/* buffer cache data */
+	struct pdinfo		*pd_parent;	/* Linked items (eg partitions) */
+	struct devsw		*pd_devsw;	/* Back pointer to devsw */
 } pdinfo_t;
 
 pdinfo_list_t *efiblk_get_pdinfo_list(struct devsw *dev);
 pdinfo_t *efiblk_get_pdinfo(struct devdesc *dev);
+pdinfo_t *efiblk_get_pdinfo_by_handle(EFI_HANDLE h);
 
 void *efi_get_table(EFI_GUID *tbl);
 

Modified: user/markj/netdump/stand/efi/include/efizfs.h
==============================================================================
--- user/markj/netdump/stand/efi/include/efizfs.h	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/efi/include/efizfs.h	Wed Apr 11 20:04:06 2018	(r332418)
@@ -48,6 +48,7 @@ extern void efi_zfs_probe(void);
 extern zfsinfo_list_t *efizfs_get_zfsinfo_list(void);
 extern bool efi_zfs_is_preferred(EFI_HANDLE *h);
 extern EFI_HANDLE efizfs_get_handle_by_guid(uint64_t);
+extern bool efizfs_get_guid_by_handle(EFI_HANDLE, uint64_t *);
 
 #endif
 

Modified: user/markj/netdump/stand/efi/libefi/efipart.c
==============================================================================
--- user/markj/netdump/stand/efi/libefi/efipart.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/efi/libefi/efipart.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -119,6 +119,7 @@ efiblk_get_pdinfo_list(struct devsw *dev)
 	return (NULL);
 }
 
+/* XXX this gets called way way too often, investigate */
 pdinfo_t *
 efiblk_get_pdinfo(struct devdesc *dev)
 {
@@ -136,6 +137,40 @@ efiblk_get_pdinfo(struct devdesc *dev)
 	return (pd);
 }
 
+static bool
+same_handle(pdinfo_t *pd, EFI_HANDLE h)
+{
+
+	return (pd->pd_handle == h || pd->pd_alias == h);
+}
+
+pdinfo_t *
+efiblk_get_pdinfo_by_handle(EFI_HANDLE h)
+{
+	pdinfo_t *dp, *pp;
+
+	/*
+	 * Check hard disks, then cd, then floppy
+	 */
+	STAILQ_FOREACH(dp, &hdinfo, pd_link) {
+		if (same_handle(dp, h))
+			return (dp);
+		STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
+			if (same_handle(pp, h))
+				return (pp);
+		}
+	}
+	STAILQ_FOREACH(dp, &cdinfo, pd_link) {
+		if (same_handle(dp, h))
+			return (dp);
+	}
+	STAILQ_FOREACH(dp, &fdinfo, pd_link) {
+		if (same_handle(dp, h))
+			return (dp);
+	}
+	return (NULL);
+}
+
 static int
 efiblk_pdinfo_count(pdinfo_list_t *pdi)
 {
@@ -294,6 +329,8 @@ efipart_fdinfo_add(EFI_HANDLE handle, uint32_t uid, EF
 	fd->pd_unit = uid;
 	fd->pd_handle = handle;
 	fd->pd_devpath = devpath;
+	fd->pd_parent = NULL;
+	fd->pd_devsw = &efipart_fddev;
 	STAILQ_INSERT_TAIL(&fdinfo, fd, pd_link);
 	return (0);
 }
@@ -364,6 +401,8 @@ efipart_cdinfo_add(EFI_HANDLE handle, EFI_HANDLE alias
 	cd->pd_unit = unit;
 	cd->pd_alias = alias;
 	cd->pd_devpath = devpath;
+	cd->pd_parent = NULL;
+	cd->pd_devsw = &efipart_cddev;
 	STAILQ_INSERT_TAIL(&cdinfo, cd, pd_link);
 	return (0);
 }
@@ -489,6 +528,8 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE 
 			pd->pd_handle = part_handle;
 			pd->pd_unit = node->PartitionNumber;
 			pd->pd_devpath = part_devpath;
+			pd->pd_parent = hd;
+			pd->pd_devsw = &efipart_hddev;
 			STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
 			return (0);
 		}
@@ -505,6 +546,8 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE 
 	hd->pd_handle = disk_handle;
 	hd->pd_unit = unit;
 	hd->pd_devpath = disk_devpath;
+	hd->pd_parent = NULL;
+	hd->pd_devsw = &efipart_hddev;
 	STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link);
 
 	if (part_devpath == NULL)
@@ -521,6 +564,8 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE 
 	pd->pd_handle = part_handle;
 	pd->pd_unit = node->PartitionNumber;
 	pd->pd_devpath = part_devpath;
+	pd->pd_parent = hd;
+	pd->pd_devsw = &efipart_hddev;
 	STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
 
 	return (0);
@@ -579,6 +624,8 @@ efipart_hdinfo_add_filepath(EFI_HANDLE disk_handle)
 		pd->pd_handle = disk_handle;
 		pd->pd_unit = unit;
 		pd->pd_devpath = devpath;
+		pd->pd_parent = NULL;
+		pd->pd_devsw = &efipart_hddev;
 		STAILQ_INSERT_TAIL(&hdinfo, pd, pd_link);
 		free(pathname);
 		return (0);
@@ -609,6 +656,8 @@ efipart_hdinfo_add_filepath(EFI_HANDLE disk_handle)
 	pd->pd_handle = disk_handle;
 	pd->pd_unit = unit;
 	pd->pd_devpath = devpath;
+	pd->pd_parent = last;
+	pd->pd_devsw = &efipart_hddev;
 	STAILQ_INSERT_TAIL(&last->pd_part, pd, pd_link);
 	free(pathname);
 	return (0);

Modified: user/markj/netdump/stand/efi/libefi/efizfs.c
==============================================================================
--- user/markj/netdump/stand/efi/libefi/efizfs.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/efi/libefi/efizfs.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -64,6 +64,22 @@ efizfs_get_handle_by_guid(uint64_t guid)
 	return (NULL);
 }
 
+bool
+efizfs_get_guid_by_handle(EFI_HANDLE handle, uint64_t *guid)
+{
+	zfsinfo_t *zi;
+
+	if (guid == NULL)
+		return (false);
+	STAILQ_FOREACH(zi, &zfsinfo, zi_link) {
+		if (zi->zi_handle == handle) {
+			*guid = zi->zi_pool_guid;
+			return (true);
+		}
+	}
+	return (false);
+}
+
 static void
 insert_zfs(EFI_HANDLE handle, uint64_t guid)
 {

Modified: user/markj/netdump/stand/efi/loader/main.c
==============================================================================
--- user/markj/netdump/stand/efi/loader/main.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/efi/loader/main.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -78,6 +78,15 @@ EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
 
 static EFI_LOADED_IMAGE *img;
 
+/*
+ * Number of seconds to wait for a keystroke before exiting with failure
+ * in the event no currdev is found. -2 means always break, -1 means
+ * never break, 0 means poll once and then reboot, > 0 means wait for
+ * that many seconds. "fail_timeout" can be set in the environment as
+ * well.
+ */
+static int fail_timeout = 5;
+
 #ifdef	EFI_ZFS_BOOT
 bool
 efi_zfs_is_preferred(EFI_HANDLE *h)
@@ -169,113 +178,183 @@ out:
 }
 
 static void
-set_devdesc_currdev(struct devsw *dev, int unit)
+set_currdev_devdesc(struct devdesc *currdev)
 {
+	const char *devname;
+
+	devname = efi_fmtdev(currdev);
+
+	printf("Setting currdev to %s\n", devname);
+
+	env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev, env_nounset);
+	env_setenv("loaddev", EV_VOLATILE, devname, env_noset, env_nounset);
+}
+
+static void
+set_currdev_devsw(struct devsw *dev, int unit)
+{
 	struct devdesc currdev;
-	char *devname;
 
 	currdev.d_dev = dev;
 	currdev.d_unit = unit;
+
+	set_currdev_devdesc(&currdev);
+}
+
+static void
+set_currdev_pdinfo(pdinfo_t *dp)
+{
+
+	/*
+	 * Disks are special: they have partitions. if the parent
+	 * pointer is non-null, we're a partition not a full disk
+	 * and we need to adjust currdev appropriately.
+	 */
+	if (dp->pd_devsw->dv_type == DEVT_DISK) {
+		struct disk_devdesc currdev;
+
+		currdev.dd.d_dev = dp->pd_devsw;
+		if (dp->pd_parent == NULL) {
+			currdev.dd.d_unit = dp->pd_unit;
+			currdev.d_slice = -1;
+			currdev.d_partition = -1;
+		} else {
+			currdev.dd.d_unit = dp->pd_parent->pd_unit;
+			currdev.d_slice = dp->pd_unit;
+			currdev.d_partition = 255;	/* Assumes GPT */
+		}
+		set_currdev_devdesc((struct devdesc *)&currdev);
+	} else {
+		set_currdev_devsw(dp->pd_devsw, dp->pd_unit);
+	}
+}
+
+static bool
+sanity_check_currdev(void)
+{
+	struct stat st;
+
+	return (stat("/boot/defaults/loader.conf", &st) == 0);
+}
+
+#ifdef EFI_ZFS_BOOT
+static bool
+probe_zfs_currdev(uint64_t guid)
+{
+	char *devname;
+	struct zfs_devdesc currdev;
+
+	currdev.dd.d_dev = &zfs_dev;
+	currdev.dd.d_unit = 0;
+	currdev.pool_guid = guid;
+	currdev.root_guid = 0;
+	set_currdev_devdesc((struct devdesc *)&currdev);
 	devname = efi_fmtdev(&currdev);
+	init_zfs_bootenv(devname);
 
-	env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
-	    env_nounset);
-	env_setenv("loaddev", EV_VOLATILE, devname, env_noset, env_nounset);
+	return (sanity_check_currdev());
 }
+#endif
 
+static bool
+try_as_currdev(pdinfo_t *hd, pdinfo_t *pp)
+{
+	uint64_t guid;
+
+#ifdef EFI_ZFS_BOOT
+	/*
+	 * If there's a zpool on this device, try it as a ZFS
+	 * filesystem, which has somewhat different setup than all
+	 * other types of fs due to imperfect loader integration.
+	 * This all stems from ZFS being both a device (zpool) and
+	 * a filesystem, plus the boot env feature.
+	 */
+	if (efizfs_get_guid_by_handle(pp->pd_handle, &guid))
+		return (probe_zfs_currdev(guid));
+#endif
+	/*
+	 * All other filesystems just need the pdinfo
+	 * initialized in the standard way.
+	 */
+	set_currdev_pdinfo(pp);
+	return (sanity_check_currdev());
+}
+
 static int
 find_currdev(EFI_LOADED_IMAGE *img)
 {
-	pdinfo_list_t *pdi_list;
 	pdinfo_t *dp, *pp;
 	EFI_DEVICE_PATH *devpath, *copy;
 	EFI_HANDLE h;
-	char *devname;
+	CHAR16 *text;
 	struct devsw *dev;
 	int unit;
 	uint64_t extra;
 
 #ifdef EFI_ZFS_BOOT
-	/* Did efi_zfs_probe() detect the boot pool? */
+	/*
+	 * Did efi_zfs_probe() detect the boot pool? If so, use the zpool
+	 * it found, if it's sane. ZFS is the only thing that looks for
+	 * disks and pools to boot. This may change in the future, however,
+	 * if we allow specifying which pool to boot from via UEFI variables
+	 * rather than the bootenv stuff that FreeBSD uses today.
+	 */
 	if (pool_guid != 0) {
-		struct zfs_devdesc currdev;
-
-		currdev.dd.d_dev = &zfs_dev;
-		currdev.dd.d_unit = 0;
-		currdev.pool_guid = pool_guid;
-		currdev.root_guid = 0;
-		devname = efi_fmtdev(&currdev);
-
-		env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
-		    env_nounset);
-		env_setenv("loaddev", EV_VOLATILE, devname, env_noset,
-		    env_nounset);
-		init_zfs_bootenv(devname);
-		return (0);
+		printf("Trying ZFS pool\n");
+		if (probe_zfs_currdev(pool_guid))
+			return (0);
 	}
 #endif /* EFI_ZFS_BOOT */
 
-	/* We have device lists for hd, cd, fd, walk them all. */
-	pdi_list = efiblk_get_pdinfo_list(&efipart_hddev);
-	STAILQ_FOREACH(dp, pdi_list, pd_link) {
-		struct disk_devdesc currdev;
-
-		currdev.dd.d_dev = &efipart_hddev;
-		currdev.dd.d_unit = dp->pd_unit;
-		currdev.d_slice = -1;
-		currdev.d_partition = -1;
-
-		if (dp->pd_handle == img->DeviceHandle) {
-			devname = efi_fmtdev(&currdev);
-
-			env_setenv("currdev", EV_VOLATILE, devname,
-			    efi_setcurrdev, env_nounset);
-			env_setenv("loaddev", EV_VOLATILE, devname,
-			    env_noset, env_nounset);
-			return (0);
+	/*
+	 * Try to find the block device by its handle based on the
+	 * image we're booting. If we can't find a sane partition,
+	 * search all the other partitions of the disk. We do not
+	 * search other disks because it's a violation of the UEFI
+	 * boot protocol to do so. We fail and let UEFI go on to
+	 * the next candidate.
+	 */
+	dp = efiblk_get_pdinfo_by_handle(img->DeviceHandle);
+	if (dp != NULL) {
+		text = efi_devpath_name(dp->pd_devpath);
+		if (text != NULL) {
+			printf("Trying ESP: %S\n", text);
+			efi_free_devpath_name(text);
 		}
-		/* Assuming GPT partitioning. */
-		STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
-			if (pp->pd_handle == img->DeviceHandle) {
-				currdev.d_slice = pp->pd_unit;
-				currdev.d_partition = 255;
-				devname = efi_fmtdev(&currdev);
-
-				env_setenv("currdev", EV_VOLATILE, devname,
-				    efi_setcurrdev, env_nounset);
-				env_setenv("loaddev", EV_VOLATILE, devname,
-				    env_noset, env_nounset);
-				return (0);
+		set_currdev_pdinfo(dp);
+		if (sanity_check_currdev())
+			return (0);
+		if (dp->pd_parent != NULL) {
+			dp = dp->pd_parent;
+			STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
+				text = efi_devpath_name(pp->pd_devpath);
+				if (text != NULL) {
+					printf("And now the part: %S\n", text);
+					efi_free_devpath_name(text);
+				}
+				/*
+				 * Roll up the ZFS special case
+				 * for those partitions that have
+				 * zpools on them 
+				 */
+				if (try_as_currdev(dp, pp))
+					return (0);
 			}
 		}
+	} else {
+		printf("Can't find device by handle\n");
 	}
 
-	pdi_list = efiblk_get_pdinfo_list(&efipart_cddev);
-	STAILQ_FOREACH(dp, pdi_list, pd_link) {
-		if (dp->pd_handle == img->DeviceHandle ||
-		    dp->pd_alias == img->DeviceHandle) {
-			set_devdesc_currdev(&efipart_cddev, dp->pd_unit);
-			return (0);
-		}
-	}
-
-	pdi_list = efiblk_get_pdinfo_list(&efipart_fddev);
-	STAILQ_FOREACH(dp, pdi_list, pd_link) {
-		if (dp->pd_handle == img->DeviceHandle) {
-			set_devdesc_currdev(&efipart_fddev, dp->pd_unit);
-			return (0);
-		}
-	}
-
 	/*
 	 * Try the device handle from our loaded image first.  If that
 	 * fails, use the device path from the loaded image and see if
 	 * any of the nodes in that path match one of the enumerated
-	 * handles.
+	 * handles. Currently, this handle list is only for netboot.
 	 */
 	if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &extra) == 0) {
-		set_devdesc_currdev(dev, unit);
-		return (0);
+		set_currdev_devsw(dev, unit);
+		if (sanity_check_currdev())
+			return (0);
 	}
 
 	copy = NULL;
@@ -289,8 +368,9 @@ find_currdev(EFI_LOADED_IMAGE *img)
 		copy = NULL;
 
 		if (efi_handle_lookup(h, &dev, &unit, &extra) == 0) {
-			set_devdesc_currdev(dev, unit);
-			return (0);
+			set_currdev_devsw(dev, unit);
+			if (sanity_check_currdev())
+				return (0);
 		}
 
 		devpath = efi_lookup_devpath(h);
@@ -304,6 +384,33 @@ find_currdev(EFI_LOADED_IMAGE *img)
 	return (ENOENT);
 }
 
+static bool
+interactive_interrupt(const char *msg)
+{
+	time_t now, then, last;
+
+	last = 0;
+	now = then = getsecs();
+	printf("%s\n", msg);
+	if (fail_timeout == -2)		/* Always break to OK */
+		return (true);
+	if (fail_timeout == -1)		/* Never break to OK */
+		return (false);
+	do {
+		if (last != now) {
+			printf("press any key to interrupt reboot in %d seconds\r",
+			    fail_timeout - (int)(now - then));
+			last = now;
+		}
+
+		/* XXX no pause or timeout wait for char */
+		if (ischar())
+			return (true);
+		now = getsecs();
+	} while (now - then < fail_timeout);
+	return (false);
+}
+
 EFI_STATUS
 main(int argc, CHAR16 *argv[])
 {
@@ -312,12 +419,13 @@ main(int argc, CHAR16 *argv[])
 	int i, j, vargood, howto;
 	UINTN k;
 	int has_kbd;
+	char *s;
+	EFI_DEVICE_PATH *imgpath;
 	CHAR16 *text;
+	EFI_STATUS status;
 	UINT16 boot_current;
 	size_t sz;
 	UINT16 boot_order[100];
-	EFI_DEVICE_PATH *imgpath;
-	EFI_STATUS status;
 #if !defined(__arm__)
 	char buf[40];
 #endif
@@ -356,12 +464,15 @@ main(int argc, CHAR16 *argv[])
 	/*
 	 * Parse the args to set the console settings, etc
 	 * boot1.efi passes these in, if it can read /boot.config or /boot/config
-	 * or iPXE may be setup to pass these in.
+	 * or iPXE may be setup to pass these in. Or the optional argument in the
+	 * boot environment was used to pass these arguments in (in which case
+	 * neither /boot.config nor /boot/config are consulted).
 	 *
 	 * Loop through the args, and for each one that contains an '=' that is
 	 * not the first character, add it to the environment.  This allows
 	 * loader and kernel env vars to be passed on the command line.  Convert
-	 * args from UCS-2 to ASCII (16 to 8 bit) as they are copied.
+	 * args from UCS-2 to ASCII (16 to 8 bit) as they are copied (though this
+	 * method is flawed for non-ASCII characters).
 	 */
 	howto = 0;
 	for (i = 1; i < argc; i++) {
@@ -441,6 +552,10 @@ main(int argc, CHAR16 *argv[])
 	for (i = 0; howto_names[i].ev != NULL; i++)
 		if (howto & howto_names[i].mask)
 			setenv(howto_names[i].ev, "YES", 1);
+
+	/*
+	 * XXX we need fallback to this stuff after looking at the ConIn, ConOut and ConErr variables
+	 */
 	if (howto & RB_MULTIPLE) {
 		if (howto & RB_SERIAL)
 			setenv("console", "comconsole efi" , 1);
@@ -448,13 +563,17 @@ main(int argc, CHAR16 *argv[])
 			setenv("console", "efi comconsole" , 1);
 	} else if (howto & RB_SERIAL) {
 		setenv("console", "comconsole" , 1);
-	}
+	} else
+		setenv("console", "efi", 1);
 
 	if (efi_copy_init()) {
 		printf("failed to allocate staging area\n");
 		return (EFI_BUFFER_TOO_SMALL);
 	}
 
+	if ((s = getenv("fail_timeout")) != NULL)
+		fail_timeout = strtol(s, NULL, 10);
+
 	/*
 	 * Scan the BLOCK IO MEDIA handles then
 	 * march through the device switch probing for things.
@@ -479,6 +598,7 @@ main(int argc, CHAR16 *argv[])
 
 	printf("\n%s", bootprog_info);
 
+	/* Determine the devpath of our image so we can prefer it. */
 	text = efi_devpath_name(img->FilePath);
 	if (text != NULL) {
 		printf("   Load Path: %S\n", text);
@@ -520,8 +640,16 @@ main(int argc, CHAR16 *argv[])
 	 */
 	BS->SetWatchdogTimer(0, 0, 0, NULL);
 
+	/*
+	 * Try and find a good currdev based on the image that was booted.
+	 * It might be desirable here to have a short pause to allow falling
+	 * through to the boot loader instead of returning instantly to follow
+	 * the boot protocol and also allow an escape hatch for users wishing
+	 * to try something different.
+	 */
 	if (find_currdev(img) != 0)
-		return (EFI_NOT_FOUND);
+		if (!interactive_interrupt("Failed to find bootable partition"))
+			return (EFI_NOT_FOUND);
 
 	efi_init_environment();
 	setenv("LINES", "24", 1);	/* optional */

Modified: user/markj/netdump/stand/forth/efi.4th
==============================================================================
--- user/markj/netdump/stand/forth/efi.4th	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/forth/efi.4th	Wed Apr 11 20:04:06 2018	(r332418)
@@ -26,5 +26,16 @@
 
 only forth definitions
 
-s" efi-autoresizecons" evaluate
+: efiboot? ( -- flag )
+	s" efi-version" getenv -1 <> dup if
+		swap drop ( c-addr flag -- flag )
+	then
+;
+
+: maybe-efi-resizecons
+	efiboot? if
+		s" efi-autoresizecons" evaluate
+	then
+;
+
 .( EFI boot environment) cr

Modified: user/markj/netdump/stand/forth/loader.4th
==============================================================================
--- user/markj/netdump/stand/forth/loader.4th	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/forth/loader.4th	Wed Apr 11 20:04:06 2018	(r332418)
@@ -46,9 +46,6 @@ include /boot/support.4th
 include /boot/color.4th
 include /boot/delay.4th
 include /boot/check-password.4th
-s" efi-version" getenv? [if]
-	include /boot/efi.4th
-[then]
 
 only forth definitions
 

Modified: user/markj/netdump/stand/forth/loader.rc
==============================================================================
--- user/markj/netdump/stand/forth/loader.rc	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/forth/loader.rc	Wed Apr 11 20:04:06 2018	(r332418)
@@ -6,11 +6,14 @@
 \
 \ Includes additional commands
 include /boot/loader.4th
+include /boot/efi.4th
 try-include /boot/loader.rc.local
 
 \ Reads and processes loader.conf variables
 \ NOTE: Change to `initialize' if you enable the below boot menu
 start
+
+maybe-efi-resizecons
 
 \ Tests for password -- executes autoboot first if a password was defined
 check-password

Modified: user/markj/netdump/stand/i386/loader/loader.rc
==============================================================================
--- user/markj/netdump/stand/i386/loader/loader.rc	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/stand/i386/loader/loader.rc	Wed Apr 11 20:04:06 2018	(r332418)
@@ -3,10 +3,13 @@
 \
 \ Includes additional commands
 include /boot/loader.4th
+include /boot/efi.4th
 try-include /boot/loader.rc.local
 
 \ Reads and processes loader.conf variables
 initialize
+
+maybe-efi-resizecons
 
 \ Tests for password -- executes autoboot first if a password was defined
 check-password

Modified: user/markj/netdump/sys/conf/NOTES
==============================================================================
--- user/markj/netdump/sys/conf/NOTES	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sys/conf/NOTES	Wed Apr 11 20:04:06 2018	(r332418)
@@ -845,9 +845,6 @@ device		wlan_xauth
 device		wlan_acl
 device		wlan_amrr
 
-#  The `fddi' device provides generic code to support FDDI.
-device		fddi
-
 #  The `arcnet' device provides generic code to support Arcnet.
 device		arcnet
 
@@ -1975,7 +1972,6 @@ device		xmphy		# XaQti XMAC II
 # ex:   Intel EtherExpress Pro/10 and other i82595-based adapters,
 #       Olicom Ethernet PC Card devices.
 # fe:   Fujitsu MB86960A/MB86965A Ethernet
-# fpa:  Support for the Digital DEFPA PCI FDDI. `device fddi' is also needed.
 # fxp:  Intel EtherExpress Pro/100B
 #	(hint of prefer_iomap can be done to prefer I/O instead of Mem mapping)
 # gem:  Apple GMAC/Sun ERI/Sun GEM
@@ -2152,9 +2148,6 @@ device		ti		# Alteon Networks Tigon I/II gigabit Ether
 device		txp		# 3Com 3cR990 (``Typhoon'')
 device		vx		# 3Com 3c590, 3c595 (``Vortex'')
 device		vxge		# Exar/Neterion XFrame 3100 10GbE
-
-# PCI FDDI NICs.
-device		fpa
 
 # PCI WAN adapters.
 device		lmc

Modified: user/markj/netdump/sys/conf/files
==============================================================================
--- user/markj/netdump/sys/conf/files	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sys/conf/files	Wed Apr 11 20:04:06 2018	(r332418)
@@ -2642,9 +2642,6 @@ dev/pci/pcib_if.m		standard
 dev/pci/pcib_support.c		standard
 dev/pci/vga_pci.c		optional pci
 dev/pcn/if_pcn.c		optional pcn pci
-dev/pdq/if_fpa.c		optional fpa pci
-dev/pdq/pdq.c			optional nowerror fpa pci
-dev/pdq/pdq_ifsubr.c		optional nowerror fpa pci
 dev/pms/freebsd/driver/ini/src/agtiapi.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sadisc.c			optional pmspcv \
@@ -4130,7 +4127,6 @@ net/if_edsc.c			optional edsc
 net/if_enc.c			optional enc inet | enc inet6
 net/if_epair.c			optional epair
 net/if_ethersubr.c		optional ether
-net/if_fddisubr.c		optional fddi
 net/if_fwsubr.c			optional fwip
 net/if_gif.c			optional gif inet | gif inet6 | \
 					 netgraph_gif inet | netgraph_gif inet6

Modified: user/markj/netdump/sys/dev/bnxt/bnxt_txrx.c
==============================================================================
--- user/markj/netdump/sys/dev/bnxt/bnxt_txrx.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sys/dev/bnxt/bnxt_txrx.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -66,14 +66,14 @@ static int bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_
 static int bnxt_intr(void *sc);
 
 struct if_txrx bnxt_txrx  = {
-	bnxt_isc_txd_encap,
-	bnxt_isc_txd_flush,
-	bnxt_isc_txd_credits_update,
-	bnxt_isc_rxd_available,
-	bnxt_isc_rxd_pkt_get,
-	bnxt_isc_rxd_refill,
-	bnxt_isc_rxd_flush,
-	bnxt_intr
+	.ift_txd_encap = bnxt_isc_txd_encap,
+	.ift_txd_flush = bnxt_isc_txd_flush,
+	.ift_txd_credits_update = bnxt_isc_txd_credits_update,
+	.ift_rxd_available = bnxt_isc_rxd_available,
+	.ift_rxd_pkt_get = bnxt_isc_rxd_pkt_get,
+	.ift_rxd_refill = bnxt_isc_rxd_refill,
+	.ift_rxd_flush = bnxt_isc_rxd_flush,
+	.ift_legacy_intr = bnxt_intr
 };
 
 /*

Modified: user/markj/netdump/sys/dev/e1000/em_txrx.c
==============================================================================
--- user/markj/netdump/sys/dev/e1000/em_txrx.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sys/dev/e1000/em_txrx.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -68,25 +68,25 @@ static int em_determine_rsstype(u32 pkt_info);
 extern int em_intr(void *arg);
 
 struct if_txrx em_txrx = {
-	em_isc_txd_encap,
-	em_isc_txd_flush,
-	em_isc_txd_credits_update,
-	em_isc_rxd_available,
-	em_isc_rxd_pkt_get,
-	em_isc_rxd_refill,
-	em_isc_rxd_flush,
-	em_intr
+	.ift_txd_encap = em_isc_txd_encap,
+	.ift_txd_flush = em_isc_txd_flush,
+	.ift_txd_credits_update = em_isc_txd_credits_update,
+	.ift_rxd_available = em_isc_rxd_available,
+	.ift_rxd_pkt_get = em_isc_rxd_pkt_get,
+	.ift_rxd_refill = em_isc_rxd_refill,
+	.ift_rxd_flush = em_isc_rxd_flush,
+	.ift_legacy_intr = em_intr
 };
 
 struct if_txrx lem_txrx = {
-	em_isc_txd_encap,
-	em_isc_txd_flush,
-	em_isc_txd_credits_update,
-	lem_isc_rxd_available,
-	lem_isc_rxd_pkt_get,
-	lem_isc_rxd_refill,
-	em_isc_rxd_flush,
-	em_intr
+	.ift_txd_encap = em_isc_txd_encap,
+	.ift_txd_flush = em_isc_txd_flush,
+	.ift_txd_credits_update = em_isc_txd_credits_update,
+	.ift_rxd_available = lem_isc_rxd_available,
+	.ift_rxd_pkt_get = lem_isc_rxd_pkt_get,
+	.ift_rxd_refill = lem_isc_rxd_refill,
+	.ift_rxd_flush = em_isc_rxd_flush,
+	.ift_legacy_intr = em_intr
 };
 
 extern if_shared_ctx_t em_sctx;

Modified: user/markj/netdump/sys/dev/e1000/igb_txrx.c
==============================================================================
--- user/markj/netdump/sys/dev/e1000/igb_txrx.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sys/dev/e1000/igb_txrx.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -62,14 +62,14 @@ extern void igb_if_enable_intr(if_ctx_t ctx);
 extern int em_intr(void *arg);
 
 struct if_txrx igb_txrx = {
-	igb_isc_txd_encap,
-	igb_isc_txd_flush,
-	igb_isc_txd_credits_update,
-	igb_isc_rxd_available,
-	igb_isc_rxd_pkt_get,
-	igb_isc_rxd_refill,
-	igb_isc_rxd_flush,
-	em_intr
+	.ift_txd_encap = igb_isc_txd_encap,
+	.ift_txd_flush = igb_isc_txd_flush,
+	.ift_txd_credits_update = igb_isc_txd_credits_update,
+	.ift_rxd_available = igb_isc_rxd_available,
+	.ift_rxd_pkt_get = igb_isc_rxd_pkt_get,
+	.ift_rxd_refill = igb_isc_rxd_refill,
+	.ift_rxd_flush = igb_isc_rxd_flush,
+	.ift_legacy_intr = em_intr
 };
 
 extern if_shared_ctx_t em_sctx;

Modified: user/markj/netdump/sys/dev/ixgbe/ix_txrx.c
==============================================================================
--- user/markj/netdump/sys/dev/ixgbe/ix_txrx.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sys/dev/ixgbe/ix_txrx.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -62,14 +62,14 @@ extern void ixgbe_if_enable_intr(if_ctx_t ctx);
 static int ixgbe_determine_rsstype(u16 pkt_info);
 
 struct if_txrx ixgbe_txrx  = {
-	ixgbe_isc_txd_encap,
-	ixgbe_isc_txd_flush,
-	ixgbe_isc_txd_credits_update,
-	ixgbe_isc_rxd_available,
-	ixgbe_isc_rxd_pkt_get,
-	ixgbe_isc_rxd_refill,
-	ixgbe_isc_rxd_flush,
-	NULL
+	.ift_txd_encap = ixgbe_isc_txd_encap,
+	.ift_txd_flush = ixgbe_isc_txd_flush,
+	.ift_txd_credits_update = ixgbe_isc_txd_credits_update,
+	.ift_rxd_available = ixgbe_isc_rxd_available,
+	.ift_rxd_pkt_get = ixgbe_isc_rxd_pkt_get,
+	.ift_rxd_refill = ixgbe_isc_rxd_refill,
+	.ift_rxd_flush = ixgbe_isc_rxd_flush,
+	.ift_legacy_intr = NULL
 };
 
 extern if_shared_ctx_t ixgbe_sctx;

Modified: user/markj/netdump/sys/net/if.c
==============================================================================
--- user/markj/netdump/sys/net/if.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sys/net/if.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -3696,7 +3696,6 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, 
 	}
 	switch (ifp->if_type) {
 	case IFT_ETHER:
-	case IFT_FDDI:
 	case IFT_XETHER:
 	case IFT_L2VLAN:
 	case IFT_BRIDGE:

Modified: user/markj/netdump/sys/net/if_bridge.c
==============================================================================
--- user/markj/netdump/sys/net/if_bridge.c	Wed Apr 11 20:02:24 2018	(r332417)
+++ user/markj/netdump/sys/net/if_bridge.c	Wed Apr 11 20:04:06 2018	(r332418)
@@ -72,8 +72,8 @@
  *
  *	- Currently only supports Ethernet-like interfaces (Ethernet,
  *	  802.11, VLANs on Ethernet, etc.)  Figure out a nice way

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804112004.w3BK46PL099026>