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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to