Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F136948314
D10447.id31486.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
70 KB
Referenced Files
None
Subscribers
None
D10447.id31486.diff
View Options
Index: lib/libstand/Makefile
===================================================================
--- lib/libstand/Makefile
+++ lib/libstand/Makefile
@@ -41,7 +41,7 @@
.PATH: ${LIBC_SRC}/string
SRCS+= bcmp.c bcopy.c bzero.c ffs.c fls.c \
memccpy.c memchr.c memcmp.c memcpy.c memmove.c memset.c \
- qdivrem.c strcat.c strchr.c strcmp.c strcpy.c \
+ qdivrem.c strcat.c strchr.c strcmp.c strcpy.c stpcpy.c stpncpy.c \
strcspn.c strlcat.c strlcpy.c strlen.c strncat.c strncmp.c strncpy.c \
strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
.if ${MACHINE_CPUARCH} == "arm"
Index: lib/libstand/stand.h
===================================================================
--- lib/libstand/stand.h
+++ lib/libstand/stand.h
@@ -166,9 +166,10 @@
#define DEVT_NONE 0
#define DEVT_DISK 1
#define DEVT_NET 2
-#define DEVT_CD 3
+#define DEVT_CD 3
#define DEVT_ZFS 4
#define DEVT_FD 5
+#define DEVT_EFI 6
int d_unit;
void *d_opendata;
};
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
-};
Index: sys/boot/efi/include/efi_driver_utils.h
===================================================================
--- /dev/null
+++ sys/boot/efi/include/efi_driver_utils.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2017 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 _EFI_DRIVER_UTILS_H_
+#define _EFI_DRIVER_UTILS_H_
+
+#include <efi.h>
+#include <efiprot.h>
+
+extern EFI_STATUS install_driver(EFI_DRIVER_BINDING *driver);
+extern EFI_STATUS connect_controllers(EFI_GUID *filter);
+
+#endif
Index: sys/boot/efi/include/efi_drivers.h
===================================================================
--- /dev/null
+++ sys/boot/efi/include/efi_drivers.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2016 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 _EFI_DRIVERS_H_
+#define _EFI_DRIVERS_H_
+
+#include <bootstrap.h>
+
+typedef struct efi_driver_t {
+ const char *name;
+ void (*init)(void);
+} efi_driver_t;
+
+extern struct devsw efipart_dev;
+extern int efipart_getdesc(struct devdesc *dev, char **out);
+
+/* EFI drivers. */
+extern const efi_driver_t fs_driver;
+
+#endif
Index: sys/boot/efi/include/efilib.h
===================================================================
--- sys/boot/efi/include/efilib.h
+++ sys/boot/efi/include/efilib.h
@@ -64,6 +64,11 @@
void *efi_get_table(EFI_GUID *tbl);
+int efi_getdev(void **vdev, const char *devspec, const char **path);
+char *efi_fmtdev(void *vdev);
+int efi_setcurrdev(struct env_var *ev, int flags, const void *value);
+
+
int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
EFI_HANDLE efi_find_handle(struct devsw *, int);
int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *, uint64_t *);
@@ -79,6 +84,7 @@
void efi_free_devpath_name(CHAR16 *);
int efi_status_to_errno(EFI_STATUS);
+EFI_STATUS errno_to_efi_status(int errno);
void efi_time_init(void);
void efi_time_fini(void);
Index: sys/boot/efi/include/efiprot.h
===================================================================
--- sys/boot/efi/include/efiprot.h
+++ sys/boot/efi/include/efiprot.h
@@ -27,6 +27,8 @@
--*/
+#include <efidef.h>
+
//
// Device Path protocol
//
@@ -555,4 +557,80 @@
CHAR8 *SupportedLanguages;
} EFI_UNICODE_COLLATION_INTERFACE;
+//
+// Driver Binding protocol
+//
+
+#define DRIVER_BINDING_PROTOCOL \
+ { 0x18a031ab, 0xb443, 0x4d1a, {0xa5, 0xc0, 0x0c, 0x09, 0x26, 0x1e, 0x9f, 0x71} }
+
+INTERFACE_DECL(_EFI_DRIVER_BINDING);
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DRIVER_BINDING_SUPPORTED) (
+ IN struct _EFI_DRIVER_BINDING *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH *RemainingPath
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DRIVER_BINDING_START) (
+ IN struct _EFI_DRIVER_BINDING *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH *RemainingPath
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DRIVER_BINDING_STOP) (
+ IN struct _EFI_DRIVER_BINDING *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+typedef struct _EFI_DRIVER_BINDING {
+ EFI_DRIVER_BINDING_SUPPORTED Supported;
+ EFI_DRIVER_BINDING_START Start;
+ EFI_DRIVER_BINDING_STOP Stop;
+ UINT32 Version;
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE DriverBindingHandle;
+} EFI_DRIVER_BINDING;
+
+//
+// Component Name Protocol 2
+//
+
+#define COMPONENT_NAME2_PROTOCOL \
+ { 0x6a7a5cff, 0xe8d9, 0x4f70, {0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14 } }
+
+INTERFACE_DECL(_EFI_COMPONENT_NAME2);
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_COMPONENT_NAME_GET_DRIVER_NAME) (
+ IN struct _EFI_COMPONENT_NAME2 *This,
+ IN CHAR8 * Language,
+ OUT CHAR16 **DriverName
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) (
+ IN struct _EFI_COMPONENT_NAME2 *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+typedef struct _EFI_COMPONENT_NAME2 {
+ EFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName;
+ EFI_COMPONENT_NAME_GET_CONTROLLER_NAME GetControllerName;
+ CHAR8 **SupportedLanguages;
+} EFI_COMPONENT_NAME2;
+
#endif
Index: sys/boot/efi/include/efizfs.h
===================================================================
--- /dev/null
+++ sys/boot/efi/include/efizfs.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2016 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 <stdint.h>
+
+#ifndef _EFIZFS_H_
+#define _EFIZFS_H_
+
+#ifdef EFI_ZFS_BOOT
+typedef STAILQ_HEAD(zfsinfo_list, zfsinfo) zfsinfo_list_t;
+
+typedef struct zfsinfo
+{
+ STAILQ_ENTRY(zfsinfo) zi_link;
+ EFI_HANDLE zi_handle;
+ uint64_t zi_pool_guid;
+} zfsinfo_t;
+
+extern uint64_t pool_guid;
+
+extern void efi_zfs_probe(void);
+extern zfsinfo_list_t *efizfs_get_zfsinfo_list(void);
+
+#endif
+
+#endif
Index: sys/boot/efi/libefi/Makefile
===================================================================
--- sys/boot/efi/libefi/Makefile
+++ sys/boot/efi/libefi/Makefile
@@ -12,7 +12,7 @@
WARNS?= 2
SRCS= delay.c devpath.c efi_console.c efinet.c efipart.c env.c errno.c \
- handles.c wchar.c libefi.c
+ handles.c wchar.c libefi.c efizfs.c devicename.c
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
SRCS+= time.c
@@ -38,6 +38,12 @@
CFLAGS+= -I${.CURDIR}/../include
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand
+.if ${MK_ZFS} != "no"
+CFLAGS+= -I${.CURDIR}/../../zfs
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
+CFLAGS+= -I${.CURDIR}/../../../crypto/skein
+CFLAGS+= -DEFI_ZFS_BOOT
+.endif
# Pick up the bootstrap header for some interface items
CFLAGS+= -I${.CURDIR}/../../common
Index: sys/boot/efi/libefi/devicename.c
===================================================================
--- sys/boot/efi/libefi/devicename.c
+++ sys/boot/efi/libefi/devicename.c
@@ -41,8 +41,6 @@
#include <efi.h>
#include <efilib.h>
-#include "loader_efi.h"
-
static int efi_parsedev(struct devdesc **, const char *, const char **);
/*
Index: sys/boot/efi/libefi/efi_driver_utils.c
===================================================================
--- /dev/null
+++ sys/boot/efi/libefi/efi_driver_utils.c
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 2017 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 <stdbool.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "efi_driver_utils.h"
+
+static EFI_GUID DriverBindingProtocolGUID = DRIVER_BINDING_PROTOCOL;
+
+EFI_STATUS
+connect_controllers(EFI_GUID *filter)
+{
+ EFI_STATUS status;
+ EFI_HANDLE *handles;
+ UINTN nhandles, i, hsize;
+
+ nhandles = 0;
+ hsize = 0;
+ status = BS->LocateHandle(ByProtocol, filter, NULL,
+ &hsize, NULL);
+
+ if(status != EFI_BUFFER_TOO_SMALL) {
+ return (status);
+ }
+
+ handles = malloc(hsize);
+ nhandles = hsize / sizeof(EFI_HANDLE);
+
+ status = BS->LocateHandle(ByProtocol, filter, NULL,
+ &hsize, handles);
+
+ if(EFI_ERROR(status)) {
+ return (status);
+ }
+
+ for(i = 0; i < nhandles; i++) {
+ BS->ConnectController(handles[i], NULL, NULL, true);
+ }
+
+ free(handles);
+
+ return (status);
+}
+
+EFI_STATUS
+install_driver(EFI_DRIVER_BINDING *driver)
+{
+ EFI_STATUS status;
+
+ driver->ImageHandle = IH;
+ driver->DriverBindingHandle = NULL;
+ status = BS->InstallMultipleProtocolInterfaces(
+ &(driver->DriverBindingHandle),
+ &DriverBindingProtocolGUID, driver,
+ NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Failed to install driver (%ld)!\n",
+ EFI_ERROR_CODE(status));
+ }
+
+ return (status);
+}
Index: sys/boot/efi/libefi/efizfs.c
===================================================================
--- /dev/null
+++ sys/boot/efi/libefi/efizfs.c
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2008-2010 Rui Paulo
+ * Copyright (c) 2006 Marcel Moolenaar
+ * 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 ``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 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.
+ */
+
+#include <sys/param.h>
+#include <sys/disk.h>
+#include <stdint.h>
+
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "efizfs.h"
+
+#ifdef EFI_ZFS_BOOT
+static zfsinfo_list_t zfsinfo;
+
+uint64_t pool_guid;
+
+zfsinfo_list_t *
+efizfs_get_zfsinfo_list(void)
+{
+ return (&zfsinfo);
+}
+
+static void
+insert_zfs(EFI_HANDLE handle, uint64_t guid)
+{
+ zfsinfo_t *zi;
+
+ zi = malloc(sizeof(zfsinfo_t));
+ zi->zi_handle = handle;
+ zi->zi_pool_guid = guid;
+ STAILQ_INSERT_TAIL(&zfsinfo, zi, zi_link);
+}
+
+void
+efi_zfs_probe(void)
+{
+ pdinfo_list_t *hdi;
+ pdinfo_t *hd, *pd = NULL;
+ EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
+ EFI_LOADED_IMAGE *img;
+ char devname[SPECNAMELEN + 1];
+ uint64_t guid;
+
+ BS->HandleProtocol(IH, &imgid, (VOID**)&img);
+ hdi = efiblk_get_pdinfo_list(&efipart_hddev);
+ STAILQ_INIT(&zfsinfo);
+
+ /*
+ * Find the handle for the boot device. The boot1 did find the
+ * device with loader binary, now we need to search for the
+ * same device and if it is part of the zfs pool, we record the
+ * pool GUID for currdev setup.
+ */
+ STAILQ_FOREACH(hd, hdi, pd_link) {
+ STAILQ_FOREACH(pd, &hd->pd_part, pd_link) {
+
+ snprintf(devname, sizeof(devname), "%s%dp%d:",
+ efipart_hddev.dv_name, hd->pd_unit, pd->pd_unit);
+
+ if (zfs_probe_dev(devname, &guid) == 0) {
+ insert_zfs(pd->pd_handle, guid);
+
+ if (pd->pd_handle == img->DeviceHandle)
+ pool_guid = guid;
+ }
+
+ }
+ }
+}
+
+uint64_t
+ldi_get_size(void *priv)
+{
+ int fd = (uintptr_t) priv;
+ uint64_t size;
+
+ ioctl(fd, DIOCGMEDIASIZE, &size);
+ return (size);
+}
+#endif
Index: sys/boot/efi/libefi/errno.c
===================================================================
--- sys/boot/efi/libefi/errno.c
+++ sys/boot/efi/libefi/errno.c
@@ -30,6 +30,69 @@
#include <efi.h>
#include <efilib.h>
+EFI_STATUS
+errno_to_efi_status(int errno)
+{
+ EFI_STATUS status;
+
+ switch (errno) {
+ case EPERM:
+ status = EFI_ACCESS_DENIED;
+ break;
+
+ case EOVERFLOW:
+ status = EFI_BUFFER_TOO_SMALL;
+ break;
+
+ case EIO:
+ status = EFI_DEVICE_ERROR;
+ break;
+
+ case EINVAL:
+ status = EFI_INVALID_PARAMETER;
+ break;
+
+ case ESTALE:
+ status = EFI_MEDIA_CHANGED;
+ break;
+
+ case ENXIO:
+ status = EFI_NO_MEDIA;
+ break;
+
+ case ENOENT:
+ status = EFI_NOT_FOUND;
+ break;
+
+ case ENOMEM:
+ status = EFI_OUT_OF_RESOURCES;
+ break;
+
+ case ENOTSUP:
+ case ENODEV:
+ status = EFI_UNSUPPORTED;
+ break;
+
+ case ENOSPC:
+ status = EFI_VOLUME_FULL;
+ break;
+
+ case EACCES:
+ status = EFI_WRITE_PROTECTED;
+ break;
+
+ case 0:
+ status = EFI_SUCCESS;
+ break;
+
+ default:
+ status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ return (status);
+}
+
int
efi_status_to_errno(EFI_STATUS status)
{
Index: sys/boot/efi/libefi/time.c
===================================================================
--- sys/boot/efi/libefi/time.c
+++ sys/boot/efi/libefi/time.c
@@ -58,6 +58,41 @@
#define SECSPERHOUR ( 60*60 )
#define SECSPERDAY (24 * SECSPERHOUR)
+/*
+// These arrays give the cumulative number of days up to the first of the
+// month number used as the index (1 -> 12) for regular and leap years.
+// The value at index 13 is for the whole year.
+*/
+static const time_t CumulativeDays[2][14] = {
+ {0,
+ 0,
+ 31,
+ 31 + 28,
+ 31 + 28 + 31,
+ 31 + 28 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
+ {0,
+ 0,
+ 31,
+ 31 + 29,
+ 31 + 29 + 31,
+ 31 + 29 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
+
void
efi_time_init(void)
{
@@ -68,45 +103,46 @@
{
}
-static time_t
-efi_time(EFI_TIME *ETime)
+void
+to_efi_time(EFI_TIME *efi_time, time_t time)
{
- /*
- // These arrays give the cumulative number of days up to the first of the
- // month number used as the index (1 -> 12) for regular and leap years.
- // The value at index 13 is for the whole year.
- */
- static time_t CumulativeDays[2][14] = {
- {0,
- 0,
- 31,
- 31 + 28,
- 31 + 28 + 31,
- 31 + 28 + 31 + 30,
- 31 + 28 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
- {0,
- 0,
- 31,
- 31 + 29,
- 31 + 29 + 31,
- 31 + 29 + 31 + 30,
- 31 + 29 + 31 + 30 + 31,
- 31 + 29 + 31 + 30 + 31 + 30,
- 31 + 29 + 31 + 30 + 31 + 30 + 31,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
-
- time_t UTime;
+ if (time >= 0) {
+ for (efi_time->Year = 1970;
+ time > CumulativeDays[isleap(efi_time->Year)][13] * SECSPERDAY;
+ time -= CumulativeDays[isleap(efi_time->Year)][13] * SECSPERDAY,
+ efi_time->Year++);
+
+ for (efi_time->Month = 0;
+ time > CumulativeDays[isleap(efi_time->Year)][efi_time->Month] *
+ SECSPERDAY;
+ efi_time->Month++);
+
+ time -= CumulativeDays[isleap(efi_time->Year)][efi_time->Month - 1] *
+ SECSPERDAY;
+
+ for (efi_time->Day = 0; time > SECSPERDAY;
+ time -= SECSPERDAY, efi_time->Day++);
+
+ for (efi_time->Hour = 0; time > SECSPERHOUR;
+ time -= SECSPERHOUR, efi_time->Hour++);
+
+ for (efi_time->Minute = 0; time > 60;
+ time -= 60, efi_time->Minute++);
+
+ efi_time->Second = time;
+ efi_time->Nanosecond = 0;
+ efi_time->TimeZone = 0;
+ efi_time->Daylight = 0;
+ } else {
+ memset(efi_time, 0, sizeof(EFI_TIME));
+ }
+}
+
+time_t
+from_efi_time(EFI_TIME *ETime)
+{
+
+ time_t UTime;
int Year;
/*
@@ -196,7 +232,7 @@
// Convert to UNIX time (ie seconds since the epoch
*/
- tp->tv_sec = efi_time( &EfiTime );
+ tp->tv_sec = from_efi_time( &EfiTime );
tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */
/*
Index: sys/boot/efi/loader/Makefile
===================================================================
--- sys/boot/efi/loader/Makefile
+++ sys/boot/efi/loader/Makefile
@@ -16,7 +16,6 @@
bootinfo.c \
conf.c \
copy.c \
- devicename.c \
main.c \
self_reloc.c \
smbios.c \
Index: sys/boot/efi/loader/loader_efi.h
===================================================================
--- sys/boot/efi/loader/loader_efi.h
+++ sys/boot/efi/loader/loader_efi.h
@@ -35,10 +35,6 @@
int efi_autoload(void);
-int efi_getdev(void **vdev, const char *devspec, const char **path);
-char *efi_fmtdev(void *vdev);
-int efi_setcurrdev(struct env_var *ev, int flags, const void *value);
-
int efi_copy_init(void);
ssize_t efi_copyin(const void *src, vm_offset_t dest, const size_t len);
Index: sys/boot/efi/loader/main.c
===================================================================
--- sys/boot/efi/loader/main.c
+++ sys/boot/efi/loader/main.c
@@ -48,6 +48,8 @@
#ifdef EFI_ZFS_BOOT
#include <libzfs.h>
+
+#include "efizfs.h"
#endif
#include "loader_efi.h"
@@ -70,11 +72,6 @@
EFI_GUID fdtdtb = FDT_TABLE_GUID;
EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
-#ifdef EFI_ZFS_BOOT
-static void efi_zfs_probe(void);
-static uint64_t pool_guid;
-#endif
-
static int
has_keyboard(void)
{
@@ -83,7 +80,7 @@
EFI_HANDLE *hin, *hin_end, *walker;
UINTN sz;
int retval = 0;
-
+
/*
* Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and
* do the typical dance to get the right sized buffer.
@@ -140,7 +137,7 @@
} else if (DevicePathType(path) == MESSAGING_DEVICE_PATH &&
DevicePathSubType(path) == MSG_USB_CLASS_DP) {
USB_CLASS_DEVICE_PATH *usb;
-
+
usb = (USB_CLASS_DEVICE_PATH *)(void *)path;
if (usb->DeviceClass == 3 && /* HID */
usb->DeviceSubClass == 1 && /* Boot devices */
@@ -892,46 +889,3 @@
}
COMMAND_SET(chain, "chain", "chain load file", command_chain);
-
-#ifdef EFI_ZFS_BOOT
-static void
-efi_zfs_probe(void)
-{
- pdinfo_list_t *hdi;
- pdinfo_t *hd, *pd = NULL;
- EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
- EFI_LOADED_IMAGE *img;
- char devname[SPECNAMELEN + 1];
-
- BS->HandleProtocol(IH, &imgid, (VOID**)&img);
- hdi = efiblk_get_pdinfo_list(&efipart_hddev);
-
- /*
- * Find the handle for the boot device. The boot1 did find the
- * device with loader binary, now we need to search for the
- * same device and if it is part of the zfs pool, we record the
- * pool GUID for currdev setup.
- */
- STAILQ_FOREACH(hd, hdi, pd_link) {
- STAILQ_FOREACH(pd, &hd->pd_part, pd_link) {
-
- snprintf(devname, sizeof(devname), "%s%dp%d:",
- efipart_hddev.dv_name, hd->pd_unit, pd->pd_unit);
- if (pd->pd_handle == img->DeviceHandle)
- (void) zfs_probe_dev(devname, &pool_guid);
- else
- (void) zfs_probe_dev(devname, NULL);
- }
- }
-}
-
-uint64_t
-ldi_get_size(void *priv)
-{
- int fd = (uintptr_t) priv;
- uint64_t size;
-
- ioctl(fd, DIOCGMEDIASIZE, &size);
- return (size);
-}
-#endif
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 21, 7:28 PM (5 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25791970
Default Alt Text
D10447.id31486.diff (70 KB)
Attached To
Mode
D10447: Unify boot1 with loader
Attached
Detach File
Event Timeline
Log In to Comment