svn commit: r324709 - in head/sys/boot/efi: boot1 libefi loader

Warner Losh imp at FreeBSD.org
Tue Oct 17 23:38:28 UTC 2017


Author: imp
Date: Tue Oct 17 23:38:27 2017
New Revision: 324709
URL: https://svnweb.freebsd.org/changeset/base/324709

Log:
  Revert "Unify boot1 with loader" change r324646
  
  Back out the unification commit to boot1. There's some issues on the
  arm and arm64 platforms that need to be addressed with code
  changes. There's also a discussion on arch@ about the future of
  boot1.efi vs just using loader.efi that needs to play out. So take a
  pause on these changes until the arm issues can be fixed and it's
  clear boot1.efi will survive into FreeBSD 12.
  
  OK'd by: Eric at meatspace

Added:
  head/sys/boot/efi/boot1/boot_module.h   (contents, props changed)
  head/sys/boot/efi/boot1/ufs_module.c   (contents, props changed)
  head/sys/boot/efi/boot1/zfs_module.c   (contents, props changed)
  head/sys/boot/efi/loader/efi_main.c   (contents, props changed)
     - copied, changed from r324707, head/sys/boot/efi/libefi/efi_main.c
Deleted:
  head/sys/boot/efi/libefi/efi_main.c
Modified:
  head/sys/boot/efi/boot1/Makefile
  head/sys/boot/efi/boot1/boot1.c
  head/sys/boot/efi/libefi/Makefile
  head/sys/boot/efi/loader/Makefile

Modified: head/sys/boot/efi/boot1/Makefile
==============================================================================
--- head/sys/boot/efi/boot1/Makefile	Tue Oct 17 21:20:07 2017	(r324708)
+++ head/sys/boot/efi/boot1/Makefile	Tue Oct 17 23:38:27 2017	(r324709)
@@ -9,11 +9,8 @@ MK_FORTH=	no
 
 PROG=		boot1.sym
 INTERNALPROG=
-WARNS?=		3
+WARNS?=		6
 
-# Include bcache code.
-HAVE_BCACHE=    yes
-
 # We implement a slightly non-standard %S in that it always takes a
 # CHAR16 that's common in UEFI-land instead of a wchar_t. This only
 # seems to matter on arm64 where wchar_t defaults to an int instead
@@ -22,15 +19,13 @@ HAVE_BCACHE=    yes
 CWARNFLAGS.boot1.c+=	-Wno-format
 
 # Disable warnings that are currently incompatible with the zfs boot code
-CWARNFLAGS.zfs.c += -Wno-incompatible-pointer-types-discards-qualifiers
-CWARNFLAGS.zfs.c += -Wno-missing-variable-declarations
-CWARNFLAGS.zfs.c += -Wno-array-bounds
-CWARNFLAGS.zfs.c += -Wno-cast-align
-CWARNFLAGS.zfs.c += -Wno-cast-qual
-CWARNFLAGS.zfs.c += -Wno-missing-prototypes
-CWARNFLAGS.zfs.c += -Wno-sign-compare
-CWARNFLAGS.zfs.c += -Wno-unused-parameter
-CWARNFLAGS.zfs.c += -Wno-unused-function
+CWARNFLAGS.zfs_module.c += -Wno-array-bounds
+CWARNFLAGS.zfs_module.c += -Wno-cast-align
+CWARNFLAGS.zfs_module.c += -Wno-cast-qual
+CWARNFLAGS.zfs_module.c += -Wno-missing-prototypes
+CWARNFLAGS.zfs_module.c += -Wno-sign-compare
+CWARNFLAGS.zfs_module.c += -Wno-unused-parameter
+CWARNFLAGS.zfs_module.c += -Wno-unused-function
 CWARNFLAGS.skein.c += -Wno-cast-align
 .if ${COMPILER_TYPE} == "clang"
 CWARNFLAGS.skein.c += -Wno-missing-variable-declarations
@@ -39,25 +34,19 @@ CWARNFLAGS.skein.c += -Wno-missing-declarations
 .endif
 
 # architecture-specific loader code
-SRCS=	boot1.c self_reloc.c start.S
+SRCS=	boot1.c self_reloc.c start.S ufs_module.c
 .if ${MK_ZFS} != "no"
-.PATH:		${.CURDIR}/../../../crypto/skein
+SRCS+=		zfs_module.c
 SRCS+=		skein.c skein_block.c
 # Do not unroll skein loops, reduce code size
 CFLAGS+=	-DSKEIN_LOOP=111
-.PATH:		${.CURDIR}/../../zfs
-SRCS+=		zfs.c
+.PATH:		${.CURDIR}/../../../crypto/skein
 .endif
 
 .if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} > 40201
 CWARNFLAGS.self_reloc.c+=	-Wno-error=maybe-uninitialized
 .endif
 
-# Always add MI sources
-.include	"../../loader.mk"
-
-.PATH: ${.CURDIR}/arch/${MACHINE}
-
 CFLAGS+=	-I.
 CFLAGS+=	-I${.CURDIR}/../include
 CFLAGS+=	-I${.CURDIR}/../include/${MACHINE}
@@ -129,7 +118,7 @@ boot1.efi: ${PROG}
 	SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} \
 	${OBJCOPY} -j .peheader -j .text -j .sdata -j .data \
 		-j .dynamic -j .dynsym -j .rel.dyn \
-		-j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
+		-j .rela.dyn -j .reloc -j .eh_frame \
 		--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
 
 boot1.o: ${SASRC}/ufsread.c

Modified: head/sys/boot/efi/boot1/boot1.c
==============================================================================
--- head/sys/boot/efi/boot1/boot1.c	Tue Oct 17 21:20:07 2017	(r324708)
+++ head/sys/boot/efi/boot1/boot1.c	Tue Oct 17 23:38:27 2017	(r324709)
@@ -23,179 +23,61 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
-#include <sys/disk.h>
 #include <machine/elf.h>
 #include <machine/stdarg.h>
 #include <stand.h>
-#include <disk.h>
 
 #include <efi.h>
-#include <efilib.h>
-#include <efiprot.h>
 #include <eficonsctl.h>
-#ifdef EFI_ZFS_BOOT
-#include <libzfs.h>
-#endif
 typedef CHAR16 efi_char;
 #include <efichar.h>
 
-#include <bootstrap.h>
-
-#include "efi_drivers.h"
-#include "efizfs.h"
+#include "boot_module.h"
 #include "paths.h"
 
 static void efi_panic(EFI_STATUS s, const char *fmt, ...) __dead2 __printflike(2, 3);
-#ifdef EFI_DEBUG
-#define DPRINTF(fmt, args...) printf(fmt, ##args)
-#define DSTALL(d) BS->Stall(d)
-#else
-#define DPRINTF(fmt, ...) {}
-#define DSTALL(d) {}
-#endif
 
-struct arch_switch archsw;	/* MI/MD interface boundary */
-
-static const efi_driver_t *efi_drivers[] = {
-        NULL
-};
-
-extern struct console efi_console;
-#if defined(__amd64__) || defined(__i386__)
-extern struct console comconsole;
-extern struct console nullconsole;
-#endif
-
+static const boot_module_t *boot_modules[] =
+{
 #ifdef EFI_ZFS_BOOT
-uint64_t pool_guid;
+	&zfs_module,
 #endif
-
-struct fs_ops *file_system[] = {
-#ifdef EFI_ZFS_BOOT
-	&zfs_fsops,
-#endif
-	&dosfs_fsops,
 #ifdef EFI_UFS_BOOT
-	&ufs_fsops,
+	&ufs_module
 #endif
-	&cd9660_fsops,
-	&nfs_fsops,
-	&gzipfs_fsops,
-	&bzipfs_fsops,
-	NULL
 };
 
-struct devsw *devsw[] = {
-	&efipart_hddev,
-	&efipart_fddev,
-	&efipart_cddev,
-#ifdef EFI_ZFS_BOOT
-	&zfs_dev,
-#endif
-	NULL
-};
-
-struct console *consoles[] = {
-	&efi_console,
-	NULL
-};
-
-static EFI_LOADED_IMAGE *boot_image;
-static EFI_DEVICE_PATH *imgpath;
-static EFI_DEVICE_PATH *imgprefix;
-
-/* Definitions we don't actually need for boot, but we need to define
- * to make the linker happy.
- */
-struct file_format *file_formats[] = { NULL };
-
-struct netif_driver *netif_drivers[] = { NULL };
-
-static int
-efi_autoload(void)
-{
-  printf("******** Boot block should not call autoload\n");
-  return (-1);
-}
-
-static ssize_t
-efi_copyin(const void *src __unused, vm_offset_t dest __unused,
-    const size_t len __unused)
-{
-  printf("******** Boot block should not call copyin\n");
-  return (-1);
-}
-
-static ssize_t
-efi_copyout(vm_offset_t src __unused, void *dest __unused,
-    const size_t len __unused)
-{
-  printf("******** Boot block should not call copyout\n");
-  return (-1);
-}
-
-static ssize_t
-efi_readin(int fd __unused, vm_offset_t dest __unused,
-    const size_t len __unused)
-{
-  printf("******** Boot block should not call readin\n");
-  return (-1);
-}
-
+#define	NUM_BOOT_MODULES	nitems(boot_modules)
 /* The initial number of handles used to query EFI for partitions. */
 #define NUM_HANDLES_INIT	24
 
+static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
 static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
 static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
+static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
 static EFI_GUID FreeBSDBootVarGUID = FREEBSD_BOOT_VAR_GUID;
 
-static EFI_STATUS
-do_load(const char *filepath, void **bufp, size_t *bufsize)
+/*
+ * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
+ * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
+ * EFI methods.
+ */
+void *
+Malloc(size_t len, const char *file __unused, int line __unused)
 {
-	struct stat st;
-        void *buf = NULL;
-        int fd, err;
-        size_t fsize, remaining;
-        ssize_t readsize;
+	void *out;
 
-        if ((fd = open(filepath, O_RDONLY)) < 0) {
-                return (ENOTSUP);
-        }
+	if (BS->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
+		return (out);
 
-        if ((err = fstat(fd, &st)) != 0) {
-                goto close_file;
-        }
+	return (NULL);
+}
 
-        fsize = st.st_size;
-
-        if ((buf = malloc(fsize)) == NULL) {
-                err = ENOMEM;
-                goto close_file;
-        }
-
-        remaining = fsize;
-
-        do {
-                if ((readsize = read(fd, buf, fsize)) < 0) {
-                        err = (-readsize);
-                        goto free_buf;
-                }
-
-                remaining -= readsize;
-        } while(remaining != 0);
-
-        close(fd);
-        *bufsize = st.st_size;
-        *bufp = buf;
-
- close_file:
-        close(fd);
-
-        return errno_to_efi_status(err);
-
- free_buf:
-        free(buf);
-        goto close_file;
+void
+Free(void *buf, const char *file __unused, int line __unused)
+{
+	if (buf != NULL)
+		(void)BS->FreePool(buf);
 }
 
 static EFI_STATUS
@@ -215,275 +97,98 @@ efi_setenv_freebsd_wcs(const char *varname, CHAR16 *va
 	return (rv);
 }
 
-static int
-probe_fs(const char *filepath)
+/*
+ * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
+ * FALSE otherwise.
+ */
+static BOOLEAN
+nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
 {
-        int fd;
+	size_t len;
 
-        if ((fd = open(filepath, O_RDONLY)) < 0) {
-                return (ENOTSUP);
-        }
+	if (imgpath == NULL || imgpath->Type != devpath->Type ||
+	    imgpath->SubType != devpath->SubType)
+		return (FALSE);
 
-        close(fd);
+	len = DevicePathNodeLength(imgpath);
+	if (len != DevicePathNodeLength(devpath))
+		return (FALSE);
 
-        return (0);
+	return (memcmp(imgpath, devpath, (size_t)len) == 0);
 }
 
-static int
-probe_dev(struct devsw *dev, int unit, const char *filepath)
+/*
+ * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
+ * in imgpath and devpath match up to their respective occurrences of a
+ * media node, FALSE otherwise.
+ */
+static BOOLEAN
+device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
 {
-        struct devdesc currdev;
-        char *devname;
-        int err;
 
-	currdev.d_dev = dev;
-	currdev.d_type = currdev.d_dev->dv_type;
-	currdev.d_unit = unit;
-	currdev.d_opendata = NULL;
-        devname = efi_fmtdev(&currdev);
+	if (imgpath == NULL)
+		return (FALSE);
 
-        env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
-            env_nounset);
+	while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
+		if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
+		    IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
+			return (TRUE);
 
-        err = probe_fs(filepath);
+		if (!nodes_match(imgpath, devpath))
+			return (FALSE);
 
-        return (err);
-}
+		imgpath = NextDevicePathNode(imgpath);
+		devpath = NextDevicePathNode(devpath);
+	}
 
-static bool
-check_preferred(EFI_HANDLE *h)
-{
-         EFI_DEVICE_PATH *path = efi_lookup_devpath(h);
-         bool out;
-
-         if ((path = efi_lookup_devpath(h)) == NULL)
-                 return (false);
-
-         out = efi_devpath_is_prefix(imgpath, path) ||
-           efi_devpath_is_prefix(imgprefix, path);
-
-         return (out);
+	return (FALSE);
 }
 
-bool
-efi_zfs_is_preferred(EFI_HANDLE *h)
+/*
+ * devpath_last returns the last non-path end node in devpath.
+ */
+static EFI_DEVICE_PATH *
+devpath_last(EFI_DEVICE_PATH *devpath)
 {
-         return (check_preferred(h));
-}
 
-static int
-load_preferred(EFI_LOADED_IMAGE *img, const char *filepath, void **bufp,
-    size_t *bufsize, EFI_HANDLE *handlep)
-{
-	pdinfo_list_t *pdi_list;
-	pdinfo_t *dp, *pp;
-	char *devname;
+	while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+		devpath = NextDevicePathNode(devpath);
 
-#ifdef EFI_ZFS_BOOT
-	/* Did efi_zfs_probe() detect the boot pool? */
-	if (pool_guid != 0) {
-                struct zfs_devdesc currdev;
-
-		currdev.d_dev = &zfs_dev;
-		currdev.d_unit = 0;
-		currdev.d_type = currdev.d_dev->dv_type;
-		currdev.d_opendata = NULL;
-		currdev.pool_guid = pool_guid;
-		currdev.root_guid = 0;
-		devname = efi_fmtdev(&currdev);
-
-		env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
-		    env_nounset);
-
-                if (probe_fs(filepath) == 0 &&
-                    do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                        *handlep = efizfs_get_handle_by_guid(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.d_dev = &efipart_hddev;
-		currdev.d_type = currdev.d_dev->dv_type;
-		currdev.d_unit = dp->pd_unit;
-		currdev.d_opendata = NULL;
-		currdev.d_slice = -1;
-		currdev.d_partition = -1;
-		devname = efi_fmtdev(&currdev);
-
-		env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
-		    env_nounset);
-
-	        if (check_preferred(dp->pd_handle) &&
-                    probe_fs(filepath) == 0 &&
-                    do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                        *handlep = dp->pd_handle;
-                        return (0);
-		}
-
-                /* Assuming GPT partitioning. */
-		STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
-                        if (check_preferred(pp->pd_handle)) {
-				currdev.d_slice = pp->pd_unit;
-				currdev.d_partition = 255;
-                                devname = efi_fmtdev(&currdev);
-
-                                env_setenv("currdev", EV_VOLATILE, devname,
-                                    efi_setcurrdev, env_nounset);
-
-                                if (probe_fs(filepath) == 0 &&
-                                    do_load(filepath, bufp, bufsize) ==
-                                        EFI_SUCCESS) {
-                                        *handlep = pp->pd_handle;
-                                        return (0);
-                                }
-			}
-		}
-	}
-
-	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 ||
-                     check_preferred(dp->pd_handle)) &&
-                    probe_dev(&efipart_cddev, dp->pd_unit, filepath) == 0 &&
-                    do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                        *handlep = dp->pd_handle;
-                        return (0);
-		}
-	}
-
-	pdi_list = efiblk_get_pdinfo_list(&efipart_fddev);
-	STAILQ_FOREACH(dp, pdi_list, pd_link) {
-                if ((dp->pd_handle == img->DeviceHandle ||
-                     check_preferred(dp->pd_handle)) &&
-                    probe_dev(&efipart_cddev, dp->pd_unit, filepath) == 0 &&
-                    do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                        *handlep = dp->pd_handle;
-                        return (0);
-		}
-	}
-
-	return (ENOENT);
+	return (devpath);
 }
 
-static int
-load_all(const char *filepath, void **bufp, size_t *bufsize,
-    EFI_HANDLE *handlep)
+/*
+ * 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)
 {
-	pdinfo_list_t *pdi_list;
-	pdinfo_t *dp, *pp;
-	zfsinfo_list_t *zfsi_list;
-	zfsinfo_t *zi;
-        char *devname;
+	UINTN i;
+	dev_info_t *dev;
+	const boot_module_t *mod;
 
-#ifdef EFI_ZFS_BOOT
-	zfsi_list = efizfs_get_zfsinfo_list();
-	STAILQ_FOREACH(zi, zfsi_list, zi_link) {
-                struct zfs_devdesc currdev;
+	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;
 
-		currdev.d_dev = &zfs_dev;
-		currdev.d_unit = 0;
-		currdev.d_type = currdev.d_dev->dv_type;
-		currdev.d_opendata = NULL;
-		currdev.pool_guid = zi->zi_pool_guid;
-		currdev.root_guid = 0;
-		devname = efi_fmtdev(&currdev);
-
-		env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
-		    env_nounset);
-
-                if (probe_fs(filepath) == 0 &&
-                    do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                        *handlep = zi->zi_handle;
-
-                        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.d_dev = &efipart_hddev;
-		currdev.d_type = currdev.d_dev->dv_type;
-		currdev.d_unit = dp->pd_unit;
-		currdev.d_opendata = NULL;
-		currdev.d_slice = -1;
-		currdev.d_partition = -1;
-		devname = efi_fmtdev(&currdev);
-
-		env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
-		    env_nounset);
-
-		if (probe_fs(filepath) == 0 &&
-                    do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                        *handlep = dp->pd_handle;
-
-                        return (0);
-		}
-
-                /* Assuming GPT partitioning. */
-		STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
-                        currdev.d_slice = pp->pd_unit;
-                        currdev.d_partition = 255;
-                        devname = efi_fmtdev(&currdev);
-
-                        env_setenv("currdev", EV_VOLATILE, devname,
-                            efi_setcurrdev, env_nounset);
-
-                        if (probe_fs(filepath) == 0 &&
-                            do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                                *handlep = pp->pd_handle;
-
-                                return (0);
+			if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
+			    EFI_SUCCESS) {
+				*devinfop = dev;
+				*modp = mod;
+				return (EFI_SUCCESS);
 			}
 		}
 	}
 
-	pdi_list = efiblk_get_pdinfo_list(&efipart_cddev);
-	STAILQ_FOREACH(dp, pdi_list, pd_link) {
-		if (probe_dev(&efipart_cddev, dp->pd_unit, filepath) == 0 &&
-                    do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                        *handlep = dp->pd_handle;
-
-                        return (0);
-		}
-	}
-
-	pdi_list = efiblk_get_pdinfo_list(&efipart_fddev);
-	STAILQ_FOREACH(dp, pdi_list, pd_link) {
-		if (probe_dev(&efipart_fddev, dp->pd_unit, filepath) == 0 &&
-                    do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
-                        *handlep = dp->pd_handle;
-
-                        return (0);
-		}
-	}
-
-	return (ENOENT);
-}
-
-static EFI_STATUS
-load_loader(EFI_HANDLE *handlep, void **bufp, size_t *bufsize)
-{
-        /* Try the preferred handles first, then all the handles */
-        if (load_preferred(boot_image, PATH_LOADER_EFI, bufp, bufsize,
-                handlep) == 0) {
-                return (0);
-        }
-
-        if (load_all(PATH_LOADER_EFI, bufp, bufsize, handlep) == 0) {
-                return (0);
-        }
-
 	return (EFI_NOT_FOUND);
 }
 
@@ -497,27 +202,20 @@ try_boot(void)
 	size_t bufsize, loadersize, cmdsize;
 	void *buf, *loaderbuf;
 	char *cmd;
-        EFI_HANDLE fshandle;
+	dev_info_t *dev;
+	const boot_module_t *mod;
 	EFI_HANDLE loaderhandle;
 	EFI_LOADED_IMAGE *loaded_image;
 	EFI_STATUS status;
-        EFI_DEVICE_PATH *fspath;
 
-	status = load_loader(&fshandle, &loaderbuf, &loadersize);
-
-        if (status != EFI_SUCCESS) {
-                return (status);
-        }
-
-	fspath = NULL;
-	if (status == EFI_SUCCESS) {
-		status = BS->OpenProtocol(fshandle, &DevicePathGUID,
-                    (void **)&fspath, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
+	if (status != EFI_SUCCESS) {
+		status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
+		    FALSE);
 		if (status != EFI_SUCCESS) {
-			DPRINTF("Failed to get image DevicePath (%lu)\n",
-			    EFI_ERROR_CODE(status));
-                }
-		DPRINTF("filesystem device path: %s\n", devpath_str(fspath));
+			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
+			return (status);
+		}
 	}
 
 	/*
@@ -532,9 +230,9 @@ try_boot(void)
 	 */
 	cmd = NULL;
 	cmdsize = 0;
-	status = do_load(PATH_DOTCONFIG, &buf, &bufsize);
+	status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
 	if (status == EFI_NOT_FOUND)
-		status = do_load(PATH_CONFIG, &buf, &bufsize);
+		status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
 	if (status == EFI_SUCCESS) {
 		cmdsize = bufsize + 1;
 		cmd = malloc(cmdsize);
@@ -546,25 +244,24 @@ try_boot(void)
 		buf = NULL;
 	}
 
-	if ((status = BS->LoadImage(TRUE, IH, efi_devpath_last_node(fspath),
+	if ((status = BS->LoadImage(TRUE, IH, devpath_last(dev->devpath),
 	    loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
-		printf("Failed to load image, size: %zu, (%lu)\n",
-		     loadersize, EFI_ERROR_CODE(status));
+		printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
+		     mod->name, loadersize, EFI_ERROR_CODE(status));
 		goto errout;
 	}
 
-	if ((status = BS->OpenProtocol(loaderhandle, &LoadedImageGUID,
-            (VOID**)&loaded_image, IH, NULL,
-            EFI_OPEN_PROTOCOL_GET_PROTOCOL)) != EFI_SUCCESS) {
-		printf("Failed to query LoadedImage (%lu)\n",
-		    EFI_ERROR_CODE(status));
+	if ((status = BS->HandleProtocol(loaderhandle, &LoadedImageGUID,
+	    (VOID**)&loaded_image)) != EFI_SUCCESS) {
+		printf("Failed to query LoadedImage provided by %s (%lu)\n",
+		    mod->name, EFI_ERROR_CODE(status));
 		goto errout;
 	}
 
 	if (cmd != NULL)
 		printf("    command args: %s\n", cmd);
 
-	loaded_image->DeviceHandle = fshandle;
+	loaded_image->DeviceHandle = dev->devhandle;
 	loaded_image->LoadOptionsSize = cmdsize;
 	loaded_image->LoadOptions = cmd;
 
@@ -582,8 +279,8 @@ try_boot(void)
 
 	if ((status = BS->StartImage(loaderhandle, NULL, NULL)) !=
 	    EFI_SUCCESS) {
-		printf("Failed to start image (%lu)\n",
-		    EFI_ERROR_CODE(status));
+		printf("Failed to start image provided by %s (%lu)\n",
+		    mod->name, EFI_ERROR_CODE(status));
 		loaded_image->LoadOptionsSize = 0;
 		loaded_image->LoadOptions = NULL;
 	}
@@ -599,37 +296,142 @@ errout:
 	return (status);
 }
 
-EFI_STATUS
-main(int argc __unused, CHAR16 *argv[] __unused)
+/*
+ * 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)
 {
-        EFI_STATUS status;
+	dev_info_t *devinfo;
+	EFI_BLOCK_IO *blkio;
+	EFI_DEVICE_PATH *devpath;
+	EFI_STATUS status;
+	UINTN i;
 
-        SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
-        UINTN i, max_dim, best_mode, cols, rows;
-        CHAR16 *text;
+	/* Figure out if we're dealing with an actual partition. */
+	status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+	if (status == EFI_UNSUPPORTED)
+		return (status);
 
-        archsw.arch_autoload = efi_autoload;
-	archsw.arch_getdev = efi_getdev;
-	archsw.arch_copyin = efi_copyin;
-	archsw.arch_copyout = efi_copyout;
-	archsw.arch_readin = efi_readin;
-#ifdef EFI_ZFS_BOOT
-        /* Note this needs to be set before ZFS init. */
-        archsw.arch_zfs_probe = efi_zfs_probe;
+	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 = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+	if (status == EFI_UNSUPPORTED)
+		return (status);
 
-	/* Init the time source */
-	efi_time_init();
-        cons_probe();
+	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 = device_paths_match(imgpath, devpath);
+
+	/* Run through each module, see if it can load this partition */
+	for (i = 0; i < NUM_BOOT_MODULES; i++) {
+		devinfo = malloc(sizeof(*devinfo));
+		if (devinfo == NULL) {
+			DPRINTF("\nFailed to allocate devinfo\n");
+			continue;
+		}
+		devinfo->dev = blkio;
+		devinfo->devpath = devpath;
+		devinfo->devhandle = h;
+		devinfo->devdata = NULL;
+		devinfo->preferred = *preferred;
+		devinfo->next = 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)
+{
+	EFI_HANDLE *handles;
+	EFI_LOADED_IMAGE *img;
+	EFI_DEVICE_PATH *imgpath;
+	EFI_STATUS status;
+	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
+	SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
+	UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
+	CHAR16 *text;
+
+	/* Basic initialization*/
+	ST = Xsystab;
+	IH = Ximage;
+	BS = ST->BootServices;
+	RS = ST->RuntimeServices;
+
+	/* Set up the console, so printf works. */
+	status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
+	    (VOID **)&ConsoleControl);
+	if (status == EFI_SUCCESS)
+		(void)ConsoleControl->SetMode(ConsoleControl,
+		    EfiConsoleControlScreenText);
 	/*
 	 * Reset the console and find the best text mode.
 	 */
 	conout = ST->ConOut;
 	conout->Reset(conout, TRUE);
 	max_dim = best_mode = 0;
-
-        for (i = 0; ; i++) {
+	for (i = 0; ; i++) {
 		status = conout->QueryMode(conout, i, &cols, &rows);
 		if (EFI_ERROR(status))
 			break;
@@ -638,37 +440,31 @@ main(int argc __unused, CHAR16 *argv[] __unused)
 			best_mode = i;
 		}
 	}
-
-        if (max_dim > 0)
+	if (max_dim > 0)
 		conout->SetMode(conout, best_mode);
-
 	conout->EnableCursor(conout, TRUE);
 	conout->ClearScreen(conout);
 
-        /* Print this here, so people know it's at least starting. */
 	printf("\n>> FreeBSD EFI boot block\n");
 	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
-
-        /* Get the image path and trim it to get the disk on which we
-         * found this loader.
-         */
-	if ((status = BS->OpenProtocol(IH, &LoadedImageGUID,
-            (VOID**)&boot_image, IH, NULL,
-            EFI_OPEN_PROTOCOL_GET_PROTOCOL)) != EFI_SUCCESS) {
-		panic("Failed to query LoadedImage (%lu)\n",
-		    EFI_ERROR_CODE(status));
+	printf("   Initializing modules:");
+	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');
 
 	/* Determine the devpath of our image so we can prefer it. */
-	status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&boot_image);
+	status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img);
 	imgpath = NULL;
 	if (status == EFI_SUCCESS) {
-		text = efi_devpath_name(boot_image->FilePath);
+		text = efi_devpath_name(img->FilePath);
 		printf("   Load Path: %S\n", text);
 		efi_setenv_freebsd_wcs("Boot1Path", text);
 		efi_free_devpath_name(text);
 
-		status = BS->HandleProtocol(boot_image->DeviceHandle, &DevicePathGUID,
+		status = BS->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
 		    (void **)&imgpath);
 		if (status != EFI_SUCCESS) {
 			DPRINTF("Failed to get image DevicePath (%lu)\n",
@@ -682,36 +478,49 @@ main(int argc __unused, CHAR16 *argv[] __unused)
 
 	}
 
-        /* The loaded image device path ends with a partition, then a
-         * file path.  Trim them both to get the actual disk.
-         */
-        if ((imgprefix = efi_devpath_trim(imgpath)) == NULL ||
-            (imgprefix = efi_devpath_trim(imgprefix)) == NULL) {
-                panic("Couldn't trim device path");
-        }
+	/* Get all the device handles */
+	hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
+	handles = malloc(hsize);
+	if (handles == NULL) {
+		printf("Failed to allocate %d handles\n", NUM_HANDLES_INIT);
+	}
 
-	/*
-	 * Initialize the block cache. Set the upper limit.
-	 */
-	bcache_init(32768, 512);
-
-	printf("\n   Initializing modules:");
-
-	for (i = 0; efi_drivers[i] != NULL; i++) {
-		printf(" %s", efi_drivers[i]->name);
-		if (efi_drivers[i]->init != NULL)
-			efi_drivers[i]->init();
+	status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
+	    &hsize, handles);
+	switch (status) {
+	case EFI_SUCCESS:
+		break;
+	case EFI_BUFFER_TOO_SMALL:
+		free(handles);
+		handles = malloc(hsize);
+		if (handles == NULL)
+			efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n",
+			    NUM_HANDLES_INIT);
+		status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
+		    NULL, &hsize, handles);
+		if (status != EFI_SUCCESS)
+			efi_panic(status, "Failed to get device handles\n");
+		break;
+	default:
+		efi_panic(status, "Failed to get device handles\n");
+		break;
 	}
 
-	for (i = 0; devsw[i] != NULL; i++) {
-                if (devsw[i]->dv_init != NULL) {
-                        printf(" %s", devsw[i]->dv_name);
-			(devsw[i]->dv_init)();
-                }
-        }
+	/* Scan all partitions, probing with all modules. */
+	nhandles = hsize / sizeof(*handles);
+	printf("   Probing %zu block devices...", nhandles);
+	DPRINTF("\n");
 
-	putchar('\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();
+	}

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


More information about the svn-src-all mailing list