Page MenuHomeFreeBSD

D10447.id31601.diff
No OneTemporary

D10447.id31601.diff

Index: sys/boot/efi/boot1/Makefile
===================================================================
--- sys/boot/efi/boot1/Makefile
+++ sys/boot/efi/boot1/Makefile
@@ -8,17 +8,23 @@
PROG= boot1.sym
INTERNALPROG=
-WARNS?= 6
+WARNS?= 3
+
+# Include bcache code.
+HAVE_BCACHE= yes
.if ${MK_ZFS} != "no"
# 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.boot1.c += -Wno-missing-variable-declarations
+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
@@ -27,20 +33,29 @@
.endif
.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}
@@ -64,6 +79,17 @@
.PATH: ${.CURDIR}/../../common
CFLAGS+= -I${.CURDIR}/../../common
+# make buildenv doesn't set DESTDIR, this means LIBSTAND
+# will be wrong when crossbuilding.
+.if exists(${.OBJDIR}/../../../../lib/libstand/libstand.a)
+LIBSTAND= ${.OBJDIR}/../../../../lib/libstand/libstand.a
+.endif
+
+# Add libefi
+.PATH: ${.CURDIR}/../libefi
+LIBEFI= ${.OBJDIR}/../libefi/libefi.a
+
+
FILES= boot1.efi boot1.efifat
FILESMODE_boot1.efi= ${BINMODE}
@@ -83,8 +109,8 @@
# __aeabi_* (arm) or __divdi3 (i386).
# as well as required string and memory functions for all platforms.
#
-DPADD+= ${LIBSTAND}
-LDADD+= -lstand
+DPADD+= ${LIBEFI} ${LIBSTAND}
+LDADD+= ${LIBEFI} ${LIBSTAND}
DPADD+= ${LDSCRIPT}
@@ -110,7 +136,7 @@
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: ${.CURDIR}/../../common/ufsread.c
@@ -119,7 +145,7 @@
# created by generate-fat.sh
.include "${.CURDIR}/Makefile.fat"
-BOOT1_MAXSIZE?= 131072
+BOOT1_MAXSIZE?= 524288
boot1.efifat: boot1.efi
@set -- `ls -l ${.ALLSRC}`; \
Index: sys/boot/efi/boot1/boot1.c
===================================================================
--- sys/boot/efi/boot1/boot1.c
+++ sys/boot/efi/boot1/boot1.c
@@ -23,64 +23,124 @@
__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
-#include "boot_module.h"
+#include <bootstrap.h>
+
+#include "efi_drivers.h"
+#include "efizfs.h"
#include "paths.h"
-static const boot_module_t *boot_modules[] =
-{
+#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
+
+#ifdef EFI_ZFS_BOOT
+uint64_t pool_guid;
+#endif
+
+struct fs_ops *file_system[] = {
#ifdef EFI_ZFS_BOOT
- &zfs_module,
+ &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)
-/* The initial number of handles used to query EFI for partitions. */
-#define NUM_HANDLES_INIT 24
+struct devsw *devsw[] = {
+ &efipart_hddev,
+ &efipart_fddev,
+ &efipart_cddev,
+#ifdef EFI_ZFS_BOOT
+ &zfs_dev,
+#endif
+ NULL
+};
-EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
+struct console *consoles[] = {
+ &efi_console,
+ NULL
+};
-EFI_SYSTEM_TABLE *systab;
-EFI_BOOT_SERVICES *bs;
-static EFI_HANDLE *image;
+/* Definitions we don't actually need for boot, but we need to define
+ * to make the linker happy.
+ */
+struct file_format *file_formats[] = { NULL };
-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;
+struct netif_driver *netif_drivers[] = { NULL };
-/*
- * 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 int
+efi_autoload(void)
{
- void *out;
+ printf("******** Boot block should not call autoload\n");
+ return (-1);
+}
- if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
- return (out);
+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);
+}
- return (NULL);
+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);
}
-void
-Free(void *buf, const char *file __unused, int line __unused)
+static ssize_t
+efi_readin(int fd __unused, vm_offset_t dest __unused,
+ const size_t len __unused)
{
- if (buf != NULL)
- (void)bs->FreePool(buf);
+ 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 DevicePathGUID = DEVICE_PATH_PROTOCOL;
+static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
+
/*
* nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
* FALSE otherwise.
@@ -141,6 +201,7 @@
return (devpath);
}
+#ifdef EFI_DEBUG
/*
* devpath_node_str is a basic output method for a devpath node which
* only understands a subset of the available sub types.
@@ -272,7 +333,7 @@
* devpath_strlcat appends a text description of devpath to buf but not more
* than size - 1 characters followed by NUL-terminator.
*/
-int
+static int
devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
{
size_t len, used;
@@ -303,48 +364,366 @@
* devpath_str is convenience method which returns the text description of
* devpath using a static buffer, so it isn't thread safe!
*/
-char *
+static char *
devpath_str(EFI_DEVICE_PATH *devpath)
{
static char buf[256];
devpath_strlcat(buf, sizeof(buf), devpath);
- return buf;
+ return (buf);
}
+#endif
-/*
- * 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)
+do_load(const char *filepath, void **bufp, size_t *bufsize)
{
- UINTN i;
- dev_info_t *dev;
- const boot_module_t *mod;
-
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- mod = boot_modules[i];
- for (dev = mod->devices(); dev != NULL; dev = dev->next) {
- if (dev->preferred != preferred)
- continue;
-
- if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
- EFI_SUCCESS) {
- *devinfop = dev;
- *modp = mod;
- return (EFI_SUCCESS);
+ struct stat st;
+ void *buf = NULL;
+ int fd, err;
+ size_t fsize, remaining;
+ ssize_t readsize;
+
+ if ((fd = open(filepath, O_RDONLY)) < 0) {
+ return (ENOTSUP);
+ }
+
+ if ((err = fstat(fd, &st)) != 0) {
+ goto close_file;
+ }
+
+ 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 int
+probe_fs(const char *filepath)
+{
+ int fd;
+
+ if ((fd = open(filepath, O_RDONLY)) < 0) {
+ return (ENOTSUP);
+ }
+
+ close(fd);
+
+ return (0);
+}
+
+static int
+probe_dev(struct devsw *dev, int unit, const char *filepath)
+{
+ 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);
+
+ env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
+ env_nounset);
+
+ err = probe_fs(filepath);
+
+ return (err);
+}
+
+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;
+ EFI_DEVICE_PATH *devpath, *copy;
+ EFI_HANDLE h;
+ struct devsw *dev;
+ int unit;
+ uint64_t extra;
+ char *devname;
+
+#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 = img->DeviceHandle;
+ 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 (dp->pd_handle == img->DeviceHandle &&
+ probe_fs(filepath) == 0 &&
+ do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
+ *handlep = img->DeviceHandle;
+ return (0);
+ }
+
+ /* Assuming GPT partitioning. */
+ STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
+ if (pp->pd_handle == img->DeviceHandle) {
+ currdev.d_slice = pp->pd_unit;
+ currdev.d_partition = 255;
+ devname = efi_fmtdev(&currdev);
+
+ env_setenv("currdev", EV_VOLATILE, devname,
+ efi_setcurrdev, env_nounset);
+
+ if (probe_fs(filepath) == 0 &&
+ do_load(filepath, bufp, bufsize) ==
+ EFI_SUCCESS) {
+ *handlep = img->DeviceHandle;
+ 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) &&
+ probe_dev(&efipart_cddev, dp->pd_unit, filepath) == 0 &&
+ do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
+ *handlep = img->DeviceHandle;
+ return (0);
+ }
+ }
+
+ pdi_list = efiblk_get_pdinfo_list(&efipart_fddev);
+ STAILQ_FOREACH(dp, pdi_list, pd_link) {
+ if (dp->pd_handle == img->DeviceHandle &&
+ probe_dev(&efipart_cddev, dp->pd_unit, filepath) == 0 &&
+ do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
+ *handlep = img->DeviceHandle;
+ return (0);
+ }
+ }
+
+ /*
+ * Try the device handle from our loaded image first. If that
+ * fails, use the device path from the loaded image and see if
+ * any of the nodes in that path match one of the enumerated
+ * handles.
+ */
+ if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &extra) == 0 &&
+ probe_dev(dev, dp->pd_unit, filepath) == 0 &&
+ do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
+ *handlep = img->DeviceHandle;
+ return (0);
+ }
+
+ copy = NULL;
+ devpath = efi_lookup_image_devpath(IH);
+ while (devpath != NULL) {
+ h = efi_devpath_handle(devpath);
+ if (h == NULL)
+ break;
+
+ free(copy);
+ copy = NULL;
+
+ if (efi_handle_lookup(h, &dev, &unit, &extra) == 0 &&
+ probe_dev(dev, dp->pd_unit, filepath) == 0 &&
+ do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
+ *handlep = img->DeviceHandle;
+ return (0);
+ }
+
+ devpath = efi_lookup_devpath(h);
+ if (devpath != NULL) {
+ copy = efi_devpath_trim(devpath);
+ devpath = copy;
+ }
+ }
+ free(copy);
+
+ return (ENOENT);
+}
+
+static int
+load_all(const char *filepath, void **bufp, size_t *bufsize,
+ EFI_HANDLE *handlep)
+{
+ pdinfo_list_t *pdi_list;
+ pdinfo_t *dp, *pp;
+ zfsinfo_list_t *zfsi_list;
+ zfsinfo_t *zi;
+ char *devname;
+
+#ifdef EFI_ZFS_BOOT
+ zfsi_list = efizfs_get_zfsinfo_list();
+ STAILQ_FOREACH(zi, zfsi_list, zi_link) {
+ 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 = 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;
+ printf("Succeeded\n");
+
+ 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)
+{
+ EFI_LOADED_IMAGE *boot_image;
+ EFI_STATUS status;
+
+ 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));
+ }
+
+ /* 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);
}
@@ -358,20 +737,27 @@
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(&fshandle, &loaderbuf, &loadersize);
+
+ if (status != EFI_SUCCESS) {
+ return (status);
+ }
- status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
- if (status != EFI_SUCCESS) {
- status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
- FALSE);
+ 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));
}
/*
@@ -386,9 +772,9 @@
*/
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);
@@ -400,24 +786,25 @@
buf = NULL;
}
- if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath),
+ if ((status = BS->LoadImage(TRUE, IH, devpath_last(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;
@@ -433,10 +820,10 @@
DSTALL(1000000);
DPRINTF(".\n");
- if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
+ 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;
}
@@ -452,135 +839,33 @@
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);
-
- if (status != EFI_SUCCESS) {
- DPRINTF("\nFailed to query DevicePath (%lu)\n",
- EFI_ERROR_CODE(status));
- return (status);
- }
+ SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
+ UINTN i, max_dim, best_mode, cols, rows;
- DPRINTF("probing: %s\n", devpath_str(devpath));
-
- 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);
- }
-
- if (!blkio->Media->LogicalPartition)
- return (EFI_UNSUPPORTED);
-
- *preferred = device_paths_match(imgpath, devpath);
+ 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
- /* Run through each module, see if it can load this partition */
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- if ((status = bs->AllocatePool(EfiLoaderData,
- sizeof(*devinfo), (void **)&devinfo)) !=
- EFI_SUCCESS) {
- DPRINTF("\nFailed to allocate devinfo (%lu)\n",
- EFI_ERROR_CODE(status));
- 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);
- (void)bs->FreePool(devinfo);
- }
+ /* Init the time source */
+ efi_time_init();
- return (EFI_UNSUPPORTED);
-}
+ cons_probe();
-/*
- * 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;
-
- /* Basic initialization*/
- systab = Xsystab;
- image = Ximage;
- bs = Xsystab->BootServices;
-
- /* 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 = systab->ConOut;
+ conout = ST->ConOut;
conout->Reset(conout, TRUE);
max_dim = best_mode = 0;
for (i = 0; ; i++) {
@@ -597,123 +882,39 @@
conout->EnableCursor(conout, TRUE);
conout->ClearScreen(conout);
- 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();
- }
- putchar('\n');
+ /*
+ * Initialise the block cache. Set the upper limit.
+ */
+ bcache_init(32768, 512);
- /* Get all the device handles */
- hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
- if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
- != EFI_SUCCESS)
- panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
- EFI_ERROR_CODE(status));
+ printf("\n>> FreeBSD EFI boot block\n");
- status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
- &hsize, handles);
- switch (status) {
- case EFI_SUCCESS:
- break;
- case EFI_BUFFER_TOO_SMALL:
- (void)bs->FreePool(handles);
- if ((status = bs->AllocatePool(EfiLoaderData, hsize,
- (void **)&handles)) != EFI_SUCCESS) {
- panic("Failed to allocate %zu handles (%lu)", hsize /
- sizeof(*handles), EFI_ERROR_CODE(status));
- }
- status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
- NULL, &hsize, handles);
- if (status != EFI_SUCCESS)
- panic("Failed to get device handles (%lu)\n",
- EFI_ERROR_CODE(status));
- break;
- default:
- panic("Failed to get device handles (%lu)",
- EFI_ERROR_CODE(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;
- /* Scan all partitions, probing with all modules. */
- nhandles = hsize / sizeof(*handles);
- printf(" Probing %zu block devices...", nhandles);
- DPRINTF("\n");
+ printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
+ printf(" Initializing modules:");
- /* Determine the devpath of our image so we can prefer it. */
- status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
- imgpath = NULL;
- if (status == EFI_SUCCESS) {
- status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
- (void **)&imgpath);
- if (status != EFI_SUCCESS)
- DPRINTF("Failed to get image DevicePath (%lu)\n",
- EFI_ERROR_CODE(status));
- DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
+ 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; i < nhandles; i++)
- probe_handle_status(handles[i], imgpath);
- printf(" done\n");
+ for (i = 0; devsw[i] != NULL; i++) {
+ if (devsw[i]->dv_init != NULL) {
+ printf(" %s", devsw[i]->dv_name);
+ (devsw[i]->dv_init)();
+ }
+ }
- /* Status summary. */
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- printf(" ");
- boot_modules[i]->status();
- }
+ putchar('\n');
try_boot();
/* If we get here, we're out of luck... */
panic("No bootable partitions found!");
}
-
-/*
- * add_device adds a device to the passed devinfo list.
- */
-void
-add_device(dev_info_t **devinfop, dev_info_t *devinfo)
-{
- dev_info_t *dev;
-
- if (*devinfop == NULL) {
- *devinfop = devinfo;
- return;
- }
-
- for (dev = *devinfop; dev->next != NULL; dev = dev->next)
- ;
-
- dev->next = devinfo;
-}
-
-void
-panic(const char *fmt, ...)
-{
- va_list ap;
-
- printf("panic: ");
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- printf("\n");
-
- while (1) {}
-}
-
-void
-putchar(int c)
-{
- CHAR16 buf[2];
-
- if (c == '\n') {
- buf[0] = '\r';
- buf[1] = 0;
- systab->ConOut->OutputString(systab->ConOut, buf);
- }
- buf[0] = c;
- buf[1] = 0;
- systab->ConOut->OutputString(systab->ConOut, buf);
-}
Index: sys/boot/efi/boot1/boot_module.h
===================================================================
--- sys/boot/efi/boot1/boot_module.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-
- * Copyright (c) 2015 Eric McCorkle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _BOOT_MODULE_H_
-#define _BOOT_MODULE_H_
-
-#include <stdbool.h>
-
-#include <efi.h>
-#include <efilib.h>
-#include <eficonsctl.h>
-
-#ifdef EFI_DEBUG
-#define DPRINTF(fmt, args...) printf(fmt, ##args)
-#define DSTALL(d) bs->Stall(d)
-#else
-#define DPRINTF(fmt, ...) {}
-#define DSTALL(d) {}
-#endif
-
-/* EFI device info */
-typedef struct dev_info
-{
- EFI_BLOCK_IO *dev;
- EFI_DEVICE_PATH *devpath;
- EFI_HANDLE *devhandle;
- void *devdata;
- BOOLEAN preferred;
- struct dev_info *next;
-} dev_info_t;
-
-/*
- * A boot loader module.
- *
- * This is a standard interface for filesystem modules in the EFI system.
- */
-typedef struct boot_module_t
-{
- const char *name;
-
- /* init is the optional initialiser for the module. */
- void (*init)(void);
-
- /*
- * probe checks to see if the module can handle dev.
- *
- * Return codes:
- * EFI_SUCCESS = The module can handle the device.
- * EFI_NOT_FOUND = The module can not handle the device.
- * Other = The module encountered an error.
- */
- EFI_STATUS (*probe)(dev_info_t* dev);
-
- /*
- * load should select the best out of a set of devices that probe
- * indicated were loadable and load the specified file.
- *
- * Return codes:
- * EFI_SUCCESS = The module can handle the device.
- * EFI_NOT_FOUND = The module can not handle the device.
- * Other = The module encountered an error.
- */
- EFI_STATUS (*load)(const char *filepath, dev_info_t *devinfo,
- void **buf, size_t *bufsize);
-
- /* status outputs information about the probed devices. */
- void (*status)(void);
-
- /* valid devices as found by probe. */
- dev_info_t *(*devices)(void);
-} boot_module_t;
-
-/* Standard boot modules. */
-#ifdef EFI_UFS_BOOT
-extern const boot_module_t ufs_module;
-#endif
-#ifdef EFI_ZFS_BOOT
-extern const boot_module_t zfs_module;
-#endif
-
-/* Functions available to modules. */
-extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo);
-extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
-
-extern EFI_SYSTEM_TABLE *systab;
-extern EFI_BOOT_SERVICES *bs;
-
-extern int devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath);
-extern char *devpath_str(EFI_DEVICE_PATH *devpath);
-#endif
Index: sys/boot/efi/boot1/ufs_module.c
===================================================================
--- sys/boot/efi/boot1/ufs_module.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*-
- * Copyright (c) 1998 Robert Nordier
- * All rights reserved.
- * Copyright (c) 2001 Robert Drehmel
- * All rights reserved.
- * Copyright (c) 2014 Nathan Whitehorn
- * All rights reserved.
- * Copyright (c) 2015 Eric McCorkle
- * All rights reverved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <stdarg.h>
-#include <stdbool.h>
-#include <sys/cdefs.h>
-#include <sys/param.h>
-#include <efi.h>
-
-#include "boot_module.h"
-
-static dev_info_t *devinfo;
-static dev_info_t *devices;
-
-static int
-dskread(void *buf, u_int64_t lba, int nblk)
-{
- int size;
- EFI_STATUS status;
-
- lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE);
- size = nblk * DEV_BSIZE;
-
- status = devinfo->dev->ReadBlocks(devinfo->dev,
- devinfo->dev->Media->MediaId, lba, size, buf);
-
- if (status != EFI_SUCCESS) {
- DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, "
- "status: %lu\n", devinfo->dev,
- devinfo->dev->Media->MediaId, (uintmax_t)lba, size,
- EFI_ERROR_CODE(status));
- return (-1);
- }
-
- return (0);
-}
-
-#include "ufsread.c"
-
-static struct dmadat __dmadat;
-
-static int
-init_dev(dev_info_t* dev)
-{
-
- devinfo = dev;
- dmadat = &__dmadat;
-
- return fsread(0, NULL, 0);
-}
-
-static EFI_STATUS
-probe(dev_info_t* dev)
-{
-
- if (init_dev(dev) < 0)
- return (EFI_UNSUPPORTED);
-
- add_device(&devices, dev);
-
- return (EFI_SUCCESS);
-}
-
-static EFI_STATUS
-load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize)
-{
- ufs_ino_t ino;
- EFI_STATUS status;
- size_t size;
- ssize_t read;
- void *buf;
-
- DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath));
-
- if (init_dev(dev) < 0) {
- DPRINTF("Failed to init device\n");
- return (EFI_UNSUPPORTED);
- }
-
- if ((ino = lookup(filepath)) == 0) {
- DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath);
- return (EFI_NOT_FOUND);
- }
-
- if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) {
- printf("Failed to read size of '%s' ino: %d\n", filepath, ino);
- return (EFI_INVALID_PARAMETER);
- }
-
- if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) !=
- EFI_SUCCESS) {
- printf("Failed to allocate read buffer %zu for '%s' (%lu)\n",
- size, filepath, EFI_ERROR_CODE(status));
- return (status);
- }
-
- read = fsread(ino, buf, size);
- if ((size_t)read != size) {
- printf("Failed to read '%s' (%zd != %zu)\n", filepath, read,
- size);
- (void)bs->FreePool(buf);
- return (EFI_INVALID_PARAMETER);
- }
-
- DPRINTF("Load complete\n");
-
- *bufp = buf;
- *bufsize = size;
-
- return (EFI_SUCCESS);
-}
-
-static void
-status(void)
-{
- int i;
- dev_info_t *dev;
-
- for (dev = devices, i = 0; dev != NULL; dev = dev->next, i++)
- ;
-
- printf("%s found ", ufs_module.name);
- switch (i) {
- case 0:
- printf("no partitions\n");
- break;
- case 1:
- printf("%d partition\n", i);
- break;
- default:
- printf("%d partitions\n", i);
- }
-}
-
-static dev_info_t *
-_devices(void)
-{
-
- return (devices);
-}
-
-const boot_module_t ufs_module =
-{
- .name = "UFS",
- .probe = probe,
- .load = load,
- .status = status,
- .devices = _devices
-};
Index: sys/boot/efi/boot1/zfs_module.c
===================================================================
--- sys/boot/efi/boot1/zfs_module.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*-
- * Copyright (c) 2015 Eric McCorkle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-#include <stddef.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <sys/cdefs.h>
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <efi.h>
-
-#include "boot_module.h"
-
-#include "libzfs.h"
-#include "zfsimpl.c"
-
-static dev_info_t *devices;
-
-uint64_t
-ldi_get_size(void *priv)
-{
- dev_info_t *devinfo = priv;
-
- return (devinfo->dev->Media->BlockSize *
- (devinfo->dev->Media->LastBlock + 1));
-}
-
-static int
-vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
-{
- dev_info_t *devinfo;
- uint64_t lba;
- size_t size, remainder, rb_size, blksz;
- char *bouncebuf = NULL, *rb_buf;
- EFI_STATUS status;
-
- devinfo = (dev_info_t *)priv;
- lba = off / devinfo->dev->Media->BlockSize;
- remainder = off % devinfo->dev->Media->BlockSize;
-
- rb_buf = buf;
- rb_size = bytes;
-
- /*
- * If we have remainder from off, we need to add remainder part.
- * Since buffer must be multiple of the BlockSize, round it all up.
- */
- size = roundup2(bytes + remainder, devinfo->dev->Media->BlockSize);
- blksz = size;
- if (remainder != 0 || size != bytes) {
- rb_size = devinfo->dev->Media->BlockSize;
- bouncebuf = malloc(rb_size);
- if (bouncebuf == NULL) {
- printf("vdev_read: out of memory\n");
- return (-1);
- }
- rb_buf = bouncebuf;
- blksz = rb_size - remainder;
- }
-
- while (bytes > 0) {
- status = devinfo->dev->ReadBlocks(devinfo->dev,
- devinfo->dev->Media->MediaId, lba, rb_size, rb_buf);
- if (EFI_ERROR(status))
- goto error;
- if (bytes < blksz)
- blksz = bytes;
- if (bouncebuf != NULL)
- memcpy(buf, rb_buf + remainder, blksz);
- buf = (void *)((uintptr_t)buf + blksz);
- bytes -= blksz;
- lba++;
- remainder = 0;
- blksz = rb_size;
- }
-
- free(bouncebuf);
- return (0);
-
-error:
- free(bouncebuf);
- DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %ju, size: %zu,"
- " rb_size: %zu, status: %lu\n", devinfo->dev,
- devinfo->dev->Media->MediaId, (uintmax_t)lba, bytes, rb_size,
- EFI_ERROR_CODE(status));
- return (-1);
-}
-
-static EFI_STATUS
-probe(dev_info_t *dev)
-{
- spa_t *spa;
- dev_info_t *tdev;
- EFI_STATUS status;
-
- /* ZFS consumes the dev on success so we need a copy. */
- if ((status = bs->AllocatePool(EfiLoaderData, sizeof(*dev),
- (void**)&tdev)) != EFI_SUCCESS) {
- DPRINTF("Failed to allocate tdev (%lu)\n",
- EFI_ERROR_CODE(status));
- return (status);
- }
- memcpy(tdev, dev, sizeof(*dev));
-
- if (vdev_probe(vdev_read, tdev, &spa) != 0) {
- (void)bs->FreePool(tdev);
- return (EFI_UNSUPPORTED);
- }
-
- dev->devdata = spa;
- add_device(&devices, dev);
-
- return (EFI_SUCCESS);
-}
-
-static EFI_STATUS
-load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize)
-{
- spa_t *spa;
- struct zfsmount zfsmount;
- dnode_phys_t dn;
- struct stat st;
- int err;
- void *buf;
- EFI_STATUS status;
-
- spa = devinfo->devdata;
-
- DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name,
- devpath_str(devinfo->devpath));
-
- if ((err = zfs_spa_init(spa)) != 0) {
- DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err);
- return (EFI_NOT_FOUND);
- }
-
- if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) {
- DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
- return (EFI_NOT_FOUND);
- }
-
- if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) {
- if (err == ENOENT) {
- DPRINTF("Failed to find '%s' on pool '%s' (%d)\n",
- filepath, spa->spa_name, err);
- return (EFI_NOT_FOUND);
- }
- printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath,
- spa->spa_name, err);
- return (EFI_INVALID_PARAMETER);
- }
-
- if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
- printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath,
- spa->spa_name, err);
- return (EFI_INVALID_PARAMETER);
- }
-
- if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
- != EFI_SUCCESS) {
- printf("Failed to allocate load buffer %jd for pool '%s' for '%s' "
- "(%lu)\n", (intmax_t)st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status));
- return (EFI_INVALID_PARAMETER);
- }
-
- if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) {
- printf("Failed to read node from %s (%d)\n", spa->spa_name,
- err);
- (void)bs->FreePool(buf);
- return (EFI_INVALID_PARAMETER);
- }
-
- *bufsize = st.st_size;
- *bufp = buf;
-
- return (EFI_SUCCESS);
-}
-
-static void
-status(void)
-{
- spa_t *spa;
-
- spa = STAILQ_FIRST(&zfs_pools);
- if (spa == NULL) {
- printf("%s found no pools\n", zfs_module.name);
- return;
- }
-
- printf("%s found the following pools:", zfs_module.name);
- STAILQ_FOREACH(spa, &zfs_pools, spa_link)
- printf(" %s", spa->spa_name);
-
- printf("\n");
-}
-
-static void
-init(void)
-{
-
- zfs_init();
-}
-
-static dev_info_t *
-_devices(void)
-{
-
- return (devices);
-}
-
-const boot_module_t zfs_module =
-{
- .name = "ZFS",
- .init = init,
- .probe = probe,
- .load = load,
- .status = status,
- .devices = _devices
-};

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 9, 8:00 PM (6 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29455247
Default Alt Text
D10447.id31601.diff (44 KB)

Event Timeline