svn commit: r353988 - in stable/12/stand: efi efi/boot1 efi/gptboot efi/include efi/libefi i386/gptboot libsa

Kyle Evans kevans at FreeBSD.org
Thu Oct 24 03:16:26 UTC 2019


Author: kevans
Date: Thu Oct 24 03:16:23 2019
New Revision: 353988
URL: https://svnweb.freebsd.org/changeset/base/353988

Log:
  MFC r348658-r348659, r348674-r348675, r348678, r348760, r348766, r348768,
  r348811-r348812, r348814, r349008
  
  r348658:
  Introduce efi_devpath_same_disk
  
  This is like efi_devpath_match, but allows differing device media
  paths. Those just specify the partition information.
  
  r348659:
  Use newly minted efi_devpath_same_disk() instead of
  efi_devpath_match(). This fixes a regression in r347193.
  
  r348674:
  Don't shadow a global zfsmount variable.
  
  r348675:
  ufs_module.c can't currently be compiled with -Wcast-align, but the
  code is safe enough. Turn off the warning for now until I can find the
  right construct to silence it in the code.
  
  r348678:
  Eliminate unused uuid parameters from gptread and gptread_table.  We
  only need it for the gptfind() function, where it's used.
  
  r348760:
  Use simple malloc/free instead of dropping down to the UEFI
  BootServices AllocatePool/FreePool calls. They are simpler to use and
  result in the same thing happening.
  
  r348766:
  Remove left-over status variables
  
  r348768:
  Rework the reporting of the priority.
  
  Simplify the code a bit and rework how we report the results
  of the probing.
  
  r348811:
  Break out the disk selection protocol from the rest of boot1.
  
  Segregate the disk probing and selection protocol from the rest of the
  boot loader.
  
  r348812:
  Create gptboot.efi
  
  This is a primary boot loader that is intended to implement the
  gptboot partition selection algorithm just like we did for BIOS
  booting. While the preferred method for UEFI is to use the UEFI Boot
  Manager protocol, there are situations where that can't be done: some
  BIOS makers interfere with the protocol in unhelpful ways, there's a
  new standard for a zero variable write from the client OS, and finally
  for USB drives that might be mobile between systems with multiple
  partitions there needs to be a media stable way to select.
  
  r348814:
  Add stuff to disable warning for %S
  
  Add the customary warnings to disable format checking on armv7. Code
  move to new files, and the unconditional setting of WARNS to 6
  provoked it on tinerbox...
  
  r349008:
  Fix gcc build by removing redeclaration

Added:
  stable/12/stand/efi/boot1/proto.c
     - copied unchanged from r348812, head/stand/efi/boot1/proto.c
  stable/12/stand/efi/boot1/proto.h
     - copied unchanged from r348812, head/stand/efi/boot1/proto.h
  stable/12/stand/efi/gptboot/
     - copied from r348812, head/stand/efi/gptboot/
Modified:
  stable/12/stand/efi/Makefile
  stable/12/stand/efi/boot1/Makefile
  stable/12/stand/efi/boot1/boot1.c
  stable/12/stand/efi/boot1/boot_module.h
  stable/12/stand/efi/boot1/ufs_module.c
  stable/12/stand/efi/boot1/zfs_module.c
  stable/12/stand/efi/include/efilib.h
  stable/12/stand/efi/libefi/devpath.c
  stable/12/stand/i386/gptboot/gptboot.c
  stable/12/stand/libsa/gpt.c
  stable/12/stand/libsa/gpt.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/stand/efi/Makefile
==============================================================================
--- stable/12/stand/efi/Makefile	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/efi/Makefile	Thu Oct 24 03:16:23 2019	(r353988)
@@ -9,7 +9,7 @@ NO_OBJ=t
 .if ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 40500
 
 SUBDIR.${MK_FDT}+=	fdt
-SUBDIR.yes+=	libefi boot1
+SUBDIR.yes+=	libefi boot1 gptboot
 SUBDIR.${MK_FORTH}+= loader_4th
 SUBDIR.${MK_LOADER_LUA}+= loader_lua
 SUBDIR.yes+=	loader_simp

Modified: stable/12/stand/efi/boot1/Makefile
==============================================================================
--- stable/12/stand/efi/boot1/Makefile	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/efi/boot1/Makefile	Thu Oct 24 03:16:23 2019	(r353988)
@@ -5,7 +5,7 @@
 BOOT1?=		boot1
 PROG=		${BOOT1}.sym
 INTERNALPROG=
-WARNS?=		6
+WARNS=		6
 
 CFLAGS+=	-DEFI_BOOT1
 # We implement a slightly non-standard %S in that it always takes a
@@ -13,8 +13,13 @@ CFLAGS+=	-DEFI_BOOT1
 # seems to matter on arm64 where wchar_t defaults to an int instead
 # of a short. There's no good cast to use here so just ignore the
 # warnings for now.
+CWARNFLAGS.proto.c+=	-Wno-format
 CWARNFLAGS.boot1.c+=	-Wno-format
 
+# Disable bogus alignment issues
+CWARNFLAGS.ufs_module.c += -Wno-format
+CWARNFLAGS.ufs_module.c += -Wno-cast-align
+
 # Disable warnings that are currently incompatible with the zfs boot code
 CWARNFLAGS.zfs_module.c += -Wno-array-bounds
 CWARNFLAGS.zfs_module.c += -Wno-cast-align
@@ -25,7 +30,7 @@ CWARNFLAGS.zfs_module.c += -Wno-unused-parameter
 CWARNFLAGS.zfs_module.c += -Wno-unused-function
 
 # architecture-specific loader code
-SRCS+=	boot1.c self_reloc.c start.S ufs_module.c devpath.c
+SRCS+=	boot1.c proto.c self_reloc.c start.S ufs_module.c devpath.c
 .if ${MK_LOADER_ZFS} != "no"
 SRCS+=		zfs_module.c
 CFLAGS.zfs_module.c+=	-I${ZFSSRC}

Modified: stable/12/stand/efi/boot1/boot1.c
==============================================================================
--- stable/12/stand/efi/boot1/boot1.c	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/efi/boot1/boot1.c	Thu Oct 24 03:16:23 2019	(r353988)
@@ -33,10 +33,11 @@ __FBSDID("$FreeBSD$");
 
 #include "boot_module.h"
 #include "paths.h"
+#include "proto.h"
 
 static void efi_panic(EFI_STATUS s, const char *fmt, ...) __dead2 __printflike(2, 3);
 
-static const boot_module_t *boot_modules[] =
+const boot_module_t *boot_modules[] =
 {
 #ifdef EFI_ZFS_BOOT
 	&zfs_module,
@@ -45,9 +46,8 @@ static const boot_module_t *boot_modules[] =
 	&ufs_module
 #endif
 };
+const UINTN num_boot_modules = nitems(boot_modules);
 
-#define	NUM_BOOT_MODULES	nitems(boot_modules)
-
 static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
 static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
 static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
@@ -91,66 +91,19 @@ Calloc(size_t n1, size_t n2, const char *file, int lin
 }
 
 /*
- * load_loader attempts to load the loader image data.
- *
- * It tries each module and its respective devices, identified by mod->probe,
- * in order until a successful load occurs at which point it returns EFI_SUCCESS
- * and EFI_NOT_FOUND otherwise.
- *
- * Only devices which have preferred matching the preferred parameter are tried.
- */
-static EFI_STATUS
-load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
-    size_t *bufsize, BOOLEAN preferred)
-{
-	UINTN i;
-	dev_info_t *dev;
-	const boot_module_t *mod;
-
-	for (i = 0; i < NUM_BOOT_MODULES; i++) {
-		mod = boot_modules[i];
-		for (dev = mod->devices(); dev != NULL; dev = dev->next) {
-			if (dev->preferred != preferred)
-				continue;
-
-			if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
-			    EFI_SUCCESS) {
-				*devinfop = dev;
-				*modp = mod;
-				return (EFI_SUCCESS);
-			}
-		}
-	}
-
-	return (EFI_NOT_FOUND);
-}
-
-/*
  * try_boot only returns if it fails to load the loader. If it succeeds
  * it simply boots, otherwise it returns the status of last EFI call.
  */
-static EFI_STATUS
-try_boot(void)
+EFI_STATUS
+try_boot(const boot_module_t *mod, dev_info_t *dev, void *loaderbuf, size_t loadersize)
 {
-	size_t bufsize, loadersize, cmdsize;
-	void *buf, *loaderbuf;
+	size_t bufsize, cmdsize;
+	void *buf;
 	char *cmd;
-	dev_info_t *dev;
-	const boot_module_t *mod;
 	EFI_HANDLE loaderhandle;
 	EFI_LOADED_IMAGE *loaded_image;
 	EFI_STATUS status;
 
-	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
-	if (status != EFI_SUCCESS) {
-		status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
-		    FALSE);
-		if (status != EFI_SUCCESS) {
-			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
-			return (status);
-		}
-	}
-
 	/*
 	 * Read in and parse the command line from /boot.config or /boot/config,
 	 * if present. We'll pass it the next stage via a simple ASCII
@@ -230,111 +183,6 @@ errout:
 	return (status);
 }
 
-/*
- * probe_handle determines if the passed handle represents a logical partition
- * if it does it uses each module in order to probe it and if successful it
- * returns EFI_SUCCESS.
- */
-static EFI_STATUS
-probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
-{
-	dev_info_t *devinfo;
-	EFI_BLOCK_IO *blkio;
-	EFI_DEVICE_PATH *devpath;
-	EFI_STATUS status;
-	UINTN i;
-
-	/* Figure out if we're dealing with an actual partition. */
-	status = OpenProtocolByHandle(h, &DevicePathGUID, (void **)&devpath);
-	if (status == EFI_UNSUPPORTED)
-		return (status);
-
-	if (status != EFI_SUCCESS) {
-		DPRINTF("\nFailed to query DevicePath (%lu)\n",
-		    EFI_ERROR_CODE(status));
-		return (status);
-	}
-#ifdef EFI_DEBUG
-	{
-		CHAR16 *text = efi_devpath_name(devpath);
-		DPRINTF("probing: %S\n", text);
-		efi_free_devpath_name(text);
-	}
-#endif
-	status = OpenProtocolByHandle(h, &BlockIoProtocolGUID, (void **)&blkio);
-	if (status == EFI_UNSUPPORTED)
-		return (status);
-
-	if (status != EFI_SUCCESS) {
-		DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
-		    EFI_ERROR_CODE(status));
-		return (status);
-	}
-
-	if (!blkio->Media->LogicalPartition)
-		return (EFI_UNSUPPORTED);
-
-	*preferred = efi_devpath_match(imgpath, devpath);
-
-	/* Run through each module, see if it can load this partition */
-	devinfo = malloc(sizeof(*devinfo));
-	if (devinfo == NULL) {
-		DPRINTF("\nFailed to allocate devinfo\n");
-		return (EFI_UNSUPPORTED);
-	}
-	devinfo->dev = blkio;
-	devinfo->devpath = devpath;
-	devinfo->devhandle = h;
-	devinfo->preferred = *preferred;
-	devinfo->next = NULL;
-
-	for (i = 0; i < NUM_BOOT_MODULES; i++) {
-		devinfo->devdata = NULL;
-		status = boot_modules[i]->probe(devinfo);
-		if (status == EFI_SUCCESS)
-			return (EFI_SUCCESS);
-	}
-	free(devinfo);
-
-	return (EFI_UNSUPPORTED);
-}
-
-/*
- * probe_handle_status calls probe_handle and outputs the returned status
- * of the call.
- */
-static void
-probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
-{
-	EFI_STATUS status;
-	BOOLEAN preferred;
-
-	preferred = FALSE;
-	status = probe_handle(h, imgpath, &preferred);
-	
-	DPRINTF("probe: ");
-	switch (status) {
-	case EFI_UNSUPPORTED:
-		printf(".");
-		DPRINTF(" not supported\n");
-		break;
-	case EFI_SUCCESS:
-		if (preferred) {
-			printf("%c", '*');
-			DPRINTF(" supported (preferred)\n");
-		} else {
-			printf("%c", '+');
-			DPRINTF(" supported\n");
-		}
-		break;
-	default:
-		printf("x");
-		DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
-		break;
-	}
-	DSTALL(500000);
-}
-
 EFI_STATUS
 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
 {
@@ -346,9 +194,6 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
 	SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
 	UINTN i, hsize, nhandles;
 	CHAR16 *text;
-	UINT16 boot_current;
-	size_t sz;
-	UINT16 boot_order[100];
 
 	/* Basic initialization*/
 	ST = Xsystab;
@@ -376,13 +221,27 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
 	printf("\n>> FreeBSD EFI boot block\n");
 	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
 	printf("   Initializing modules:");
-	for (i = 0; i < NUM_BOOT_MODULES; i++) {
+	for (i = 0; i < num_boot_modules; i++) {
 		printf(" %s", boot_modules[i]->name);
 		if (boot_modules[i]->init != NULL)
 			boot_modules[i]->init();
 	}
 	putchar('\n');
 
+	/* Fetch all the block I/O handles, we have to search through them later */
+	hsize = 0;
+	BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
+	    &hsize, NULL);
+	handles = malloc(hsize);
+	if (handles == NULL)
+		efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n",
+		    hsize);
+	status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
+	    NULL, &hsize, handles);
+	if (status != EFI_SUCCESS)
+		efi_panic(status, "Failed to get device handles\n");
+	nhandles = hsize / sizeof(*handles);
+
 	/* Determine the devpath of our image so we can prefer it. */
 	status = OpenProtocolByHandle(IH, &LoadedImageGUID, (void **)&img);
 	imgpath = NULL;
@@ -409,58 +268,7 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
 		}
 	}
 
-	boot_current = 0;
-	sz = sizeof(boot_current);
-	if (efi_global_getenv("BootCurrent", &boot_current, &sz) == EFI_SUCCESS) {
-		printf("   BootCurrent: %04x\n", boot_current);
-
-		sz = sizeof(boot_order);
-		if (efi_global_getenv("BootOrder", &boot_order, &sz) == EFI_SUCCESS) {
-			printf("   BootOrder:");
-			for (i = 0; i < sz / sizeof(boot_order[0]); i++)
-				printf(" %04x%s", boot_order[i],
-				    boot_order[i] == boot_current ? "[*]" : "");
-			printf("\n");
-		}
-	}
-
-#ifdef TEST_FAILURE
-	/*
-	 * For testing failover scenarios, it's nice to be able to fail fast.
-	 * Define TEST_FAILURE to create a boot1.efi that always fails after
-	 * reporting the boot manager protocol details.
-	 */
-	BS->Exit(IH, EFI_OUT_OF_RESOURCES, 0, NULL);
-#endif
-
-	hsize = 0;
-	BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
-	    &hsize, NULL);
-	handles = malloc(hsize);
-	if (handles == NULL)
-		efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n",
-		    hsize);
-	status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
-	    NULL, &hsize, handles);
-	if (status != EFI_SUCCESS)
-		efi_panic(status, "Failed to get device handles\n");
-
-	/* Scan all partitions, probing with all modules. */
-	nhandles = hsize / sizeof(*handles);
-	printf("   Probing %zu block devices...", nhandles);
-	DPRINTF("\n");
-
-	for (i = 0; i < nhandles; i++)
-		probe_handle_status(handles[i], imgpath);
-	printf(" done\n");
-
-	/* Status summary. */
-	for (i = 0; i < NUM_BOOT_MODULES; i++) {
-		printf("    ");
-		boot_modules[i]->status();
-	}
-
-	try_boot();
+	choice_protocol(handles, nhandles, imgpath);
 
 	/* If we get here, we're out of luck... */
 	efi_panic(EFI_LOAD_ERROR, "No bootable partitions found!");

Modified: stable/12/stand/efi/boot1/boot_module.h
==============================================================================
--- stable/12/stand/efi/boot1/boot_module.h	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/efi/boot1/boot_module.h	Thu Oct 24 03:16:23 2019	(r353988)
@@ -96,6 +96,9 @@ typedef struct boot_module_t
 	dev_info_t *(*devices)(void);
 } boot_module_t;
 
+extern const boot_module_t *boot_modules[];
+extern const UINTN num_boot_modules;
+
 /* Standard boot modules. */
 #ifdef EFI_UFS_BOOT
 extern const boot_module_t ufs_module;
@@ -106,5 +109,4 @@ extern const boot_module_t zfs_module;
 
 /* Functions available to modules. */
 extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo);
-extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
 #endif

Copied: stable/12/stand/efi/boot1/proto.c (from r348812, head/stand/efi/boot1/proto.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/12/stand/efi/boot1/proto.c	Thu Oct 24 03:16:23 2019	(r353988, copy of r348812, head/stand/efi/boot1/proto.c)
@@ -0,0 +1,223 @@
+/*-
+ * Copyright (c) 1998 Robert Nordier
+ * All rights reserved.
+ * Copyright (c) 2001 Robert Drehmel
+ * All rights reserved.
+ * Copyright (c) 2014 Nathan Whitehorn
+ * All rights reserved.
+ * Copyright (c) 2015 Eric McCorkle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <machine/elf.h>
+#include <machine/stdarg.h>
+#include <stand.h>
+
+#include <efi.h>
+#include <eficonsctl.h>
+#include <efichar.h>
+
+#include "boot_module.h"
+#include "paths.h"
+#include "proto.h"
+
+static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
+static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
+
+static const char *prio_str[] = {
+	"error",
+	"not supported",
+	"good",
+	"better"
+};
+
+/*
+ * probe_handle determines if the passed handle represents a logical partition
+ * if it does it uses each module in order to probe it and if successful it
+ * returns EFI_SUCCESS.
+ */
+static int
+probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
+{
+	dev_info_t *devinfo;
+	EFI_BLOCK_IO *blkio;
+	EFI_DEVICE_PATH *devpath;
+	EFI_STATUS status;
+	UINTN i;
+	int preferred;
+
+	/* Figure out if we're dealing with an actual partition. */
+	status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+	if (status == EFI_UNSUPPORTED)
+		return (0);
+
+	if (status != EFI_SUCCESS) {
+		DPRINTF("\nFailed to query DevicePath (%lu)\n",
+		    EFI_ERROR_CODE(status));
+		return (-1);
+	}
+#ifdef EFI_DEBUG
+	{
+		CHAR16 *text = efi_devpath_name(devpath);
+		DPRINTF("probing: %S ", text);
+		efi_free_devpath_name(text);
+	}
+#endif
+	status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+	if (status == EFI_UNSUPPORTED)
+		return (0);
+
+	if (status != EFI_SUCCESS) {
+		DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
+		    EFI_ERROR_CODE(status));
+		return (-1);
+	}
+
+	if (!blkio->Media->LogicalPartition)
+		return (0);
+
+	preferred = efi_devpath_same_disk(imgpath, devpath);
+
+	/* Run through each module, see if it can load this partition */
+	devinfo = malloc(sizeof(*devinfo));
+	if (devinfo == NULL) {
+		DPRINTF("\nFailed to allocate devinfo\n");
+		return (-1);
+	}
+	devinfo->dev = blkio;
+	devinfo->devpath = devpath;
+	devinfo->devhandle = h;
+	devinfo->preferred = preferred;
+	devinfo->next = NULL;
+
+	for (i = 0; i < num_boot_modules; i++) {
+		devinfo->devdata = NULL;
+
+		status = boot_modules[i]->probe(devinfo);
+		if (status == EFI_SUCCESS)
+			return (preferred + 1);
+	}
+	free(devinfo);
+
+	return (0);
+}
+
+/*
+ * load_loader attempts to load the loader image data.
+ *
+ * It tries each module and its respective devices, identified by mod->probe,
+ * in order until a successful load occurs at which point it returns EFI_SUCCESS
+ * and EFI_NOT_FOUND otherwise.
+ *
+ * Only devices which have preferred matching the preferred parameter are tried.
+ */
+static EFI_STATUS
+load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
+    size_t *bufsize, int preferred)
+{
+	UINTN i;
+	dev_info_t *dev;
+	const boot_module_t *mod;
+
+	for (i = 0; i < num_boot_modules; i++) {
+		mod = boot_modules[i];
+		for (dev = mod->devices(); dev != NULL; dev = dev->next) {
+			if (dev->preferred != preferred)
+				continue;
+
+			if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
+			    EFI_SUCCESS) {
+				*devinfop = dev;
+				*modp = mod;
+				return (EFI_SUCCESS);
+			}
+		}
+	}
+
+	return (EFI_NOT_FOUND);
+}
+
+void
+choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath)
+{
+	UINT16 boot_current;
+	size_t sz;
+	UINT16 boot_order[100];
+	unsigned i;
+	int rv;
+	EFI_STATUS status;
+	const boot_module_t *mod;
+	dev_info_t *dev;
+	void *loaderbuf;
+	size_t loadersize;
+
+	/* Report UEFI Boot Manager Protocol details */
+	boot_current = 0;
+	sz = sizeof(boot_current);
+	if (efi_global_getenv("BootCurrent", &boot_current, &sz) == EFI_SUCCESS) {
+		printf("   BootCurrent: %04x\n", boot_current);
+
+		sz = sizeof(boot_order);
+		if (efi_global_getenv("BootOrder", &boot_order, &sz) == EFI_SUCCESS) {
+			printf("   BootOrder:");
+			for (i = 0; i < sz / sizeof(boot_order[0]); i++)
+				printf(" %04x%s", boot_order[i],
+				    boot_order[i] == boot_current ? "[*]" : "");
+			printf("\n");
+		}
+	}
+
+#ifdef TEST_FAILURE
+	/*
+	 * For testing failover scenarios, it's nice to be able to fail fast.
+	 * Define TEST_FAILURE to create a boot1.efi that always fails after
+	 * reporting the boot manager protocol details.
+	 */
+	BS->Exit(IH, EFI_OUT_OF_RESOURCES, 0, NULL);
+#endif
+
+	/* Scan all partitions, probing with all modules. */
+	printf("   Probing %zu block devices...", nhandles);
+	DPRINTF("\n");
+	for (i = 0; i < nhandles; i++) {
+		rv = probe_handle(handles[i], imgpath);
+#ifdef EFI_DEBUG
+		printf("%c", "x.+*"[rv + 1]);
+#else
+		printf("%s\n", prio_str[rv + 1]);
+#endif
+	}
+	printf(" done\n");
+
+
+	/* Status summary. */
+	for (i = 0; i < num_boot_modules; i++) {
+		printf("    ");
+		boot_modules[i]->status();
+	}
+
+	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 1);
+	if (status != EFI_SUCCESS) {
+		status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 0);
+		if (status != EFI_SUCCESS) {
+			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
+			return;
+		}
+	}
+
+	try_boot(mod, dev, loaderbuf, loadersize);
+}

Copied: stable/12/stand/efi/boot1/proto.h (from r348812, head/stand/efi/boot1/proto.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/12/stand/efi/boot1/proto.h	Thu Oct 24 03:16:23 2019	(r353988, copy of r348812, head/stand/efi/boot1/proto.h)
@@ -0,0 +1,29 @@
+/*-
+ * Copyright (c) 2019 Netflix, Inc
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+void choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath);
+EFI_STATUS try_boot(const boot_module_t *mod, dev_info_t *dev, void *loaderbuf, size_t loadersize);

Modified: stable/12/stand/efi/boot1/ufs_module.c
==============================================================================
--- stable/12/stand/efi/boot1/ufs_module.c	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/efi/boot1/ufs_module.c	Thu Oct 24 03:16:23 2019	(r353988)
@@ -140,7 +140,6 @@ static EFI_STATUS
 load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize)
 {
 	ufs_ino_t ino;
-	EFI_STATUS status;
 	size_t size;
 	ssize_t read;
 	void *buf;
@@ -167,18 +166,18 @@ load(const char *filepath, dev_info_t *dev, void **buf
 		return (EFI_INVALID_PARAMETER);
 	}
 
-	if ((status = BS->AllocatePool(EfiLoaderData, size, &buf)) !=
-	    EFI_SUCCESS) {
-		printf("Failed to allocate read buffer %zu for '%s' (%lu)\n",
-		    size, filepath, EFI_ERROR_CODE(status));
-		return (status);
+	buf = malloc(size);
+	if (buf == NULL) {
+		printf("Failed to allocate read buffer %zu for '%s'\n",
+		    size, filepath);
+		return (EFI_OUT_OF_RESOURCES);
 	}
 
 	read = fsread(ino, buf, size);
 	if ((size_t)read != size) {
 		printf("Failed to read '%s' (%zd != %zu)\n", filepath, read,
 		    size);
-		(void)BS->FreePool(buf);
+		free(buf);
 		return (EFI_INVALID_PARAMETER);
 	}
 

Modified: stable/12/stand/efi/boot1/zfs_module.c
==============================================================================
--- stable/12/stand/efi/boot1/zfs_module.c	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/efi/boot1/zfs_module.c	Thu Oct 24 03:16:23 2019	(r353988)
@@ -115,19 +115,17 @@ probe(dev_info_t *dev)
 {
 	spa_t *spa;
 	dev_info_t *tdev;
-	EFI_STATUS status;
 
 	/* ZFS consumes the dev on success so we need a copy. */
-	if ((status = BS->AllocatePool(EfiLoaderData, sizeof(*dev),
-	    (void**)&tdev)) != EFI_SUCCESS) {
-		DPRINTF("Failed to allocate tdev (%lu)\n",
-		    EFI_ERROR_CODE(status));
-		return (status);
+	tdev = malloc(sizeof(*dev));
+	if (tdev == NULL) {
+		DPRINTF("Failed to allocate tdev\n");
+		return (EFI_OUT_OF_RESOURCES);
 	}
 	memcpy(tdev, dev, sizeof(*dev));
 
 	if (vdev_probe(vdev_read, tdev, &spa) != 0) {
-		(void)BS->FreePool(tdev);
+		free(tdev);
 		return (EFI_UNSUPPORTED);
 	}
 
@@ -141,12 +139,11 @@ static EFI_STATUS
 load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize)
 {
 	spa_t *spa;
-	struct zfsmount zfsmount;
+	struct zfsmount zmount;
 	dnode_phys_t dn;
 	struct stat st;
 	int err;
 	void *buf;
-	EFI_STATUS status;
 
 	spa = devinfo->devdata;
 
@@ -163,12 +160,12 @@ load(const char *filepath, dev_info_t *devinfo, void *
 		return (EFI_NOT_FOUND);
 	}
 
-	if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) {
+	if ((err = zfs_mount(spa, 0, &zmount)) != 0) {
 		DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
 		return (EFI_NOT_FOUND);
 	}
 
-	if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) {
+	if ((err = zfs_lookup(&zmount, filepath, &dn)) != 0) {
 		if (err == ENOENT) {
 			DPRINTF("Failed to find '%s' on pool '%s' (%d)\n",
 			    filepath, spa->spa_name, err);
@@ -185,17 +182,17 @@ load(const char *filepath, dev_info_t *devinfo, void *
 		return (EFI_INVALID_PARAMETER);
 	}
 
-	if ((status = BS->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
-	    != EFI_SUCCESS) {
-		printf("Failed to allocate load buffer %jd for pool '%s' for '%s' "
-		    "(%lu)\n", (intmax_t)st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status));
+	buf = malloc(st.st_size);
+	if (buf == NULL) {
+		printf("Failed to allocate load buffer %jd for pool '%s' for '%s' ",
+		    (intmax_t)st.st_size, spa->spa_name, filepath);
 		return (EFI_INVALID_PARAMETER);
 	}
 
 	if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) {
 		printf("Failed to read node from %s (%d)\n", spa->spa_name,
 		    err);
-		(void)BS->FreePool(buf);
+		free(buf);
 		return (EFI_INVALID_PARAMETER);
 	}
 

Modified: stable/12/stand/efi/include/efilib.h
==============================================================================
--- stable/12/stand/efi/include/efilib.h	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/efi/include/efilib.h	Thu Oct 24 03:16:23 2019	(r353988)
@@ -91,6 +91,7 @@ bool efi_devpath_match_node(EFI_DEVICE_PATH *, EFI_DEV
 bool efi_devpath_is_prefix(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *);
 CHAR16 *efi_devpath_name(EFI_DEVICE_PATH *);
 void efi_free_devpath_name(CHAR16 *);
+bool efi_devpath_same_disk(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *);
 EFI_DEVICE_PATH *efi_devpath_to_media_path(EFI_DEVICE_PATH *);
 UINTN efi_devpath_length(EFI_DEVICE_PATH *);
 EFI_HANDLE efi_devpath_to_handle(EFI_DEVICE_PATH *path, EFI_HANDLE *handles, unsigned nhandles);

Modified: stable/12/stand/efi/libefi/devpath.c
==============================================================================
--- stable/12/stand/efi/libefi/devpath.c	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/efi/libefi/devpath.c	Thu Oct 24 03:16:23 2019	(r353988)
@@ -199,14 +199,19 @@ efi_devpath_match_node(EFI_DEVICE_PATH *devpath1, EFI_
 	return (true);
 }
 
-bool
-efi_devpath_match(EFI_DEVICE_PATH *devpath1, EFI_DEVICE_PATH *devpath2)
+static bool
+_efi_devpath_match(EFI_DEVICE_PATH *devpath1, EFI_DEVICE_PATH *devpath2,
+    bool ignore_media)
 {
 
 	if (devpath1 == NULL || devpath2 == NULL)
 		return (false);
 
 	while (true) {
+		if (ignore_media &&
+		    IsDevicePathType(devpath1, MEDIA_DEVICE_PATH) &&
+		    IsDevicePathType(devpath2, MEDIA_DEVICE_PATH))
+			return (true);
 		if (!efi_devpath_match_node(devpath1, devpath2))
 			return false;
 		if (IsDevicePathEnd(devpath1))
@@ -215,6 +220,25 @@ efi_devpath_match(EFI_DEVICE_PATH *devpath1, EFI_DEVIC
 		devpath2 = NextDevicePathNode(devpath2);
 	}
 	return (true);
+}
+/*
+ * Are two devpaths identical?
+ */
+bool
+efi_devpath_match(EFI_DEVICE_PATH *devpath1, EFI_DEVICE_PATH *devpath2)
+{
+	return _efi_devpath_match(devpath1, devpath2, false);
+}
+
+/*
+ * Like efi_devpath_match, but stops at when we hit the media device
+ * path node that specifies the partition information. If we match
+ * up to that point, then we're on the same disk.
+ */
+bool
+efi_devpath_same_disk(EFI_DEVICE_PATH *devpath1, EFI_DEVICE_PATH *devpath2)
+{
+	return _efi_devpath_match(devpath1, devpath2, true);
 }
 
 bool

Modified: stable/12/stand/i386/gptboot/gptboot.c
==============================================================================
--- stable/12/stand/i386/gptboot/gptboot.c	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/i386/gptboot/gptboot.c	Thu Oct 24 03:16:23 2019	(r353988)
@@ -232,7 +232,7 @@ static int
 gptinit(void)
 {
 
-	if (gptread(&freebsd_ufs_uuid, &gdsk.dsk, dmadat->secbuf) == -1) {
+	if (gptread(&gdsk.dsk, dmadat->secbuf) == -1) {
 		printf("%s: unable to load GPT\n", BOOTPROG);
 		return (-1);
 	}

Modified: stable/12/stand/libsa/gpt.c
==============================================================================
--- stable/12/stand/libsa/gpt.c	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/libsa/gpt.c	Thu Oct 24 03:16:23 2019	(r353988)
@@ -275,8 +275,8 @@ gptbootconv(const char *which, struct dsk *dskp, struc
 }
 
 static int
-gptread_table(const char *which, const uuid_t *uuid, struct dsk *dskp,
-    struct gpt_hdr *hdr, struct gpt_ent *table)
+gptread_table(const char *which, struct dsk *dskp, struct gpt_hdr *hdr,
+    struct gpt_ent *table)
 {
 	struct gpt_ent *ent;
 	int entries_per_sec;
@@ -313,7 +313,7 @@ gptread_table(const char *which, const uuid_t *uuid, s
 }
 
 int
-gptread(const uuid_t *uuid, struct dsk *dskp, char *buf)
+gptread(struct dsk *dskp, char *buf)
 {
 	uint64_t altlba;
 
@@ -328,8 +328,7 @@ gptread(const uuid_t *uuid, struct dsk *dskp, char *bu
 	dskp->start = 0;
 
 	if (gptread_hdr("primary", dskp, &hdr_primary, 1) == 0 &&
-	    gptread_table("primary", uuid, dskp, &hdr_primary,
-	    table_primary) == 0) {
+	    gptread_table("primary", dskp, &hdr_primary, table_primary) == 0) {
 		hdr_primary_lba = hdr_primary.hdr_lba_self;
 		gpthdr = &hdr_primary;
 		gpttable = table_primary;
@@ -349,8 +348,7 @@ gptread(const uuid_t *uuid, struct dsk *dskp, char *bu
 	if (altlba == 0)
 		printf("%s: unable to locate backup GPT header\n", BOOTPROG);
 	else if (gptread_hdr("backup", dskp, &hdr_backup, altlba) == 0 &&
-	    gptread_table("backup", uuid, dskp, &hdr_backup,
-	    table_backup) == 0) {
+	    gptread_table("backup", dskp, &hdr_backup, table_backup) == 0) {
 		hdr_backup_lba = hdr_backup.hdr_lba_self;
 		if (hdr_primary_lba == 0) {
 			gpthdr = &hdr_backup;

Modified: stable/12/stand/libsa/gpt.h
==============================================================================
--- stable/12/stand/libsa/gpt.h	Thu Oct 24 03:09:31 2019	(r353987)
+++ stable/12/stand/libsa/gpt.h	Thu Oct 24 03:16:23 2019	(r353988)
@@ -34,7 +34,7 @@
 
 #define	MAXTBLENTS	128
 
-int gptread(const uuid_t *uuid, struct dsk *dskp, char *buf);
+int gptread(struct dsk *dskp, char *buf);
 int gptfind(const uuid_t *uuid, struct dsk *dskp, int part);
 void gptbootfailed(struct dsk *dskp);
 


More information about the svn-src-all mailing list