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

Warner Losh imp at FreeBSD.org
Mon Oct 16 03:59:13 UTC 2017


Author: imp
Date: Mon Oct 16 03:59:11 2017
New Revision: 324646
URL: https://svnweb.freebsd.org/changeset/base/324646

Log:
  Unify boot1 with loader
  
  Refactor boot1 to use the same I/O code as /boot/loader uses. Refactor
  to use the common efi_main.c.
  
  Submitted by: Eric McCorkle
  Differential Revision: https://reviews.freebsd.org/D10447

Added:
  head/sys/boot/efi/libefi/efi_main.c   (contents, props changed)
     - copied, changed from r324645, head/sys/boot/efi/loader/efi_main.c
Deleted:
  head/sys/boot/efi/boot1/boot_module.h
  head/sys/boot/efi/boot1/ufs_module.c
  head/sys/boot/efi/boot1/zfs_module.c
  head/sys/boot/efi/loader/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	Sun Oct 15 23:54:04 2017	(r324645)
+++ head/sys/boot/efi/boot1/Makefile	Mon Oct 16 03:59:11 2017	(r324646)
@@ -8,8 +8,11 @@ MK_SSP=		no
 
 PROG=		boot1.sym
 INTERNALPROG=
-WARNS?=		6
+WARNS?=		3
 
+# 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
@@ -18,13 +21,15 @@ WARNS?=		6
 CWARNFLAGS.boot1.c+=	-Wno-format
 
 # 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
-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.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.skein.c += -Wno-cast-align
 .if ${COMPILER_TYPE} == "clang"
 CWARNFLAGS.skein.c += -Wno-missing-variable-declarations
@@ -33,19 +38,27 @@ CWARNFLAGS.skein.c += -Wno-missing-declarations
 .endif
 
 # architecture-specific loader code
-SRCS=	boot1.c self_reloc.c start.S ufs_module.c
+SRCS=	boot1.c self_reloc.c start.S
 .if ${MK_ZFS} != "no"
-SRCS+=		zfs_module.c
+.PATH:		${.CURDIR}/../../../crypto/skein
 SRCS+=		skein.c skein_block.c
 # Do not unroll skein loops, reduce code size
 CFLAGS+=	-DSKEIN_LOOP=111
-.PATH:		${.CURDIR}/../../../crypto/skein
+.PATH:		${.CURDIR}/../../zfs
+SRCS+=		zfs.c
 .endif
 
 .if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} > 40201
 CWARNFLAGS.self_reloc.c+=	-Wno-error=maybe-uninitialized
 .endif
 
+# Always add MI sources
+.PATH:		${.CURDIR}/../../common
+.include	"${.CURDIR}/../../common/Makefile.inc"
+CFLAGS+=	-I${.CURDIR}/../../common
+
+.PATH: ${.CURDIR}/arch/${MACHINE}
+
 CFLAGS+=	-I.
 CFLAGS+=	-I${.CURDIR}/../include
 CFLAGS+=	-I${.CURDIR}/../include/${MACHINE}
@@ -117,7 +130,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 .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
 		--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	Sun Oct 15 23:54:04 2017	(r324645)
+++ head/sys/boot/efi/boot1/boot1.c	Mon Oct 16 03:59:11 2017	(r324646)
@@ -23,61 +23,179 @@
 __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 "boot_module.h"
+#include <bootstrap.h>
+
+#include "efi_drivers.h"
+#include "efizfs.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
 
-static const boot_module_t *boot_modules[] =
-{
+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
+
 #ifdef EFI_ZFS_BOOT
-	&zfs_module,
+uint64_t pool_guid;
 #endif
+
+struct fs_ops *file_system[] = {
+#ifdef EFI_ZFS_BOOT
+	&zfs_fsops,
+#endif
+	&dosfs_fsops,
 #ifdef EFI_UFS_BOOT
-	&ufs_module
+	&ufs_fsops,
 #endif
+	&cd9660_fsops,
+	&nfs_fsops,
+	&gzipfs_fsops,
+	&bzipfs_fsops,
+	NULL
 };
 
-#define	NUM_BOOT_MODULES	nitems(boot_modules)
+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);
+}
+
 /* 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;
 
-/*
- * 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)
+static EFI_STATUS
+do_load(const char *filepath, void **bufp, size_t *bufsize)
 {
-	void *out;
+	struct stat st;
+        void *buf = NULL;
+        int fd, err;
+        size_t fsize, remaining;
+        ssize_t readsize;
 
-	if (BS->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
-		return (out);
+        if ((fd = open(filepath, O_RDONLY)) < 0) {
+                return (ENOTSUP);
+        }
 
-	return (NULL);
-}
+        if ((err = fstat(fd, &st)) != 0) {
+                goto close_file;
+        }
 
-void
-Free(void *buf, const char *file __unused, int line __unused)
-{
-	if (buf != NULL)
-		(void)BS->FreePool(buf);
+        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;
 }
 
 static EFI_STATUS
@@ -97,98 +215,275 @@ efi_setenv_freebsd_wcs(const char *varname, CHAR16 *va
 	return (rv);
 }
 
-/*
- * 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)
+static int
+probe_fs(const char *filepath)
 {
-	size_t len;
+        int fd;
 
-	if (imgpath == NULL || imgpath->Type != devpath->Type ||
-	    imgpath->SubType != devpath->SubType)
-		return (FALSE);
+        if ((fd = open(filepath, O_RDONLY)) < 0) {
+                return (ENOTSUP);
+        }
 
-	len = DevicePathNodeLength(imgpath);
-	if (len != DevicePathNodeLength(devpath))
-		return (FALSE);
+        close(fd);
 
-	return (memcmp(imgpath, devpath, (size_t)len) == 0);
+        return (0);
 }
 
-/*
- * 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)
+static int
+probe_dev(struct devsw *dev, int unit, const char *filepath)
 {
+        struct devdesc currdev;
+        char *devname;
+        int err;
 
-	if (imgpath == NULL)
-		return (FALSE);
+	currdev.d_dev = dev;
+	currdev.d_type = currdev.d_dev->dv_type;
+	currdev.d_unit = unit;
+	currdev.d_opendata = NULL;
+        devname = efi_fmtdev(&currdev);
 
-	while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
-		if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
-		    IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
-			return (TRUE);
+        env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
+            env_nounset);
 
-		if (!nodes_match(imgpath, devpath))
-			return (FALSE);
+        err = probe_fs(filepath);
 
-		imgpath = NextDevicePathNode(imgpath);
-		devpath = NextDevicePathNode(devpath);
-	}
+        return (err);
+}
 
-	return (FALSE);
+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);
 }
 
-/*
- * devpath_last returns the last non-path end node in devpath.
- */
-static EFI_DEVICE_PATH *
-devpath_last(EFI_DEVICE_PATH *devpath)
+bool
+efi_zfs_is_preferred(EFI_HANDLE *h)
 {
+         return (check_preferred(h));
+}
 
-	while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
-		devpath = NextDevicePathNode(devpath);
+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;
 
-	return (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);
 }
 
-/*
- * 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)
+static int
+load_all(const char *filepath, void **bufp, size_t *bufsize,
+    EFI_HANDLE *handlep)
 {
-	UINTN i;
-	dev_info_t *dev;
-	const boot_module_t *mod;
+	pdinfo_list_t *pdi_list;
+	pdinfo_t *dp, *pp;
+	zfsinfo_list_t *zfsi_list;
+	zfsinfo_t *zi;
+        char *devname;
 
-	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;
+#ifdef EFI_ZFS_BOOT
+	zfsi_list = efizfs_get_zfsinfo_list();
+	STAILQ_FOREACH(zi, zfsi_list, zi_link) {
+                struct zfs_devdesc currdev;
 
-			if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
-			    EFI_SUCCESS) {
-				*devinfop = dev;
-				*modp = mod;
-				return (EFI_SUCCESS);
+		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);
 			}
 		}
 	}
 
+	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);
 }
 
@@ -202,20 +497,27 @@ try_boot(void)
 	size_t bufsize, loadersize, cmdsize;
 	void *buf, *loaderbuf;
 	char *cmd;
-	dev_info_t *dev;
-	const boot_module_t *mod;
+        EFI_HANDLE fshandle;
 	EFI_HANDLE loaderhandle;
 	EFI_LOADED_IMAGE *loaded_image;
 	EFI_STATUS status;
+        EFI_DEVICE_PATH *fspath;
 
-	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
-	if (status != EFI_SUCCESS) {
-		status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
-		    FALSE);
+	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);
 		if (status != EFI_SUCCESS) {
-			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
-			return (status);
-		}
+			DPRINTF("Failed to get image DevicePath (%lu)\n",
+			    EFI_ERROR_CODE(status));
+                }
+		DPRINTF("filesystem device path: %s\n", devpath_str(fspath));
 	}
 
 	/*
@@ -230,9 +532,9 @@ try_boot(void)
 	 */
 	cmd = NULL;
 	cmdsize = 0;
-	status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
+	status = do_load(PATH_DOTCONFIG, &buf, &bufsize);
 	if (status == EFI_NOT_FOUND)
-		status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
+		status = do_load(PATH_CONFIG, &buf, &bufsize);
 	if (status == EFI_SUCCESS) {
 		cmdsize = bufsize + 1;
 		cmd = malloc(cmdsize);
@@ -244,24 +546,25 @@ try_boot(void)
 		buf = NULL;
 	}
 
-	if ((status = BS->LoadImage(TRUE, IH, devpath_last(dev->devpath),
+	if ((status = BS->LoadImage(TRUE, IH, efi_devpath_last_node(fspath),
 	    loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
-		printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
-		     mod->name, loadersize, EFI_ERROR_CODE(status));
+		printf("Failed to load image, size: %zu, (%lu)\n",
+		     loadersize, EFI_ERROR_CODE(status));
 		goto errout;
 	}
 
-	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));
+	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));
 		goto errout;
 	}
 
 	if (cmd != NULL)
 		printf("    command args: %s\n", cmd);
 
-	loaded_image->DeviceHandle = dev->devhandle;
+	loaded_image->DeviceHandle = fshandle;
 	loaded_image->LoadOptionsSize = cmdsize;
 	loaded_image->LoadOptions = cmd;
 
@@ -279,8 +582,8 @@ try_boot(void)
 
 	if ((status = BS->StartImage(loaderhandle, NULL, NULL)) !=
 	    EFI_SUCCESS) {
-		printf("Failed to start image provided by %s (%lu)\n",
-		    mod->name, EFI_ERROR_CODE(status));
+		printf("Failed to start image (%lu)\n",
+		    EFI_ERROR_CODE(status));
 		loaded_image->LoadOptionsSize = 0;
 		loaded_image->LoadOptions = NULL;
 	}
@@ -296,142 +599,37 @@ 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)
+EFI_STATUS
+main(int argc __unused, CHAR16 *argv[] __unused)
 {
-	dev_info_t *devinfo;
-	EFI_BLOCK_IO *blkio;
-	EFI_DEVICE_PATH *devpath;
-	EFI_STATUS status;
-	UINTN i;
+        EFI_STATUS status;
 
-	/* Figure out if we're dealing with an actual partition. */
-	status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
-	if (status == EFI_UNSUPPORTED)
-		return (status);
+        SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
+        UINTN i, max_dim, best_mode, cols, rows;
+        CHAR16 *text;
 
-	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);
-	}
+        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;
 #endif
-	status = BS->HandleProtocol(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);
-	}
+	/* Init the time source */
+	efi_time_init();
+        cons_probe();
 
-	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;
@@ -440,31 +638,37 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
 			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);
-	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();
+
+        /* 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));
 	}
-	putchar('\n');
 
 	/* Determine the devpath of our image so we can prefer it. */
-	status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img);
+	status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&boot_image);
 	imgpath = NULL;
 	if (status == EFI_SUCCESS) {
-		text = efi_devpath_name(img->FilePath);
+		text = efi_devpath_name(boot_image->FilePath);
 		printf("   Load Path: %S\n", text);
 		efi_setenv_freebsd_wcs("Boot1Path", text);
 		efi_free_devpath_name(text);
 
-		status = BS->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
+		status = BS->HandleProtocol(boot_image->DeviceHandle, &DevicePathGUID,
 		    (void **)&imgpath);
 		if (status != EFI_SUCCESS) {
 			DPRINTF("Failed to get image DevicePath (%lu)\n",
@@ -478,49 +682,36 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
 
 	}
 
-	/* 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);
-	}
+        /* 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");
+        }
 
-	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;
-	}
+	/*
+	 * Initialize the block cache. Set the upper limit.
+	 */
+	bcache_init(32768, 512);
 
-	/* Scan all partitions, probing with all modules. */
-	nhandles = hsize / sizeof(*handles);
-	printf("   Probing %zu block devices...", nhandles);
-	DPRINTF("\n");
+	printf("\n   Initializing modules:");
 
-	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();
+	for (i = 0; efi_drivers[i] != NULL; i++) {
+		printf(" %s", efi_drivers[i]->name);
+		if (efi_drivers[i]->init != NULL)
+			efi_drivers[i]->init();
 	}
 
+	for (i = 0; devsw[i] != NULL; i++) {
+                if (devsw[i]->dv_init != NULL) {
+                        printf(" %s", devsw[i]->dv_name);
+			(devsw[i]->dv_init)();
+                }
+        }

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


More information about the svn-src-head mailing list