CFT EFI Boot Refactoring
Ben Woods
woodsb02 at gmail.com
Sat Dec 3 06:40:20 UTC 2016
Hi Eric,
Thanks for your work on this.
I just applied your diff to my subversion repository, and tried to
buildworld, but the build failed with the following error:
make[6]: make[6]: don't know how to make efipart.c. Stop
make[6]: stopped in /usr/src/sys/boot/efi/drivers
*** [all_subdir_sys/boot/efi/drivers] Error code 2
Does it build ok for you?
Because I use subversion, and I wanted to build it from my main tree, I had
to regenerate your patch using "git diff --no-prefix
master..origin/efize_new > /tmp/efize_new.diff".
I could then apply this cleanly with "svn patch /tmp/efize_new.diff".
I checked the difference between your diff and the diff I generated, and
the only differences were in the file headers. Therefore I don't think the
patch change should make any difference. I have attached my version of the
patch for reference.
For example:
diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile
index 0ebcaf1..3b608c5 100644
--- a/lib/libstand/Makefile
+++ b/lib/libstand/Makefile
Became:
diff --git lib/libstand/Makefile lib/libstand/Makefile
index 0ebcaf1ccfd..3b608c5bc92 100644
--- lib/libstand/Makefile
+++ lib/libstand/Makefile
To show the differences with your patch applied:
$ svn status
M lib/libstand/Makefile
M lib/libstand/stand.h
M sys/boot/efi/Makefile
M sys/boot/efi/boot1/Makefile
M sys/boot/efi/boot1/Makefile.fat
M sys/boot/efi/boot1/boot1.c
D sys/boot/efi/boot1/boot_module.h
M sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
M sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu
M sys/boot/efi/boot1/fat-arm64.tmpl.bz2.uu
M sys/boot/efi/boot1/fat-i386.tmpl.bz2.uu
M sys/boot/efi/boot1/generate-fat.sh
D sys/boot/efi/boot1/ufs_module.c
D sys/boot/efi/boot1/zfs_module.c
A sys/boot/efi/drivers
A sys/boot/efi/drivers/Makefile
A sys/boot/efi/drivers/efi_drivers.h
A sys/boot/efi/drivers/fs_driver.c
M sys/boot/efi/include/efilib.h
M sys/boot/efi/include/efiprot.h
A sys/boot/efi/include/string16.h
M sys/boot/efi/libefi/Makefile
A sys/boot/efi/libefi/efifs.c
M sys/boot/efi/libefi/efipart.c
M sys/boot/efi/libefi/errno.c
M sys/boot/efi/libefi/handles.c
A sys/boot/efi/libefi/string16.c
M sys/boot/efi/libefi/time.c
M sys/boot/efi/loader/Makefile
M sys/boot/efi/loader/conf.c
M sys/boot/efi/loader/loader_efi.h
M sys/boot/efi/loader/main.c
Regards,
Ben
--
From: Benjamin Woods
woodsb02 at gmail.com
On 3 December 2016 at 01:02, Eric McCorkle <eric at metricspace.net> wrote:
> Hello everyone,
>
> My work to refactor the EFI boot loader has been in review for some time
> now. This work is a behavior-neutral refactoring which eliminates
> duplicated code in boot1, provides better integration of boot1 and
> loader with the EFI API, and moves towards better compliance with the
> recommendations of the UEFI driver writer's guide. This work also
> serves as a precursor to more work, such as GELI, hot-plugging, and
> other things.
>
> One of the reviewers was able to trigger a hang on his setup; however,
> it's not clear whether this is a problem in the refactoring, or whether
> it's due to a related bug:
>
> https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=214423
>
> Therefore, I would like to issue a CFT for this changeset. We need
> people using the boot1/loader EFI boot setup to test their setup using
> boot1 and loader as built with this patch applied.
>
> You can also get the source tree directly from my github
> (https://github.com/emc2/freebsd.git). Use the efize_new branch to get
> this changeset. Note that I am maintaining the state of this branch in
> a single change at this point using rebase -i, so there *will* be forced
> pushes to this branch.
>
>
> Here are some notes on testing the changeset:
>
> * To test it, just do a buildworld, then copy loader.efi in place and
> copy boot1.efi to /efi/BOOT/BOOTX64.EFI on your ESP. If your system
> boots, then the test was successful (there are no new features in this
> changeset).
>
> * The output of boot1 is slightly different, so you'll be able to tell
> if you installed it correctly.
>
> * I recommend keeping a copy of the basic boot1 around on your ESP, just
> in case something goes wrong. On my setup, I have a backup at
> /efi/BOOT/BOOTX64.BAK (with the main program at /efi/BOOT/BOOTX64.EFI,
> of course)
>
> * I have been using this on a machine with two disks, a ZFS pool
> spanning both disks, and a dummy UFS filesystem for months now, so it
> can be considered relatively safe.
>
> * This has also been tested on basic setups without incident, so
> priority is on complex or odd setups.
>
> * If something goes wrong, you will most likely get a boot-hang. If
> this happens, please contact me directly with the details, and I'll
> coordinate on diagnosis.
>
-------------- next part --------------
diff --git lib/libstand/Makefile lib/libstand/Makefile
index 0ebcaf1ccfd..3b608c5bc92 100644
--- lib/libstand/Makefile
+++ lib/libstand/Makefile
@@ -41,7 +41,7 @@ SRCS+= ntoh.c
.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"
diff --git lib/libstand/stand.h lib/libstand/stand.h
index f77a586fb06..066aff05d65 100644
--- lib/libstand/stand.h
+++ lib/libstand/stand.h
@@ -24,7 +24,7 @@
* SUCH DAMAGE.
*
* $FreeBSD$
- * From $NetBSD: stand.h,v 1.22 1997/06/26 19:17:40 drochner Exp $
+ * From $NetBSD: stand.h,v 1.22 1997/06/26 19:17:40 drochner Exp $
*/
/*-
@@ -131,7 +131,7 @@ extern struct fs_ops pkgfs_fsops;
#define SEEK_CUR 1 /* set file offset to current plus offset */
#define SEEK_END 2 /* set file offset to EOF plus offset */
-/*
+/*
* Device switch
*/
struct devsw {
@@ -166,8 +166,9 @@ struct devdesc
#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_EFI 5
int d_unit;
void *d_opendata;
};
@@ -279,7 +280,7 @@ extern struct dirent *readdirfd(int);
extern void srandom(u_long seed);
extern u_long random(void);
-
+
/* imports from stdlib, locally modified */
extern long strtol(const char *, char **, int);
extern unsigned long strtoul(const char *, char **, int);
@@ -368,9 +369,9 @@ extern int null_stat(struct open_file *f, struct stat *sb);
extern int null_readdir(struct open_file *f, struct dirent *d);
-/*
- * Machine dependent functions and data, must be provided or stubbed by
- * the consumer
+/*
+ * Machine dependent functions and data, must be provided or stubbed by
+ * the consumer
*/
extern int getchar(void);
extern int ischar(void);
diff --git sys/boot/efi/Makefile sys/boot/efi/Makefile
index 66481f8513f..00490d0e943 100644
--- sys/boot/efi/Makefile
+++ sys/boot/efi/Makefile
@@ -15,7 +15,7 @@ SUBDIR+= fdt
.if ${MACHINE_CPUARCH} == "aarch64" || \
${MACHINE_CPUARCH} == "amd64" || \
${MACHINE_CPUARCH} == "arm"
-SUBDIR+= libefi loader boot1
+SUBDIR+= libefi drivers loader boot1
.endif
.endif # ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 40500
diff --git sys/boot/efi/boot1/Makefile sys/boot/efi/boot1/Makefile
index 110a8577491..7480c9c3eca 100644
--- sys/boot/efi/boot1/Makefile
+++ sys/boot/efi/boot1/Makefile
@@ -8,34 +8,50 @@ MK_SSP= no
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
CWARNFLAGS.skein.c += -Wno-missing-variable-declarations
.endif
+
# architecture-specific loader code
-SRCS= boot1.c self_reloc.c start.S ufs_module.c
+SRCS= boot1.c self_reloc.c start.S
.if ${MK_ZFS} != "no"
-SRCS+= zfs_module.c
+.PATH: ${.CURDIR}/../../../crypto/skein
SRCS+= skein.c skein_block.c
# Do not unroll skein loops, reduce code size
CFLAGS+= -DSKEIN_LOOP=111
-.PATH: ${.CURDIR}/../../../crypto/skein
+.PATH: ${.CURDIR}/../../zfs
+SRCS+= zfs.c
.endif
+# 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}
+CFLAGS+= -I${.CURDIR}/../drivers/
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
CFLAGS+= -DEFI_UFS_BOOT
@@ -56,6 +72,20 @@ CFLAGS+= -DEFI_ZFS_BOOT
.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
+
+.PATH: ${.CURDIR}/../drivers
+LIBEFI_DRIVERS= ${.OBJDIR}/../drivers/libefi_drivers.a
+
+
FILES= boot1.efi boot1.efifat
FILESMODE_boot1.efi= ${BINMODE}
@@ -75,8 +105,8 @@ LDFLAGS+= -Wl,-znocombreloc
# __aeabi_* (arm) or __divdi3 (i386).
# as well as required string and memory functions for all platforms.
#
-DPADD+= ${LIBSTAND}
-LDADD+= -lstand
+DPADD+= ${LIBEFI_DRIVERS} ${LIBEFI} ${LIBSTAND}
+LDADD+= ${LIBEFI_DRIVERS} ${LIBEFI} ${LIBSTAND}
DPADD+= ${LDSCRIPT}
@@ -102,7 +132,7 @@ boot1.efi: ${PROG}
SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} \
${OBJCOPY} -j .peheader -j .text -j .sdata -j .data \
-j .dynamic -j .dynsym -j .rel.dyn \
- -j .rela.dyn -j .reloc -j .eh_frame \
+ -j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
boot1.o: ${.CURDIR}/../../common/ufsread.c
@@ -111,7 +141,7 @@ boot1.o: ${.CURDIR}/../../common/ufsread.c
# created by generate-fat.sh
.include "${.CURDIR}/Makefile.fat"
-BOOT1_MAXSIZE?= 131072
+BOOT1_MAXSIZE?= 524288
boot1.efifat: boot1.efi
@set -- `ls -l boot1.efi`; \
diff --git sys/boot/efi/boot1/Makefile.fat sys/boot/efi/boot1/Makefile.fat
index c86a7c3f585..e2cda1ceb79 100644
--- sys/boot/efi/boot1/Makefile.fat
+++ sys/boot/efi/boot1/Makefile.fat
@@ -1,4 +1,4 @@
# This file autogenerated by generate-fat.sh - DO NOT EDIT
# $FreeBSD$
BOOT1_OFFSET=0x2d
-BOOT1_MAXSIZE=131072
+BOOT1_MAXSIZE=524288
diff --git sys/boot/efi/boot1/boot1.c sys/boot/efi/boot1/boot1.c
index 80b1895d4b2..9e02bfa3849 100644
--- sys/boot/efi/boot1/boot1.c
+++ sys/boot/efi/boot1/boot1.c
@@ -26,62 +26,118 @@ __FBSDID("$FreeBSD$");
#include <machine/elf.h>
#include <machine/stdarg.h>
#include <stand.h>
+#include <string16.h>
#include <efi.h>
+#include <efilib.h>
+#include <efiprot.h>
#include <eficonsctl.h>
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
+
+#include <bootstrap.h>
-#include "boot_module.h"
+#include "efi_drivers.h"
#include "paths.h"
-static const boot_module_t *boot_modules[] =
-{
-#ifdef EFI_ZFS_BOOT
- &zfs_module,
-#endif
-#ifdef EFI_UFS_BOOT
- &ufs_module
+#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[] = {
+ &fs_driver,
+ NULL
};
-#define NUM_BOOT_MODULES nitems(boot_modules)
-/* The initial number of handles used to query EFI for partitions. */
-#define NUM_HANDLES_INIT 24
+extern struct console efi_console;
+#if defined(__amd64__) || defined(__i386__)
+extern struct console comconsole;
+extern struct console nullconsole;
+#endif
-void putchar(int c);
-EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
+struct fs_ops *file_system[] = {
+ &dosfs_fsops,
+ &ufs_fsops,
+ &cd9660_fsops,
+ &nfs_fsops,
+ &gzipfs_fsops,
+ &bzipfs_fsops,
+ NULL
+};
-EFI_SYSTEM_TABLE *systab;
-EFI_BOOT_SERVICES *bs;
-static EFI_HANDLE *image;
+struct devsw *devsw[] = {
+ &efipart_dev,
+#ifdef EFI_ZFS_BOOT
+ &zfs_dev,
+#endif
+ 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 console *consoles[] = {
+ &efi_console,
+ NULL
+};
-/*
- * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
- * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
- * EFI methods.
+/* Definitions we don't actually need for boot, but we need to define
+ * to make the linker happy.
*/
-void *
-Malloc(size_t len, const char *file __unused, int line __unused)
+struct file_format *file_formats[] = { NULL };
+
+struct netif_driver *netif_drivers[] = { NULL };
+
+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 int efi_getdev(void **vdev __unused, const char *devspec __unused,
+ const char **path __unused)
+{
+ printf("******** Boot block should not call getdev\n");
+ return (-1);
+}
- return (NULL);
+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);
}
-void
-Free(void *buf, const char *file __unused, int line __unused)
+static ssize_t
+efi_copyout(vm_offset_t src __unused, void *dest __unused,
+ const size_t len __unused)
{
- if (buf != NULL)
- (void)bs->FreePool(buf);
+ printf("******** Boot block should not call copyout\n");
+ return (-1);
+}
+
+static ssize_t
+efi_readin(int fd __unused, vm_offset_t dest __unused,
+ const size_t len __unused)
+{
+ printf("******** Boot block should not call readin\n");
+ return (-1);
}
+/* The initial number of handles used to query EFI for partitions. */
+#define NUM_HANDLES_INIT 24
+
+static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
+static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
+static EFI_GUID SimpleFileSystemProtocolGUID = SIMPLE_FILE_SYSTEM_PROTOCOL;
+static EFI_GUID FileInfoGUID = EFI_FILE_INFO_ID;;
+
/*
* nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
* FALSE otherwise.
@@ -142,6 +198,7 @@ devpath_last(EFI_DEVICE_PATH *devpath)
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.
@@ -273,7 +330,7 @@ devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
* 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;
@@ -304,48 +361,207 @@ devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
* 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
+
+static EFI_STATUS
+efi_load(EFI_HANDLE dev, const char *filepath, void **bufp, size_t *bufsize)
+{
+ UINTN infosize = sizeof(EFI_FILE_INFO) +
+ ((strlen(filepath) + 1) * sizeof(CHAR16));
+ EFI_FILE_INFO *finfo;
+ EFI_STATUS status;
+ EFI_FILE_IO_INTERFACE *iface;
+ EFI_FILE_HANDLE root;
+ EFI_FILE_HANDLE target;
+ CHAR16 path16[strlen(filepath) + 1];
+ void *buf;
+
+ finfo = malloc(infosize);
+
+ if (finfo == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ status = BS->OpenProtocol(dev, &SimpleFileSystemProtocolGUID,
+ (void **)&iface, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (status != EFI_SUCCESS) {
+ free(finfo);
+ printf("Open protocol failed! %ld\n", EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ status = iface->OpenVolume(iface, &root);
+
+ if (status != EFI_SUCCESS) {
+ BS->CloseProtocol(dev, &SimpleFileSystemProtocolGUID, IH, NULL);
+ free(finfo);
+ printf("Open volume failed! %ld\n", EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ strcpy_to_16(path16, filepath);
+ status = root->Open(root, &target, path16, EFI_FILE_MODE_READ, 0);
+
+ if (status != EFI_SUCCESS) {
+ BS->CloseProtocol(dev, &SimpleFileSystemProtocolGUID, IH, NULL);
+ free(finfo);
+
+ return (status);
+ }
+
+ *bufsize = infosize;
+ status = target->GetInfo(target, &FileInfoGUID, bufsize, finfo);
+
+ if (status != EFI_SUCCESS) {
+ BS->CloseProtocol(dev, &SimpleFileSystemProtocolGUID, IH, NULL);
+ free(finfo);
+ printf("Get info failed! %ld\n", EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ *bufsize = finfo->FileSize;
+
+ if ((buf = malloc(finfo->FileSize)) == NULL) {
+ BS->CloseProtocol(dev, &SimpleFileSystemProtocolGUID, IH, NULL);
+ free(finfo);
+ printf("Failed to allocate load buffer %zd for '%s' "
+ "(%lu)\n", finfo->FileSize, filepath, EFI_ERROR_CODE(status));
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ *bufp = buf;
+ status = target->Read(target, bufsize, buf);
+ BS->CloseProtocol(dev, &SimpleFileSystemProtocolGUID, IH, NULL);
+ free(finfo);
+
+ if (status != EFI_SUCCESS) {
+ printf("Read failed! %ld\n", EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ return (EFI_SUCCESS);
}
/*
* 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.
+ * This tries all handles which support the EFI_SIMPLE_FILE_SYSTEM interface.
+ * It is expected that the drivers will have installed this interface on every
+ * handle representing a device containing a supported file system.
+ *
+ * Note: In the future, this may be altered to use the EFI_LOAD_FILE interface,
+ * which should work transparently with network booting.
*
* 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)
+load_loader(EFI_HANDLE *handlep, 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);
- }
+ EFI_DEVICE_PATH *imgpath;
+ EFI_DEVICE_PATH *devpath;
+ EFI_LOADED_IMAGE *boot_image;
+ EFI_HANDLE *boot_handle;
+ EFI_HANDLE *preferred;
+ EFI_HANDLE *handles;
+ EFI_STATUS status;
+ UINTN i, hsize, nhandles, npreferred;
+
+ 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));
+ }
+
+ boot_handle = boot_image->DeviceHandle;
+
+ if ((status = BS->OpenProtocol(boot_handle, &DevicePathGUID,
+ (void **)&imgpath, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL))) {
+ panic("Failed to get image DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ }
+ DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
+
+ /* Allocate space for the handles */
+ hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
+ if ((handles = malloc(hsize)) == NULL)
+ panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
+ EFI_ERROR_CODE(status));
+
+ status = BS->LocateHandle(ByProtocol, &SimpleFileSystemProtocolGUID, NULL,
+ &hsize, handles);
+
+ switch (status) {
+ case EFI_SUCCESS:
+ break;
+ case EFI_BUFFER_TOO_SMALL:
+ (void)BS->FreePool(handles);
+ if ((handles = malloc(hsize)) == NULL) {
+ panic("Failed to allocate %zu handles (%lu)", hsize /
+ sizeof(*handles), EFI_ERROR_CODE(status));
}
+ status = BS->LocateHandle(ByProtocol,
+ &SimpleFileSystemProtocolGUID, 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));
}
+ if ((preferred = malloc(hsize)) == NULL)
+ panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
+ EFI_ERROR_CODE(status));
+
+ npreferred = 0;
+ nhandles = hsize / sizeof(*handles);
+
+ /* Figure out which handles are preferred */
+ for (i = 0; i < nhandles; i++) {
+ if (BS->OpenProtocol(handles[i], &DevicePathGUID,
+ (void **)&devpath, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL) ==
+ EFI_SUCCESS) {
+ if (device_paths_match(imgpath, devpath)) {
+ preferred[npreferred] = handles[i];
+ npreferred++;
+ }
+ BS->CloseProtocol(handles[i], &DevicePathGUID, IH, NULL);
+ }
+ }
+
+ BS->CloseProtocol(boot_handle, &DevicePathGUID, IH, NULL);
+
+ /* Try the preferred handles first, then all the handles */
+ for (i = 0; i < npreferred; i++) {
+ if (efi_load(preferred[i], PATH_LOADER_EFI, bufp, bufsize) ==
+ EFI_SUCCESS) {
+ *handlep = preferred[i];
+ return (EFI_SUCCESS);
+ }
+ }
+
+ for (i = 0; i < nhandles; i++) {
+ if (efi_load(handles[i], PATH_LOADER_EFI, bufp, bufsize) ==
+ EFI_SUCCESS) {
+ *handlep = handles[i];
+ return (EFI_SUCCESS);
+ }
+ }
+
+ printf("Failed to load %s from any device!\n", PATH_LOADER_EFI);
+
return (EFI_NOT_FOUND);
}
@@ -359,20 +575,27 @@ try_boot(void)
size_t bufsize, loadersize, cmdsize;
void *buf, *loaderbuf;
char *cmd;
- dev_info_t *dev;
- const boot_module_t *mod;
+ EFI_HANDLE fshandle;
EFI_HANDLE loaderhandle;
EFI_LOADED_IMAGE *loaded_image;
EFI_STATUS status;
+ EFI_DEVICE_PATH *fspath;
+
+ status = load_loader(&fshandle, &loaderbuf, &loadersize);
- status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
- if (status != EFI_SUCCESS) {
- status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
- FALSE);
+ if (status != EFI_SUCCESS) {
+ return (status);
+ }
+
+ fspath = NULL;
+ if (status == EFI_SUCCESS) {
+ status = BS->OpenProtocol(fshandle, &DevicePathGUID,
+ (void **)&fspath, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (status != EFI_SUCCESS) {
- printf("Failed to load '%s'\n", PATH_LOADER_EFI);
- return (status);
- }
+ DPRINTF("Failed to get image DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ }
+ DPRINTF("filesystem device path: %s\n", devpath_str(fspath));
}
/*
@@ -387,9 +610,9 @@ try_boot(void)
*/
cmd = NULL;
cmdsize = 0;
- status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
+ status = efi_load(fshandle, PATH_DOTCONFIG, &buf, &bufsize);
if (status == EFI_NOT_FOUND)
- status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
+ status = efi_load(fshandle, PATH_CONFIG, &buf, &bufsize);
if (status == EFI_SUCCESS) {
cmdsize = bufsize + 1;
cmd = malloc(cmdsize);
@@ -401,24 +624,25 @@ try_boot(void)
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;
@@ -434,10 +658,10 @@ try_boot(void)
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;
}
@@ -453,134 +677,19 @@ errout:
return (status);
}
-/*
- * probe_handle determines if the passed handle represents a logical partition
- * if it does it uses each module in order to probe it and if successful it
- * returns EFI_SUCCESS.
- */
-static EFI_STATUS
-probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
-{
- dev_info_t *devinfo;
- EFI_BLOCK_IO *blkio;
- EFI_DEVICE_PATH *devpath;
- EFI_STATUS status;
- UINTN i;
-
- /* 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);
- }
-
- 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);
-
- /* 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);
- }
-
- return (EFI_UNSUPPORTED);
-}
-
-/*
- * probe_handle_status calls probe_handle and outputs the returned status
- * of the call.
- */
-static void
-probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
-{
- EFI_STATUS status;
- BOOLEAN preferred;
-
- 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)
+main(int argc __unused, CHAR16 *argv[] __unused)
{
- 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);
+ UINTN i, max_dim, best_mode, cols, rows;
+
+ cons_probe();
+
/*
* 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 +706,31 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
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');
-
- /* 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));
-
- 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));
- }
+ /*
+ * Initialise the block cache. Set the upper limit.
+ */
+ bcache_init(32768, 512);
- /* Scan all partitions, probing with all modules. */
- nhandles = hsize / sizeof(*handles);
- printf(" Probing %zu block devices...", nhandles);
- DPRINTF("\n");
+ printf("\n>> FreeBSD EFI boot block\n");
- /* 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));
- }
+ 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;
- for (i = 0; i < nhandles; i++)
- probe_handle_status(handles[i], imgpath);
- printf(" done\n");
+ printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
+ printf(" Initializing modules:");
- /* Status summary. */
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- printf(" ");
- boot_modules[i]->status();
+ for (i = 0; efi_drivers[i] != NULL; i++) {
+ printf(" %s", efi_drivers[i]->name);
+ if (efi_drivers[i]->init != NULL)
+ efi_drivers[i]->init();
}
+ 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);
-}
diff --git sys/boot/efi/boot1/boot_module.h sys/boot/efi/boot1/boot_module.h
deleted file mode 100644
index 296d5a67a10..00000000000
--- sys/boot/efi/boot1/boot_module.h
+++ /dev/null
@@ -1,117 +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)();
-
- /*
- * 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)();
-
- /* valid devices as found by probe. */
- dev_info_t *(*devices)();
-} 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 void panic(const char *fmt, ...) __dead2;
-extern int printf(const char *fmt, ...);
-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
diff --git sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
index a3ec32d1451..c7308a47985 100644
--- sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
+++ sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
@@ -2,25 +2,50 @@ FAT template boot filesystem created by generate-fat.sh
DO NOT EDIT
$FreeBSD$
begin 644 fat-amd64.tmpl.bz2
-M0EIH.3%!62936?$)3$,`&U9_____Z^KJZ_^N_^O^Z_^[ON_NK^JJ^KZNKNNJ
-MZNKNZOJ^P`+\#$!0$#1D-,@#)DT#1B&AIDQ,AD:#1HTR`-#)D80Q!D:,)D``
-M#1 at F30```&@`$JJ9!_HU4:",3!,F0&C(83`F30T`T!B&!,F`(P3`"#0,@`/2
-M::`#0!D`,C1`T9#3(`R9-`T8AH:9,3(9&@T:-,@#0R9&$,09&C"9```T8)DT
-M```!H``JBD at _2B:FF9)IHQ/1#:@-`:`R#(T`&@:-`!H8FAH:::'J::-`9&1Z
-MFF!'HAB8U/1/*8---3EV+*<ZL\S9BXEC[6I",BE$0BDA$1$%G66TH6PF$0(0
-MXDA!"&<HJ,=-W=K>PZ5:L^\19>>T2K3OA>TUS8M>VJ_;9P7"8;&7&8R51N>F
-M1E%A#6+F9*H@$(9J<K2V7=DH[YSK)LDN618]0S$3"M6JK5JU:M9J*5)44444
-M45JU%:5::U:M6K<:T42HHHHHHYI:J)44444,+B;R5>%%%%%%%$>!!!!!!!!!
-M!!!!!!!#76C@<C1HT:-&C1!!!!!!!!!TX&#!@P8,&#J8Y*BBBBBBBB'@<#!@
-MP8,&#"$4*******.?ZO)U59NW9Y_5RB9=SGK%AO91D/,RW:JUEWJ7CICT$M,
-M]]>OM;-N%^W[!<=H[<-1<QY)W<`%BRT<D`+3375[\FOS\YBD0`RSL8,UV51>
-MRR"SVLL>LG*Z1G+K%N;);>IIYL-7L*D<B5U+2/2:5J6K7K+ON7S<-ZW[`8;$
-M9ESS6Y>[Q-SH;5D;RU_+ZK.+TEMX%K(QQ813V:GS1ZT;"R\!H$K/Z:=%386M
-MPJL.<K?C*J6 at DI)\#6KU=, at V3:-JW3>.`X;BN0SS2,I;U*I;;.]O5ZMI9CMV
-MY(;8*\CXX-SPW(^Z5WIWPW0V@?7DLGZ at QJQHC6!J-\U[>@T$2F)3"7UM2V+:
-M+YMFW;MO6^<- at L)R7+<WLVJEO,&HNI+>XU0JB(L,KI:F[OD%ZUC=-0WB\7C?
-M."P'%83CL1BM$RLHD):&7,DOSLY1=2Y,H_EOG`<%YS0,!Q&$XS]')8CXEXP_
-MFX2-7*,#%P;!Q]V)E#BO"83#?\V3C..Y#E,1?L5S&,NC%DQI>;+`DS>NQL5?
-?+6IF915V$0"$)@`M+"Q)@(_9+!?^+N2*<*$AXA*8A@``
+M0EIH.3%!629363$"%&\`'YA______________^O^Z_^[_N[^J^NK^KZOKONJ
+MZNK^ZN[^X`C_%-``HH`%41"1(*)`BJ!H:```?M5```#0````````-`:-#0``
+M`````````````555$_2@!O_U2J/_TJA_JJ>4!H````T``````&@`````:```
+M!H``>H`&@!HR`0,F3(!DR``TP0T`:``#0Q#30#(``-`-`R&@&@!D!H&FC$&C
+M0``&@`#0 at 9,F0#)D`!I at AH`T``&AB&F@&0``:`:!D-`-`#(#0--&(-&@``-`
+M`&A`R9,@&3(`#3!#0!H``-#$--`,@``T`T#(:`:`&0&@::,0:-```:``-`55
+M(_23]"13-3TIZJ?[*D:$_]5-3TVBFU-J;1&3)A'H0\F2/4Q&GJ!ZF`3U#U'E
+M/031B8U#$9'J!ZAM(\*#R#0,4S4_5,U/0VJ>$\B*9O7.9HQ&K at F!RV88885S
+M,&#####&POFPP!@<W- at R&;#`PPP'JJLYET/0LJ/Q4O7O:*/<NO9^T?#=J^2_
+MP?TNZ?0=X\)X;Q7EM7G/.YW1L-K_B,,,,,,,`%@W4$\J!`.@(!`*@0"!#`("
+M`@("`@("`@("`@("Z!^`\PXGK&QR'F\,S<S-S<EN;E6Y.YN;FYN;FYN;FYN;
+MFYN;G`Y'/<B'(Y%'(Y'(Y'(Y'(Y%UUUUUUUUUUV.LQU,=FL9CLJQF5LU%@RS
+M4\;0JS*JJJJJN@:E6IF79EUUUUUW\7J[?\YL+KKKKKKI:56E&&=999999*4I
+M2E*4K*K.F[3,Q49,F3)DR2E*4I2E+)5DUT0NNNNNNX/2=K========+4JU.\
+MHA======QJLEF2&=======S/09M>?ILGJGM'9/CNX=\\1]7S2JJJJJJJ7IE7
+M7(9UEEEEEDI2E*4I2LJLAG6666662E*4I2E*RJR&=999999?K++++++++)9*
+MLD,ZRRRRRS*JJJJJJJJ5U5W@=3BHR9,F3)DY555555554M*K2AG6666662E*
+M4I2E*RJR&=999999*RJR&=999999M]ST6EDR8Z75L[4S8=BSC1D=PZ]J#RWA
+M*>XSS+OI9+,OP:!G,`[#(RG-'!93*8`$4]KF#`!H][S_R?Y_E]3FG`P`><?@
+MNJ;UF]O;V]O;V]O;V]O;V]O;V]O;V]SSV3B>;;6UBVMK0VMK:VMK:VMK:VMK
+M:VMK:VMK:Z^ZZZZZZZZZZZZZZZZZZZZZZZ[+MSB;FU1#B<MPN4TLDI2E*4I2
+MNJNAG6666663A*4I2E*5E5GGZ(777777=955555555+)5DAG6666662E*4I2
+ME*RJR&=999999\BJJJJJJJJ5U5W1.57,Z%+0TM+2EI:4M*K2AG6666662[!V
+MCX[MW>/J/_7C^C55555552ZG]E9V3I_)YDL6IJ:FIJ:DI2E*4I2TJM+G^S^#
+MFT,6EI:6EI:4I2E*4I2TJM+^;^[%1DR9,F3)*4I2E*4LE62&=999999*4I2E
+M*4K*K(9UEEEEEDI2E*4I2LJL^[1"ZZZZZZ4I2E*4I7570SK+++++/R*KK+H9
+MUUUUUUUE55G3M,9UIK<&G/7:>^5EGWHT*,&#!$1$1$<#@<#@=(_=<MT;HN@=
+MMQN-QN-QN-QN-QN-QN-QN-QLPS6P_W[?"V6666666666666669#(9#(9;==2
+M\CT]5554?T&9111]'`7S#H#0T-#0A"$(0A#+][%BQ8NGP]UA\R?SW:OXWQ6M
+M11117Y?*YF7S+[&>',TM+2TO\J***,:***(0A"$(0O1C,9C,3$Q,3,,'G/3>
+MP]YDOJ9]^;^6Z(B(B(B(B(B(Y=WCP6;9%EEEEEEEEEEEEEEEFEQ$1$:0B(B(
+MB(LLLXG%111WF+U'JX['EU555=UW6+%BQ<_U&K0T-#0M1111^K^EBQ8L7*Z'
+MJNBLU,.M?M.S=NIP]AGY<I2EV>SL.W_;U+ZLF3)DA"$.D]GIK*4I0A"'*HHH
+MHA"$(0A#_-W+NW>N^>`^L^RYKQ7CORG#PN%PN%PL&#!@P8,&#!@P>,\UY3/*
+M4I2E*4I2E*4I2(B(B(B(B(B*4IL=_XF+%BQ0A"$(0A"$(0A"'F>UQ8L6+O>X
+M=L_D=VA"$(0A#]BBBBB$(0A"$(0A#F^%\(9\,,-#0T-"$(0^$^>Z5TKZSPV?
+M?D_1H&B?XB(B(B(B(B(CC6=?"R5*4I2E*4I2E*;/99 at P8,&#!@X7"X7"X7"X
+M7`X'$XG$XD(0A"$(0A"'6T444>51111"$(?]._?2?30A"'K****/-!1111"$
+M(;J***/O44440A"$(0A]=X3JWV'-?;>,[I]YSGQ'H'B]MK:VMK:VMK:VMK:V
+MMK:VMK>"\-]ET[8V-C8V-C8V-C8V-C8V*4B(B(B(B(B(BE*4Q,3$A\&BBBB$
+M(0A"$/^_(_3T-#0T(0A#[G?O$>Q<U"$(0A"$(0A2BBBB$(0A"$(0A"$(0^T^
+MV[UXS[C[KQW.?/>0\EY;@<#@1$1$1$1$1F6A=*T2E*4I2E*4I2E*4B(B(B(B
+M(B(BFQL;'@T4440A"'E4444>BHHHH\.BBBB$(0ZCKO*YSG.<YR$(0[ET>+%B
+MQ=;11113L;YQY+#P?@66666KA at 888#-AA@`>5H:&AH:****(?:4440>6S/_G
++WQ=R13A0D#$"%&\`
`
end
diff --git sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu
index 23e063ee23d..ee2ee9954f5 100644
--- sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu
+++ sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu
@@ -2,25 +2,50 @@ FAT template boot filesystem created by generate-fat.sh
DO NOT EDIT
$FreeBSD$
begin 644 fat-arm.tmpl.bz2
-M0EIH.3%!62936>#67)H`&U9_____Z^KJZ_ZN_^O^J_^[OJ[NK^JJ^KZNKNNJ
-MZNKNZOJ^P`+\```"``:`T::-`:8 at P@&1D-!H:808)B:#0`T``,$T#!, at PC09
-M#33"9,0`T(`!H#1IHT!IB#"`9&0T&AIA!@F)H-`#0``P30,$R#"-!D--,)DQ
-M`#0@`&@-&FC0&F(,(!D9#0:&F$&"8F at T`-``#!-`P3(,(T&0TTPF3$`-`522
-M$_(H2-DT0T:8C(T!H!ZC30R-&@-`,@&C1H:`:#1M3(T,@:::/1#331FII@)@
-M)Z:)RK5N6<7,O<%[)S4ZD(ODD1"*2"(B(+E99)"P2A$"$.#(((0Z^BHO)97*
-MKNTS2;//!6_,:)5IVI>LPGUM8_)MV&_QO'$<Q>Y;`J/TETR.=50:\2B`0AF9
-M<_.ME;:;0N<9%D%\Q['*&6B4*U:JM6K5JUQ12I)1111116K45I*TJU:M6K<:
-MZ424444448Y-1)111111[F<_6R+%BQ8L6+$X3333333333333333=7Z\E2M6
-MK5JU:M--------->R44444447N#[%BQ8L6+%BQ-M)*******,!0HHHHHHHY[
-M-RR5757;.MS?HE)GL[:M-Q)&/TG09Q6MZ%)XJ4><D]5[S5M>^]M6W8C at ..T=
-MV&HOX\@T$`%JWHY$`-/ZV!A?)K>YEEZ1`#*,&#,]G484F/7/RDR%Y<?]FG8X
-M&-?VUWJ*AR)+Z32//:9[#4M6R;8-FVK<,1OG$8K*LE&JR>4Q?U[J:^S$]EPK
-MD81)^D"<A>%H^>2OU:FLC31KK??,_$ES74S%+)U7JU5D:VQD)R-2U3"7[FWW
-M-DPVV;ANV^9-R&"T;G,A>6EJ3:=EVE6ENKC#PZG.]=9:75*G=>-4N\OA]'=-
-M`L[RN\MM/>Z'8:6Q.RAWU+=HOHDCZ6H?8_!^+:-JVS^6Z;UP'#<ERG-[$W'`
-MJ+^19>>T*HB+3GM+4VVS(NQ)&K?`_9IW\,PS#$;QOG"<-QV*QFB8^2)!)H).
-M7(_ at P9(R$G)DC<L1NV\;UGV_<)Q'&?FY+%?$Z1Q?DWR/?DC at 8W"M'(_<RTBJ
-M2'#=^XK8.,U[CN0Q'_,5MV,Y;F,`QI',DW7EU-_(S>MYF,_-.IT<D58,0"$)
-60`75I:D;]&V2<%_XNY(IPH2'!K+DT```
+M0EIH.3%!629363'ZIQP`'Z#______________^O^J_^[OJ[^J^JK^KZNKONZ
+MZNK^ZN[^X`C_```:*`!()"1(2)!!H&@&09!H&@:,3(T#0`8@`T#"&C0-````
+M-`9&C0````#1D9,F)H!DT8%552:!D9/_]453_]53_54_]53]4``-````````
+M``&@````!H```&@`T:``T!H:`0:!H!D&0:!H&C$R-`T`&(`-`PAHT#0```#0
+M&1HT`````T9&3)B:`9-&(-`T`R#(-`T#1B9&@:`#$`&@80T:!H```!H#(T:`
+M````:,C)DQ-`,FC$&@:`9!D&@:!HQ,C0-`!B`#0,(:-`T````T!D:-`````-
+M&1DR8F@&31 at 55(_2/0E-&HVE-XJ9ZJ3:G_JDC90]3(:&C0:-/4]0/4>H]0;4
+M`#0-&@VIZFFF:FC0:>IHVH>H!IHWHIH>2::#U/4]3#4]&3:FD[$4T=T[;+$:
+MN:8'3:!AAA70P8,,,,,;"^A@#`N-'Q-`PPPP'K:M)GVO:LZ/HDN[1WS1^6_`
+M:?U'@N_>Z>(\)[YX[_!_T\EYCYC5@>EXZ7BZ.V8;VEA at PPP'IM'5[.SK*.LZ
+MRKK.L[UP<'!P<'!P<'!P<'!P<'!U'9MCN7.VGI<-#>T-[>EO;U6].]O;V]O;
+MV]O;V]O;V]O;W,VNC:AM;5&UM;6UM;6UM;6UM;6UM;6UM;6UO;&]SM[M*-[0
+MHT;'3:W*U/-R5:%555557!J5:FA?#0NNNNNN]K]=XU\+KKKKKKI<BKD1AI66
+M66662E*4I2E*RJSN._T,5&;-FS9LTI2E*4I2S59NE1"ZZZZZ[F]7X%UUUUUU
+MUTM2K4]_1"ZZZZZ[LE6:S-#2NNNNNN[;U&CI:>XS>M??OTGN7]#X#RWP_2*J
+MJJJJJI>L5=ZAI6666662E*4I2E*RJS5R#PV';_R52Y7*Y7*Y7*E*4I2E*7*J
+MY4-*RRRRRSFJJJJJJJJE=5=WE$+KKKKKLZJJJJJJJI9JLWP:(777777=UTK+
+M++++++)<BKD0TK+++++)2E*4I2E959#2LLLLLLE959#2LLLLLLZOYW;<C-FQ
+MS#B659EI&4ZEG&51WCM&+S'BJ>X]59]#/KOP:)G,`]MV>'L#N\,,`"*?E:`P
+M`>T]KU?=^%[SNM$X&`#M'S;[=Q6<7%Q<7%Q<7%Q<7%Q<7%Q<7%Q<70[YL?--
+MS<Q;FYDW-S<W-S<W-S<W-S<W,C(R,C(NNNNNNNNNNNNNNNNNNNNZCJ.HZCH;
+MFQN;E$-CIM;E<C-*4I2E*4KJKH:5EEEEEDX2E*4I2E959ZBB%UUUUUW>5555
+M55552S59H:5EEEEEDI2E*4I2LJLAI666666>[JJJJJJJJE=5=Z9RUT/G>TJE
+MJ:FI5J:DM2K4AI6666662]@]H_??S/?OA/BO/^H55555552[K\A9W[U/R^WE
+MBU-34U-34E*4I2E*7(JY'5]QBHS9LV;-FE*4I2E*6:K-#2LLLLLLE*4I2E*5
+ME5D-*RRRRRR4I2E*4I6560TK+++++)2E*4I2E959\FB%UUUUUTI2E*4I2NJN
+MAI666666?3U7670TKKKKKKK,LRS+NK:<SK3VWLPSS,M`U!]Z/Y1 at P8(B(B(B
+M(B,VZAJ+86J93.V666666666666=#H=#AZ?L=SW>QL;&QL;&QL;&QL;&QL;&
+MQO;V]O<OK-W8[ZJJJJ/"-"BBCR,!?0.!DR9,D(0A[RBBBCD_1Q8L6+N,/S,/
+M#G[IX#P7[CN<*****^'R]OGKOIYT:>WY'(Y'(_LHHHHA"$(0A"$(0O1111"$
+M(=DUOZGO77?Y/@O^7E/C/.?4N9S.9$1$1$1$1'-N^>(\EJM[++++++++++++
+M+++,O$1$1IB(B(B(CH=#H=#HHHH\7%]5];'LNG5555U^OBQ8L75]5JR9,F2V
+M>+%BQ?@^OQ8L6+E[7[/YRS[AX3]5XC7^+S=.4I2\#G_&\3V6I?5FS9LT(0A]
+M]G.3)DR0A"&VBBBB$(0A"$/>O?/%>,_T?ZO]WE/_7F//>N:];6UM;!@P8,&#
+M!@P8,&#RG7/-9Y2E*4I2E*4I2E*1$1$1$1$1$12G.YWD>7BQ8L4(0A"$(0A"
+M$(0AV3#J^!DR9,F3X'];W3P7C(0A"$(0A"$/PJ***(0A"$(0Y^CVXTX889,F
+M3)"$(>W>.S;-OG?4^UH7Y-$T;_$1$1$1$1$1$<>]YGV at 4I2E*4I2E*4IDS3-
+M,&#!@UM;6UM;6UM;6UN9S-C8V-B$(0A"$(0A#[:BBBCT:***(0A#_-X[X3X:
+M$(0]=1111"$(>D"BBBC?\C%BQ8O.HHHHA"$(0A#R7_;[5_X^*^.\U[%YSY3W
+M#U+_[W/2=)TG2=)BQ8L6+%BQ8L6+['W-"VQ2E*4I2E*4I2E*1$1$1$1$1$12
+ME.="$(>VHHHHA"$.%%%%'E]CU^3)DR0A"'7\A\1WKXR$(0A"$(0A"E%%%$(0
+MA"$(0A"$(0AUWF/Z7FOD/DO/?*>.[#Y;_D1$1$1$1$1$7:-T[^E*4I2E*4I2
+ME*4I$1$1$1$1',YG,YW.YW.\FBBBB$(0]&BBBCK4444>51111"$(>J^[]'T'
+MH/0>@A"$/[GI\6+%B[RBBBBGL<6+%BICA at 888#1AA@`>CDR9,F5%%%$/CJ**
+1(/F-#S7_XNY(IPH2!C]4XX``
`
end
diff --git sys/boot/efi/boot1/fat-arm64.tmpl.bz2.uu sys/boot/efi/boot1/fat-arm64.tmpl.bz2.uu
index 1101deb0227..1fa41380542 100644
--- sys/boot/efi/boot1/fat-arm64.tmpl.bz2.uu
+++ sys/boot/efi/boot1/fat-arm64.tmpl.bz2.uu
@@ -2,25 +2,49 @@ FAT template boot filesystem created by generate-fat.sh
DO NOT EDIT
$FreeBSD$
begin 644 fat-arm64.tmpl.bz2
-M0EIH.3%!629364C65#T`&U;_____Z^KJZ_^N_^O^J_^[OJ[NK^JJ^KZNKNNJ
-MZNKNZOJ^P`+\#0``0`#0#)D&@TR8AD`,0!D--&`@:!H&@`!B#)IHR:--#(9,
-MAA`8F at Q,0,#52`_U4?J@`&AH```:`:``````T-`T&@R&@T``````````$``T
-M`R9!H-,F(9`#$`9#31@(&@:!H``8 at R::,FC30R&3(80&)H,3$#`521(]I1I)
-MF*:8C1Z`F0:`TR,@:&C30:`R!HTT,$!DTT-J:&@R&C)IA,:F33(S4]-3`--$
-MZ--B6=6F1M!<28FJA"+E)$0B<@B(B"TK+:2%L)0B!"'(D$$(9F:@LRO+Q;TL
-MNJ9YY2QZK1*-0US5+UM6R;E?-T_QQG*=-<9#J:#>R[!&-40;(2B`0AE9=956
-MO+"IH&,8M=KEBF(3,A$H5JU%:M6K5K1-.A)------6K35I*TJU:M6K<RU323
-M333338A4FDFFFFFFMX;;,<,#`P,#`P,".`@0($"!`@0($"!`@0J5,OJY*%:M
-M6K5JU:I4J5*E2I4J*E2I4J5*EQ<9OW>[LK*RLK*RLK*INY)IIIIIIL6F3333
-M333=7VLL91VEN[UP[M$I,5X--+ at R1:XKTL?G%LL>,D\Y*-*DU+6MB^YMF\7S
-MB,!S6CMPUEU'H'B0`4V-'(@!JKN]^?Z<]*UB`&/9J#*9N at O9.H6FYDN5AT,L
-MS-UAW-A;:O3J61R=".=)EY-(TK3M8US8NM;1N&\<%Q%^Y3"9%=8Z-AUMYA;W
-MPYKK)5;?@6D;$DWL"J0LE*.Q]RA>Q[,;.QH%VDM/KGE)[.JBX4T=56_.0JD:
-MUL&Q73$OR;=NF^?PXKCL%SF=:1FKO&W%A1)O,YWU&FM;1N]W0QW=6U*UDS]Q
-M0M\CN\G:L^KT%O2U%G0;335JJYFAG8I,5$D?:UC\'Z/U;QO7`<)_3CL!R7/=
-M%B=L<+`H+J1;6??%$1%*H8[34M_N$+V0O6O;YJ7!95E7%<9?L%R7-83#:)BY
-M(D$F?DZ4B^,W)%W)SY(X;B/[<9?L\P'_-*YC<N>PGRLLY=[?HU\D?[A\BDOL
-MP)20P6A<ERG+;5S'-<YT&$OF&Z3IKLPY'3DPI,"1F-ET\-^SUZ&2DBC-1`(0
-6E`!:TJ9&`C?I,%_XNY(IPH2"1K*AZ```
+M0EIH.3%!629366M+$VP`'Z%______________^O^J_^[OJ[^J^NK^KZNK_NJ
+MZNK^ZN[^X`C_%``&B@`)"0D2$B0&JJ:8F`F``>]5````````````````````
+M``````````*JJDT`&G_^J2I_^I4_RJGJ``!H``-````````&@-`````````&
+M@#0`&AH!`:!H!H`:#30R`&FA at F@T-!IB!H#(#3$``9```:`#",`@`,@:````
+M0&@:`:`&@TT,@!IH8)H-#0:8@:`R`TQ``&0``&@`PC`(`#(&@```$!H&@&@!
+MH--#(`::&":#0T&F(&@, at -,0`!D``!H`,(P"``R!H````*JD?I'H1*;293/%
+M*FVJ;?JJ?JFGM2&F0VB`/4'J`>2&@R:#0#1H-'H3)IY0'J'I`T:&@TTT_1(T
+MVIFH'I-I/334]&3)E/-BFK[5U\L1LVS`Z+4,,,*ZF#!AAAAC87U88`P+CQM8
+MPPPP';U:S/K=9G1]*EW*/6M7YKUS7^J[U[-W[^I_$]^\)V'B/BO(>>V8':L.
+MF[3K4>#JPPP888`5#1,2SH&`V!@,!X#`8(,$"!`@0($"!`@0($"=FZ;LW.[A
+MS-QZ'#4X-3 at X)<'!5P3P<'!P<'!P<'!P<'!P<'!R-SLMR&YN4;FYN;FYN;FY
+MN;FYN;FYN;FYN;G!SN#F<':4<&I1JYW1;70;'DY*M2JJJJJKLVQ5L:E\-2ZZ
+MZZZ[]?[#X%\+KKKKKKI:*M$8:UEEEEEDI2E*4I2LJLZ_L]3%1FS9LV;-*4I2
+ME*4LU6:&M999999R\GU'M<V;-FS9LV:6Q5L=BB%UUUUUW259K,T-:ZZZZZ[K
+M_2:N77Z3-V[\)[)^Z]X^"^._XZJJJJJJJJ7U:KU:&M999999*4I2E*4K*K(:
+MUEEEEEDI2E*4I2LJLAK6666667JJJJJJJJE=5=W5$+KKKKKLZJJJJJJJI9JL
+MWQ-G<9,6C1HT:-$I2E*4I2T5:(:UEEEEEFW0>LPP];FS9LV;-FS2V*MB&M99
+M9999*RJR&M999999U/8=KHS9L='=,NS#1,MG'.,NCMG7,CR7@*>V]-F7T,\N
+M^]H'/8!V'4P_+.YPPP`(I^9J#`![;J>Y_A_D^TU98&`#T+M'<N*SBXN+BXN+
+MBXN+BXN+BXN+BXN+B[)ZQSNJWM[%O;V3>WM[>WM[>WM[>WM[>WM[*93*7777
+M777777777777777777=-TW9-[G;V]1#G=%M=!HS2E*4I2E*ZJZ&M999999.$
+MI2E*4I656>DHA======ZJJJJJJJJJ6:K-#6LLLLLLE*4I2E*5E5D-:RRRRRS
+MW-55555554KJKNLZ%=3T2631HT2T:):*M$-:RRRRRR7Y3VCOG\[L/]WR'E^I
+M55555552[C\A9W;TOS>O+%L;&QL;&Q*4I2E*4M%6CJ=YVV3%KT:-&C1H]3AA
+M99555555+8JV+^C^BR8M&C1HT:)2E*4I2EHJT0UK+++++)2E*4I2E959#6LL
+MLLLLE*4I2E*5E5GRZ(7777772E*4I2E*ZJZ&M999999LJNLNAK7777776556
+M>R7?OLW;-'OVQX;H/CN1Y;D;6UM<CD<B(B(B(C-,XU!L*VJY;N[+++++++++
+M++++++-9S7]^UPF+%BQ8L6+%BQ8L6+%BQ:FZCJ.HZ&K=YOQI2EDCOS4HHH^'
+M at +:AZ`R9,F2$(0A"$/K_T\6+%B]+A[##W4_=O:N]=R^@44445_FZ'7S]U?7S
+M(U^CT:-&C^ZBBBB$(0A"$(0A"]%%%$(0ATFU_8]Z[#X+XCQ'BO'>4^L<B(B(
+MB(B(B(CDG=/!9MF[ZI9999999999999999I<1$1&D(B(B.1R.1TG2=)TG/11
+M1X&+ZWMX]CT:JJJNQV,6+%B]!VVS)DR9+4444>NZN+%BQ=#K?;^BL[IW[NWN
+MW)Z_ER9,F3N^CZ_W?L=%],V;-FA"$/P,YR9,F2$(0Z=%%%$(0A"$(?WO?/`>
+M"_U>&_Z>*\9Y#RWV3;M;6#!@P8,&#!@P8,&#!XSJGD/54I2E*4I2E*4I2D1$
+M1$1$1$1$<SF<SF>%_[BQ8L4(0A"$(0A"$(0A\Y[3%BQ8O@>\=\[QX"$(0A"$
+M/>T444?XT4440A"$(0AS=EWHUX889,F3)"$(=Z^$Z[8GS,^^U^+\V@:%_B(B
+M(B(B(B(B.-9E\#/*4I2E*4I2E*4V;%BP8,&#:VMK:VMK:VMK:Y'(YW.YW.A"
+M$(0A"$(0^ZHHHH\ZBBBB$(0_T?"?#>&A"$/L:***(0A#JA1111PHHHH\JBBB
+MCQZ***(0A#_M\5]P^,\9\EY+L/*?,?N/3/([[E<KE<KE<K(R,C(R,C(R,C(S
+M[['W-J4I2E*4I2E*4I2D1$1$1$1$1$4I2D(0AWE%%%$(0A"$(>+YOX.3)DR0
+MA"'RO"=5]Z^0A"$(0A"$(0I1111"$(0A"$(0A"$(?)>0\%Y+Y3Y;RWS'A/-?
+M->>B(B(B(B(B(B[0ND?TI2E*4I2E*4I2E(B(B(B(B(CD<CF<SF<SQ****(0A
+M#SJ***/34444?^44440A"'TWJ_.\QYCS'F(0A#WSM<6+%B]511113\_%BQ8J
+G8X8&&&`U888`'G9,F3)E1111#QU%%$'GM3_Y_^+N2*<*$@UI8FV`
`
end
diff --git sys/boot/efi/boot1/fat-i386.tmpl.bz2.uu sys/boot/efi/boot1/fat-i386.tmpl.bz2.uu
index 74c734d2d37..c0440cae421 100644
--- sys/boot/efi/boot1/fat-i386.tmpl.bz2.uu
+++ sys/boot/efi/boot1/fat-i386.tmpl.bz2.uu
@@ -2,25 +2,49 @@ FAT template boot filesystem created by generate-fat.sh
DO NOT EDIT
$FreeBSD$
begin 644 fat-i386.tmpl.bz2
-M0EIH.3%!629361/"1&$`&U;_____Z^KJZ_ZN_^O^J_^[OJ[NK^JJ^KZNKNNJ
-MZNKNZOJ^P`+\#0``0`#0&C31H#3$&$`R,AH-#3"#!,30:`&@`!@F at 8)D&$:#
-M(::83)B`&@:J0:?ZJ/U30`,@```-`,F@``````R-```R``````````$``T!H
-MTT:`TQ!A`,C(:#0TP at P3$T&@!H``8)H&"9!A&@R&FF$R8@!H"JB(GM*:(3VI
-MJ:;29-DF)ZC1H#)IA&0,C1H`R`VH#3$#(#R(R#(T8FFR$P(R8&AHQ3TTU.M/
-M4CH56XJBSBR%$R"%HBA""$HA"$(0*M)8Q06(C!"`@@OXA`@@[^28LHY?+JTZ
-MY4-*\Q4]=JDWP-DUR\;EM6^<1OW+<Q@,99V]K,<"*#>(;UG$,HJ0@""#-QRL
-MK%;U%@U#)LDM5=:+-(N(1 at I4IJ5*E2I54DID4DDDDDE*E)2BI1I4J5*EU;!)
-M%))))))CE"2*222222VAMLQPP,#`P,#`P(X"!`@0($"!`@0($"!"A0[?7Q3*
-M5*E2I4J5"A0H4*%"A04*%"A0H4+.ST&QK*RLK*RLK*RA>Q22222226J1))))
-M)))E.[CDIL[6:1_==<1)HM-I)YW&BA1::S+:)65-0B]%&'M(M<V2\;ANU\XC
-MDN at P6KK!L*\/4/(@`3U-7$@`^+([2[^_Q8V$(`,J\&!FM!,;2+'JN_BM,?5?
-M]<L]7Q:]TM\Q0QVOF&%%<Q:Q[:EL&S7C+-RWS at N,Y+G,!B+A<VSZ\M;XG"\:
-M2OF*-[X56%V1<"`HB+(LZB&<]^9>0NH;>IIW;(JNVEFI;>C')YXV5+]XBB)\
-M[ZEVKL at W3>-^_IQW*<UT6$T3U7N9.RG317VA\.:ZL*J]MKV=;9^M.HBT^EF6
-M68O<S8-.I\NM.KV7E;C6TJ*9&IE4G.PA%#\6O?HW;^%\X#AN0Y3FN at Z;#=9D
-M/V./M9BO$L;+8B:$(3K:ZF<+>(%VV;@O/<5F69<ES'/=%TV"Q&*U3*10B$7C
-MQ3(=>*8X9GXH9&+#BAR'^.4Y;FM,Y[HL!@OY8;$?8S;J7G.0^F*'/Q;^<WV%
-MPQ&*#I-2P'4=5NF"PF&_UB.*Q778RU,6)C18D5_$SNVQL5?-;,[6*$V>A`$$
-7$8`%A.GB7Z'$1=)_XNY(IPH2`GA(C"``
+M0EIH.3%!62936=SO#C@`'YC______________^O^J_^[OJ[^J^NK^KZOKONJ
+MZNK^ZN[^X`C_*``&B@`4"0D2(B0&I*````````#0```````#(-``R```````
+M```````"JJE'ZH`:?_ZDJG_ZJ>JG_JJ````````````````#0``T```````#
+M0:&AZ@$!H&@&@!H--#(`::&":#0T&F(&@, at -,0`!D``!H`,(P"``R!H```!`
+M:!H!H`:#30R`&FA at F@T-!IB!H#(#3$``9```:`#",`@`,@:````0&@:`:`&@
+MTT,@!IH8)H-#0:8@:`R`TQ``&0``&@`PC`(`#(&@````JJ1^E'Z:22>E-/U3
+MU*?_I2GM2)_ZJF3TVJ>H>IH:,C0,T@:;4'J&@:#U--`:`9`>H!ZC30:`>H`>
+MU3U&3TCU--&AZ3T33#4]J:3M1;5],[S;L'-SS`ZK4,LLKZF3)EEEELH8U99`
+MR/+U#+++(9CZ.Z#/T/H6=GI$O6OLUGWK[5KIA8"H%V,<7HTANC4'..@>0_ at A
+MKX(FK!2V=#7*(0A"$(`%PKSW6IUUG7==AUW7>"Z72Z72Z72Z72Z72Z72Z72Z
+M7<NEP>K=N^0//Y:G%J<7%+BXKN*>+BXN+BXN+BXN+BXN+BXM[O]'1HLT:+-&
+MC1HT:-&C1HT:-&C1HT:-'6<'6=NXN5G%J6:N#JN=U',^%M7:EUUUUUW=.9=S
+M-3#4PPPPPP_-]37^&K+######"6Y=N1EK4I2E*2E*4I2E*EU.Q^3J;%F;-FS
+M9LTI2E*4I2S79H:U*4I2G;;_3^TS9LV;-FS9I<R[F=FR&&&&&&'0NS4S0UL,
+M,,,,.QWVKMM?R^;Z1]H_%?JO%>Y>^?Z]TNNNNNNNEZA=X*&M2E*4I*4I2E*4
+MJ74AK4I2E*2E*4I2E*EU(:U*4I2F/JZ4I2E*4EFNS0UJ4I2E,[KKKKKKKI87
+M8>3S>KVMC<W-S<W-R4I2E*4I;EVY#6I2E*4E*4I2E*5+J0UJ4I2E)4NI#6I2
+ME*4T^^^3W,V;9N>M:W,U9>R>P:"CMW8,'DLXI[;TV+Z7QKOP9]SE at S>HY7-G
+M"965E`$6]AJ#(!^7UO;>U_<[_5MR,@'H'R+ZIR4Y.3DY.3DY.3DY.3DY.3DY
+M.3DY.X>N<'=-&C8T:-K1HT:-&C1HT:-&C1HT:-&CN7<KKKKKKKKKKKKKKKKK
+MKKKKKL6GLMHT60X.JYW4;F:4I2E*4I8780UJ4I2E)RE*4I2E*EU.]LAAAAAA
+MAX%UUUUUUUTLUV:&M2E*4I*4I2E*4J74AK4I2E*>O]M2E*4I2DLUV;T3??4[
+MNTMK<W-R[<W);EU(:U*4I2DONWLWB/WW9>[>_>9Z5=======+O_"4_&?,?&[
+M$MCF<SF<SF8YFJ[T?8PPPPPPPIU%V;K^'L69LV;-FS2E*4I2E+-=FAK4I2E*
+M2E*4I2E*EU(:U*4I2DI2E*4I2I=2&M2E*4I*4I2E*4J74^)9######"4I2E*
+M4I878>F960PPPPPPNNPIA#6PPPG###"E-(=.TEWK2FVLT]9FGRM+9U'\HLLL
+MB(B(C>WM[>WNP]DZKNWT'7>)T.AT.AT.AT.AT.AT.AT.AT.AZ#L=KQ_6<'!P
+M<'!P<'!P<'!P<'!P<'6=9UG6=3O=.UJE*4H]J:EEEG^60K4.N=,I2E"$(0A"
+M'T7X>QL;&QWV7L<O;SX#V;\]^F[U9999?]WJ=C/V^."(U=7<W-S<_FLLLLA"
+M$(0A"$(0Q9999"$(=#G>*_H>,]P_S?[O*?`?%>H;V]O;V]$1$1$1$<J[MG'B
+M.EU+%BQ8L6+%BQ8L6+%BQ8M'B(B(T1$1$1$1B[AW#N'"RRSL['T/J8_"ZMUU
+MUWC=?QMK:VMKK^EZFUM;6UBRRRSU_?[&QL;&_T7K.[I]8\)^._@;_"[;:VMK
+M:[OJ_=?J?@;F-V;-FS0A"'V.<[6UM;4(0AW-EEED(0A"$(?SOZG9?W/<O)>\
+M>4\M\%YCU3GYW.YW.YW.LLLLLLLLLL\5YCR'J*4I2E*4I2E*4I2(B(B(B(B(
+MB*4I3R/?;&QL;$(0A"$(0A"$(0AY[VFQL;&QX_BO$>&[*$(0A"$*LLLLA"$(
+M0A"$(0\OWOZ`UY99;6UM;4(0A[%[IWCO'O'_#RGY,\S[,?XB(B(B(B(B(CC6
+M;?"^12E*4I2E*4I2FS9;+66666666<[G<[G<[G;V]P<'!P0A"$(0A"$(>!99
+M99YUEEED(0A[AY#R7NT(0AZJRRRSN at LLLLA"$.-EEEGQ;+++(0A"$,C(^I]C
+M at WW/Q9Y^SUW\,QW+!^G>8,&#!@P8,&#!@P8,&#!];[6=;.I2E*4I2E*4I2E(
+MB(B(B(B(B(I2E,C(R,CP[+++(0A"$(0_Z[7KMK:VMJ$(0^'Y#_MX+WZ$(0A"
+M$(0A"UEEED(0A"$(0A"$(0A_X^"\=\)\-\1YC_Y[IVGQGQV]O;V]$1$1$1$1
+M=F.F?TI2E*4I2E*4I2E(B(B(B(B(B(I3MW;O>V6660A"'G6666=]9999_S99
+M99"$(>D^N\[S7FO->:A"$/['H]C8V-CP+++++?@[&QL;%MF61EED-6660!YV
+A<#S[+FVTI2&VRRRR'P%EED'QVI_Z__%W)%.%"0W.\..`
`
end
diff --git sys/boot/efi/boot1/generate-fat.sh sys/boot/efi/boot1/generate-fat.sh
index d9dfb27de25..7c46e926f60 100755
--- sys/boot/efi/boot1/generate-fat.sh
+++ sys/boot/efi/boot1/generate-fat.sh
@@ -13,7 +13,7 @@
FAT_SIZE=1600 #Size in 512-byte blocks of the produced image
-BOOT1_SIZE=128k
+BOOT1_SIZE=512k
#
# Known filenames
diff --git sys/boot/efi/boot1/ufs_module.c sys/boot/efi/boot1/ufs_module.c
deleted file mode 100644
index 0860a860fdf..00000000000
--- 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
-};
diff --git sys/boot/efi/boot1/zfs_module.c sys/boot/efi/boot1/zfs_module.c
deleted file mode 100644
index 1926a33010d..00000000000
--- sys/boot/efi/boot1/zfs_module.c
+++ /dev/null
@@ -1,196 +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;
-
-static int
-vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
-{
- dev_info_t *devinfo;
- off_t lba;
- EFI_STATUS status;
-
- devinfo = (dev_info_t *)priv;
- lba = off / devinfo->dev->Media->BlockSize;
-
- status = devinfo->dev->ReadBlocks(devinfo->dev,
- devinfo->dev->Media->MediaId, lba, bytes, buf);
- if (status != EFI_SUCCESS) {
- DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %jd, size: %zu,"
- " status: %lu\n", devinfo->dev,
- devinfo->dev->Media->MediaId, (intmax_t)lba, bytes,
- EFI_ERROR_CODE(status));
- return (-1);
- }
-
- return (0);
-}
-
-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 %zd for pool '%s' for '%s' "
- "(%lu)\n", 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
-};
diff --git sys/boot/efi/drivers/Makefile sys/boot/efi/drivers/Makefile
new file mode 100644
index 00000000000..5e1f18be252
--- /dev/null
+++ sys/boot/efi/drivers/Makefile
@@ -0,0 +1,34 @@
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+LIB= efi_drivers
+INTERNALLIB=
+WARNS?= 2
+
+SRCS= efipart.c fs_driver.c
+
+.if ${MACHINE_CPUARCH} == "aarch64"
+CFLAGS+= -msoft-float -mgeneral-regs-only
+.endif
+.if ${MACHINE_ARCH} == "amd64"
+CFLAGS+= -fPIC -mno-red-zone
+.endif
+.if ${MK_ZFS} != "no"
+CFLAGS+= -I${.CURDIR}/../../zfs
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
+CFLAGS+= -DEFI_ZFS_BOOT
+.endif
+
+CFLAGS+= -I${.CURDIR}/../include
+CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
+CFLAGS+= -I${.CURDIR}/../../../../lib/libstand
+
+# Pick up the bootstrap header for some interface items
+CFLAGS+= -I${.CURDIR}/../../common
+
+# Handle FreeBSD specific %b and %D printf format specifiers
+CFLAGS+= ${FORMAT_EXTENSIONS}
+CFLAGS+= -DTERM_EMU
+
+.include <bsd.lib.mk>
diff --git sys/boot/efi/drivers/efi_drivers.h sys/boot/efi/drivers/efi_drivers.h
new file mode 100644
index 00000000000..0c599d17af9
--- /dev/null
+++ sys/boot/efi/drivers/efi_drivers.h
@@ -0,0 +1,42 @@
+/*-
+ * 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_
+
+typedef struct efi_driver_t {
+ const char *name;
+ void (*init)(void);
+} efi_driver_t;
+
+extern struct devsw efipart_dev;
+
+/* EFI drivers. */
+extern const efi_driver_t fs_driver;
+
+#endif
diff --git sys/boot/efi/libefi/efipart.c sys/boot/efi/drivers/efipart.c
similarity index 75%
rename from sys/boot/efi/libefi/efipart.c
rename to sys/boot/efi/drivers/efipart.c
index 5a993812bce..3e3a9c04a17 100644
--- sys/boot/efi/libefi/efipart.c
+++ sys/boot/efi/drivers/efipart.c
@@ -74,90 +74,109 @@ static int npdinfo = 0;
#define PD(dev) (pdinfo[(dev)->d_unit])
+static EFI_STATUS
+efipart_supported(EFI_DRIVER_BINDING *This, EFI_HANDLE handle,
+ EFI_DEVICE_PATH *RemainingDevicePath __unused)
+{
+ return BS->OpenProtocol(handle, &blkio_guid,
+ NULL, IH, handle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+}
+
+static EFI_STATUS
+efipart_start(EFI_DRIVER_BINDING *This, EFI_HANDLE handle,
+ EFI_DEVICE_PATH *RemainingDevicePath __unused,
+ u_int* ndisk, uint* nrdisk)
+{
+ EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
+ EFI_STATUS status;
+ EFI_HANDLE alias;
+
+ devpath = efi_lookup_devpath(handle);
+
+ if (devpath == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ status = BS->HandleProtocol(handle, &blkio_guid,
+ (void**)&blkio);
+ if (EFI_ERROR(status))
+ return (status);
+
+ if (!blkio->Media->LogicalPartition) {
+ *nrdisk++;
+ return (EFI_UNSUPPORTED);
+ }
+
+ /*
+ * If we come across a logical partition of subtype CDROM
+ * it doesn't refer to the CD filesystem itself, but rather
+ * to any usable El Torito boot image on it. In this case
+ * we try to find the parent device and add that instead as
+ * that will be the CD filesystem.
+ */
+ node = efi_devpath_last_node(devpath);
+ if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(node) == MEDIA_CDROM_DP) {
+ devpathcpy = efi_devpath_trim(devpath);
+ tmpdevpath = devpathcpy;
+ status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
+ &alias);
+ free(devpathcpy);
+
+ if (EFI_ERROR(status))
+ return (status);
+
+ efi_register_handle(&efipart_dev, handle, alias);
+ } else
+ efi_register_handle(&efipart_dev, handle, NULL);
+
+ pdinfo[npdinfo].pd_open = 0;
+ pdinfo[npdinfo].pd_bcache = NULL;
+ pdinfo[npdinfo].pd_unit = npdinfo;
+ npdinfo++;
+ *ndisk++;
+
+ return (EFI_SUCCESS);
+}
+
static int
-efipart_init(void)
+efipart_init(void)
{
- EFI_BLOCK_IO *blkio;
- EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
- EFI_HANDLE *hin, *hout, *aliases, handle;
+ EFI_HANDLE *handles;
EFI_STATUS status;
UINTN sz;
- u_int n, nin, nout, nrdisk;
+ u_int n, nin, ndisk, nrdisk;
int err;
sz = 0;
- hin = NULL;
+ handles = NULL;
status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
if (status == EFI_BUFFER_TOO_SMALL) {
- hin = (EFI_HANDLE *)malloc(sz * 3);
+ handles = (EFI_HANDLE *)malloc(sz);
status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
- hin);
+ handles);
if (EFI_ERROR(status))
- free(hin);
+ free(handles);
}
if (EFI_ERROR(status))
return (efi_status_to_errno(status));
/* Filter handles to only include FreeBSD partitions. */
nin = sz / sizeof(EFI_HANDLE);
- hout = hin + nin;
- aliases = hout + nin;
- nout = 0;
- nrdisk = 0;
-
- bzero(aliases, nin * sizeof(EFI_HANDLE));
pdinfo = malloc(nin * sizeof(*pdinfo));
- if (pdinfo == NULL)
- return (ENOMEM);
+ ndisk = 0;
+ nrdisk = 0;
for (n = 0; n < nin; n++) {
- devpath = efi_lookup_devpath(hin[n]);
- if (devpath == NULL) {
- continue;
- }
-
- status = BS->HandleProtocol(hin[n], &blkio_guid,
- (void**)&blkio);
- if (EFI_ERROR(status))
- continue;
- if (!blkio->Media->LogicalPartition) {
- nrdisk++;
- continue;
- }
-
- /*
- * If we come across a logical partition of subtype CDROM
- * it doesn't refer to the CD filesystem itself, but rather
- * to any usable El Torito boot image on it. In this case
- * we try to find the parent device and add that instead as
- * that will be the CD filesystem.
- */
- node = efi_devpath_last_node(devpath);
- if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
- DevicePathSubType(node) == MEDIA_CDROM_DP) {
- devpathcpy = efi_devpath_trim(devpath);
- tmpdevpath = devpathcpy;
- status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
- &handle);
- free(devpathcpy);
- if (EFI_ERROR(status))
- continue;
- hout[nout] = handle;
- aliases[nout] = hin[n];
- } else
- hout[nout] = hin[n];
- nout++;
- pdinfo[npdinfo].pd_open = 0;
- pdinfo[npdinfo].pd_bcache = NULL;
- pdinfo[npdinfo].pd_unit = npdinfo;
- npdinfo++;
+ efipart_start(NULL, handles[n], NULL, &ndisk, &nrdisk);
}
bcache_add_dev(npdinfo);
- err = efi_register_handles(&efipart_dev, hout, aliases, nout);
- free(hin);
+ free(handles);
- if (nout == 0 && nrdisk > 0)
+ if (ndisk == 0 && nrdisk > 0)
printf("Found %d disk(s) but no logical partition\n", nrdisk);
return (err);
}
diff --git sys/boot/efi/drivers/fs_driver.c sys/boot/efi/drivers/fs_driver.c
new file mode 100644
index 00000000000..b9c85362a71
--- /dev/null
+++ sys/boot/efi/drivers/fs_driver.c
@@ -0,0 +1,853 @@
+/*-
+ * 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 <stddef.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <efi.h>
+#include <efilib.h>
+#include <efiprot.h>
+#include <string16.h>
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
+#include <bootstrap.h>
+
+#include "efi_drivers.h"
+
+static EFI_GUID SimpleFileSystemProtocolGUID = SIMPLE_FILE_SYSTEM_PROTOCOL;
+
+static struct fs_ops *backend_file_system[] = {
+ &dosfs_fsops,
+ &ufs_fsops,
+ &cd9660_fsops,
+ &tftp_fsops,
+ &nfs_fsops,
+ &gzipfs_fsops,
+ &bzipfs_fsops,
+ NULL
+};
+
+static struct devsw *backend_devsw[] = {
+ &efipart_dev,
+#ifdef EFI_ZFS_BOOT
+ &zfs_dev,
+#endif
+ NULL
+};
+
+typedef struct volinfo_t {
+ struct fs_ops *fsops;
+ struct devdesc *dev;
+} volinfo_t;
+
+typedef struct fileinfo_t {
+ const volinfo_t* vinfo;
+ struct open_file fdata;
+ char path[];
+} fileinfo_t;
+
+static EFI_GUID FileInfoGUID = EFI_FILE_INFO_ID;;
+
+static EFIAPI EFI_STATUS
+file_open_impl(EFI_FILE_HANDLE File, EFI_FILE_HANDLE *NewHandle,
+ CHAR16 *FileName, UINT64 OpenMode, UINT64 Attributes);
+
+static EFIAPI EFI_STATUS
+file_close_impl(EFI_FILE_HANDLE File);
+
+static EFIAPI EFI_STATUS
+file_delete_impl(EFI_FILE_HANDLE File);
+
+static EFIAPI EFI_STATUS
+dir_read_impl(EFI_FILE_HANDLE File, UINTN *BufferSize, VOID *Buffer);
+
+static EFIAPI EFI_STATUS
+dir_write_impl(EFI_FILE_HANDLE File, UINTN *BufferSize,
+ VOID *Buffer);
+
+static EFIAPI EFI_STATUS
+file_read_impl(EFI_FILE_HANDLE File, UINTN *BufferSize, VOID *Buffer);
+
+static EFIAPI EFI_STATUS
+file_write_impl(EFI_FILE_HANDLE File, UINTN *BufferSize,
+ VOID *Buffer);
+
+static EFIAPI EFI_STATUS
+file_set_position_impl(EFI_FILE_HANDLE File, UINT64 Position);
+
+static EFIAPI EFI_STATUS
+file_get_position_impl(EFI_FILE_HANDLE File, UINT64 *Position);
+
+static EFIAPI EFI_STATUS
+file_get_info_impl(EFI_FILE_HANDLE File, EFI_GUID *InformationType,
+ UINTN *BufferSize, VOID *Buffer);
+
+static EFIAPI EFI_STATUS
+file_set_info_impl(EFI_FILE_HANDLE File, EFI_GUID *InformationType,
+ UINTN BufferSize, VOID *Buffer);
+
+static EFIAPI EFI_STATUS
+file_flush_impl(EFI_FILE_HANDLE File);
+
+static struct devdesc*
+clone_devdesc(struct devdesc *dev)
+{
+ struct devdesc *out;
+
+ switch(dev->d_dev->dv_type) {
+ case DEVT_ZFS:
+ out = malloc(sizeof(struct zfs_devdesc));
+
+ if (out == NULL) {
+ return NULL;
+ }
+
+ memcpy(out, dev, sizeof(struct zfs_devdesc));
+
+ return out;
+
+ default:
+ out = malloc(sizeof(struct devdesc));
+
+ if (out == NULL) {
+ return NULL;
+ }
+
+ memcpy(out, dev, sizeof(struct devdesc));
+
+ return out;
+ }
+}
+
+static EFI_STATUS
+do_file_open(const volinfo_t *vinfo, const char filepath[],
+ int mode, EFI_FILE_HANDLE *out)
+{
+ EFI_FILE_HANDLE fhandle;
+ fileinfo_t *finfo;
+ struct stat st;
+ struct devdesc *tmpdev;
+ int err;
+
+ memset(&st, 0, sizeof(struct stat));
+ fhandle = malloc(sizeof(EFI_FILE) + sizeof(fileinfo_t) +
+ strlen(filepath) + 1);
+
+ if (fhandle == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ tmpdev = clone_devdesc(vinfo->dev);
+
+ if (tmpdev == NULL) {
+ free(fhandle);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ finfo = (fileinfo_t*)(fhandle + 1);
+ finfo->fdata.f_flags = mode + 1;
+ finfo->fdata.f_dev = NULL;
+ finfo->fdata.f_ops = NULL;
+ finfo->fdata.f_offset = 0;
+ finfo->fdata.f_devdata = NULL;
+
+ if ((err = vinfo->dev->d_dev->dv_open(&(finfo->fdata), tmpdev)) != 0) {
+ free(fhandle);
+ return (errno_to_efi_status(err));
+ }
+
+ finfo->fdata.f_dev = vinfo->dev->d_dev;
+
+ if ((err = vinfo->fsops->fo_open(filepath, &(finfo->fdata))) != 0) {
+ free(fhandle);
+ return (errno_to_efi_status(err));
+ }
+
+ finfo->fdata.f_ops = vinfo->fsops;
+
+ if ((err = vinfo->fsops->fo_stat(&(finfo->fdata), &st)) != 0) {
+ free(fhandle);
+ return (errno_to_efi_status(err));
+ }
+
+ strcpy(finfo->path, filepath);
+ finfo->vinfo = vinfo;
+ fhandle->Revision = EFI_FILE_HANDLE_REVISION;
+ fhandle->Open = file_open_impl;
+ fhandle->Close = file_close_impl;
+ fhandle->Delete = file_delete_impl;
+ fhandle->SetPosition = file_set_position_impl;
+ fhandle->GetPosition = file_get_position_impl;
+ fhandle->GetInfo = file_get_info_impl;
+ fhandle->SetInfo = file_set_info_impl;
+ fhandle->Flush = file_flush_impl;
+
+ if (S_ISDIR(st.st_mode)) {
+ fhandle->Read = dir_read_impl;
+ fhandle->Write = dir_write_impl;
+ } else {
+ fhandle->Read = file_read_impl;
+ fhandle->Write = file_write_impl;
+ }
+
+ *out = fhandle;
+
+ return (EFI_SUCCESS);
+}
+
+static int
+mode_from_efi(UINT64 efi_mode)
+{
+ int mode = 0;
+
+ if (efi_mode & EFI_FILE_MODE_WRITE) {
+ mode |= O_WRONLY;
+ } else if (efi_mode & EFI_FILE_MODE_READ) {
+ mode |= O_RDONLY;
+ } else if (efi_mode & EFI_FILE_MODE_READ &&
+ efi_mode & EFI_FILE_MODE_WRITE) {
+ mode |= O_RDWR;
+ }
+
+ return mode;
+}
+
+static UINT64
+mode_to_efi(int mode)
+{
+ UINT64 efi_mode = 0;
+
+ if (mode & O_WRONLY) {
+ efi_mode |= EFI_FILE_MODE_WRITE;
+ } else if (mode & O_RDONLY) {
+ efi_mode |= EFI_FILE_MODE_READ;
+ } else if (mode & O_RDWR) {
+ efi_mode |= EFI_FILE_MODE_READ;
+ efi_mode |= EFI_FILE_MODE_WRITE;
+ }
+
+ return (efi_mode);
+}
+
+static EFIAPI EFI_STATUS
+file_open_impl(EFI_FILE_HANDLE File, EFI_FILE_HANDLE *NewHandle,
+ CHAR16 *FileName, UINT64 OpenMode, UINT64 Attributes)
+{
+ fileinfo_t *finfo = (fileinfo_t*)(File + 1);
+ char buf[strlen(finfo->path) + strlen16(FileName) + 1];
+
+ strcpy_from_16(stpcpy(buf, finfo->path), FileName);
+
+ return do_file_open(finfo->vinfo, buf,
+ mode_from_efi(OpenMode), NewHandle);
+}
+
+static EFIAPI EFI_STATUS
+file_close_impl(EFI_FILE_HANDLE File)
+{
+ fileinfo_t *finfo = (fileinfo_t*)(File + 1);
+ int res;
+
+ if ((res = finfo->fdata.f_ops->fo_close(&(finfo->fdata))) != 0) {
+ return (errno_to_efi_status(res));
+ }
+
+ if ((res = finfo->vinfo->dev->d_dev->dv_close(&(finfo->fdata))) != 0) {
+ return (errno_to_efi_status(res));
+ }
+
+ free(File);
+ return (EFI_SUCCESS);
+}
+
+static EFIAPI EFI_STATUS
+file_delete_impl(EFI_FILE_HANDLE File)
+{
+ file_close_impl(File);
+
+ return (EFI_WARN_DELETE_FAILURE);
+}
+
+static EFIAPI EFI_STATUS
+dir_read_impl(EFI_FILE_HANDLE File, UINTN *BufferSize, VOID *Buffer)
+{
+ fileinfo_t *finfo = (fileinfo_t*)(File + 1);
+ fileinfo_t *entinfo;
+ struct dirent d;
+ struct stat st;
+ int err;
+ UINTN currsize = *BufferSize;
+ UINTN reqsize;
+ EFI_FILE_INFO *out = (EFI_FILE_INFO*)Buffer;
+ EFI_FILE_HANDLE enthandle;
+ EFI_STATUS status;
+ off_t currpos;
+
+ /* Record teh current position so we can rewind if we have to */
+ if ((currpos = finfo->fdata.f_ops->fo_seek(&(finfo->fdata),
+ 0, SEEK_CUR)) < 0) {
+ return (errno_to_efi_status(errno));
+ }
+
+ if ((err = finfo->fdata.f_ops->fo_readdir(&(finfo->fdata), &d)) != 0) {
+ return (errno_to_efi_status(errno));
+ }
+
+ reqsize = sizeof(EFI_FILE_INFO) +
+ ((strlen(d.d_name) + 1) * sizeof(CHAR16));
+
+ if (Buffer == NULL || currsize < reqsize) {
+ finfo->fdata.f_ops->fo_seek(&(finfo->fdata), currpos, SEEK_SET);
+ *BufferSize = reqsize;
+
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+
+ // We have to actually open the file, since EFI directory
+ // reads are supposed to return stat information.
+ CHAR16 buf[d.d_namlen];
+ strcpy_to_16(buf, d.d_name);
+ status = file_open_impl(File, &enthandle, buf, EFI_FILE_READ_ONLY, 0);
+
+ if (EFI_ERROR(status)) {
+ finfo->fdata.f_ops->fo_seek(&(finfo->fdata), currpos, SEEK_SET);
+ return (status);
+ }
+
+ entinfo = (fileinfo_t*)(enthandle + 1);
+
+ if ((err = finfo->fdata.f_ops->fo_stat(&(entinfo->fdata), &st)) != 0) {
+ finfo->fdata.f_ops->fo_seek(&(finfo->fdata), currpos, SEEK_SET);
+ return (errno_to_efi_status(errno));
+ }
+
+ status = file_close_impl(enthandle);
+
+ if (EFI_ERROR(status)) {
+ finfo->fdata.f_ops->fo_seek(&(finfo->fdata), currpos, SEEK_SET);
+ return (status);
+ }
+
+ // We're good at this point, copy everything into place.
+ out->Size = reqsize;
+ out->FileSize = st.st_size;
+ out->PhysicalSize = st.st_blocks * st.st_blksize;
+ out->Attribute = mode_to_efi(st.st_mode);
+ to_efi_time(&(out->LastAccessTime), st.st_atime);
+ to_efi_time(&(out->ModificationTime), st.st_mtime);
+ to_efi_time(&(out->CreateTime), st.st_ctime);
+
+ if (S_ISDIR(st.st_mode)) {
+ out->Attribute |= EFI_FILE_DIRECTORY;
+ }
+
+ strcpy_to_16(out->FileName, d.d_name);
+ *BufferSize = reqsize;
+
+ return (EFI_SUCCESS);
+}
+
+static EFIAPI EFI_STATUS
+dir_write_impl(EFI_FILE_HANDLE File __unused, UINTN *BufferSize __unused,
+ VOID *Buffer __unused)
+{
+ // EFI API doesn't allow writing to directories
+ return (EFI_UNSUPPORTED);
+}
+
+static EFIAPI EFI_STATUS
+file_read_impl(EFI_FILE_HANDLE File, UINTN *BufferSize, VOID *Buffer)
+{
+ fileinfo_t *finfo = (fileinfo_t*)(File + 1);
+ size_t readsize = *BufferSize;
+ size_t resid;
+ int err;
+
+ if ((err = finfo->fdata.f_ops->fo_read(&(finfo->fdata), Buffer,
+ readsize, &resid)) != 0) {
+ return (errno_to_efi_status(errno));
+ }
+
+ *BufferSize = readsize - resid;
+
+ return (EFI_SUCCESS);
+}
+
+static EFIAPI EFI_STATUS
+file_write_impl(EFI_FILE_HANDLE File, UINTN *BufferSize, VOID *Buffer)
+{
+ fileinfo_t *finfo = (fileinfo_t*)(File + 1);
+ size_t writesize = *BufferSize;
+ size_t resid;
+ int err;
+
+ if ((err = finfo->fdata.f_ops->fo_write(&(finfo->fdata), Buffer,
+ writesize, &resid)) != 0) {
+ return (errno_to_efi_status(errno));
+ }
+
+ *BufferSize = writesize - resid;
+
+ return (EFI_SUCCESS);
+}
+
+static EFIAPI EFI_STATUS
+file_set_position_impl(EFI_FILE_HANDLE File, UINT64 Position)
+{
+ fileinfo_t *finfo = (fileinfo_t*)(File + 1);
+ int res;
+
+ if (Position != 0xffffffffffffffffLL) {
+ res = finfo->fdata.f_ops->fo_seek(&(finfo->fdata),
+ Position, SEEK_SET);
+ } else {
+ res = finfo->fdata.f_ops->fo_seek(&(finfo->fdata),
+ 0, SEEK_END);
+ }
+
+ if (res > 0) {
+ return (EFI_SUCCESS);
+ } else {
+ return (errno_to_efi_status(res));
+ }
+}
+
+
+static EFIAPI EFI_STATUS
+file_get_position_impl(EFI_FILE_HANDLE File, UINT64 *Position)
+{
+ fileinfo_t *finfo = (fileinfo_t*)(File + 1);
+ off_t res;
+
+ res = finfo->fdata.f_ops->fo_seek(&(finfo->fdata), 0, SEEK_CUR);
+
+ if (res > 0) {
+ *Position = res;
+
+ return (EFI_SUCCESS);
+ } else {
+ return (errno_to_efi_status(errno));
+ }
+}
+
+static EFIAPI EFI_STATUS
+file_get_info_impl(EFI_FILE_HANDLE File, EFI_GUID *InformationType,
+ UINTN *BufferSize, VOID *Buffer)
+{
+ fileinfo_t *finfo = (fileinfo_t*)(File + 1);
+
+ if (!memcmp(InformationType, &FileInfoGUID, sizeof(EFI_GUID))) {
+ EFI_FILE_INFO *out = (EFI_FILE_INFO*)Buffer;
+ UINTN str16len =(strlen(finfo->path) + 1) * sizeof(CHAR16);
+ UINTN currsize = *BufferSize;
+ UINTN reqsize = sizeof(EFI_FILE_INFO) + str16len;
+ struct stat st;
+ int err;
+
+ memset(&st, 0, sizeof(struct stat));
+ *BufferSize = reqsize;
+
+ if (Buffer == NULL ||
+ currsize < sizeof(EFI_FILE_INFO) + str16len) {
+ *BufferSize = sizeof(EFI_FILE_INFO) + str16len;
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+
+ if ((err = finfo->fdata.f_ops->fo_stat(&(finfo->fdata),
+ &st)) != 0) {
+ return (errno_to_efi_status(errno));
+ }
+
+ out->Size = sizeof(EFI_FILE_INFO) + str16len;
+ out->FileSize = st.st_size;
+ out->PhysicalSize = st.st_blocks * st.st_blksize;
+ to_efi_time(&(out->LastAccessTime), st.st_atime);
+ to_efi_time(&(out->ModificationTime), st.st_mtime);
+ to_efi_time(&(out->CreateTime), st.st_ctime);
+ out->Attribute = mode_to_efi(st.st_mode);
+
+ if (S_ISDIR(st.st_mode)) {
+ out->Attribute |= EFI_FILE_DIRECTORY;
+ }
+
+ strcpy_to_16(out->FileName, finfo->path);
+ } else {
+ return (EFI_UNSUPPORTED);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+static EFIAPI EFI_STATUS
+file_set_info_impl(EFI_FILE_HANDLE File __unused,
+ EFI_GUID *InformationType __unused,
+ UINTN BufferSize __unused, VOID *Buffer __unused)
+{
+ return (EFI_WRITE_PROTECTED);
+}
+
+static EFIAPI EFI_STATUS
+file_flush_impl(EFI_FILE_HANDLE File __unused)
+{
+ return (EFI_SUCCESS);
+}
+
+static EFIAPI EFI_STATUS
+open_volume_impl(EFI_FILE_IO_INTERFACE *This, EFI_FILE_HANDLE *Root)
+{
+ volinfo_t *vinfo = (volinfo_t*)(This + 1);
+
+ return do_file_open(vinfo, "", O_RDONLY, Root);
+}
+
+static struct fs_ops*
+fs_probe(struct devdesc *dev)
+{
+ struct open_file f;
+ int err, i;
+
+ f.f_flags = O_RDONLY + 1;
+ f.f_dev = (struct devsw *)0;
+ f.f_ops = (struct fs_ops *)0;
+ f.f_offset = 0;
+ f.f_devdata = dev;
+
+ if ((err = dev->d_dev->dv_open(&f, dev)) != 0) {
+ return NULL;
+ }
+
+ for (i = 0; backend_file_system[i] != NULL; i++) {
+ f.f_ops = backend_file_system[i];
+
+ if ((err = f.f_ops->fo_open("/", &f)) == 0) {
+ return backend_file_system[i];
+ }
+ }
+
+ return NULL;
+}
+
+static EFI_STATUS
+make_fs_file_io_iface(struct devdesc *dev, EFI_FILE_IO_INTERFACE **out)
+{
+ static struct fs_ops* fsops;
+ EFI_FILE_IO_INTERFACE* fiface;
+ volinfo_t *vinfo;
+
+ switch (dev->d_type) {
+#ifdef EFI_ZFS_BOOT
+ case DEVT_ZFS:
+ fsops = &zfs_fsops;
+ break;
+#endif
+ default:
+ fsops = fs_probe(dev);
+ break;
+ }
+
+ if (fsops == NULL) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ fiface = malloc(sizeof(EFI_FILE_IO_INTERFACE) + sizeof(volinfo_t));
+
+ if (fiface == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ vinfo = (volinfo_t*)(fiface + 1);
+
+ fiface->Revision = EFI_FILE_IO_INTERFACE_REVISION;
+ fiface->OpenVolume = open_volume_impl;
+ vinfo->dev = dev;
+ vinfo->fsops = fsops;
+
+ *out = fiface;
+
+ return (EFI_SUCCESS);
+}
+
+static EFIAPI EFI_STATUS
+bind_iface(EFI_HANDLE handle, struct devdesc *dev)
+{
+ EFI_STATUS status;
+ EFI_FILE_IO_INTERFACE *iface;
+
+ // Check if there is already a filesystem interface
+ status = BS->OpenProtocol(handle, &SimpleFileSystemProtocolGUID,
+ NULL, IH, handle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (!EFI_ERROR(status)) {
+ return (EFI_ACCESS_DENIED);
+ } else if (status != EFI_UNSUPPORTED) {
+ return (status);
+ }
+
+ status = make_fs_file_io_iface(dev, &iface);
+
+ if (EFI_ERROR(status)) {
+ return (status);
+ }
+
+ status = BS->InstallMultipleProtocolInterfaces(&handle,
+ &SimpleFileSystemProtocolGUID, iface, NULL);
+
+ if (EFI_ERROR(status)) {
+ free(iface);
+
+ return (status);
+ }
+
+ return (status);
+}
+
+static EFIAPI EFI_STATUS
+stop_impl(EFI_DRIVER_BINDING *This __unused, EFI_HANDLE ControllerHandle __unused,
+ UINTN NumberOfChildren __unused, EFI_HANDLE *ChildHandleBuffer __unused)
+{
+ // Get the protocol inteface, uninstall it, and free it
+ return (EFI_SUCCESS);
+}
+
+#ifdef EFI_ZFS_BOOT
+static void
+efi_zfs_probe(void)
+{
+ EFI_HANDLE h;
+ u_int unit;
+ int i;
+ char dname[SPECNAMELEN + 1];
+ uint64_t guid;
+
+ unit = 0;
+ h = efi_find_handle(&efipart_dev, 0);
+ for (i = 0; h != NULL; h = efi_find_handle(&efipart_dev, ++i)) {
+ snprintf(dname, sizeof(dname), "%s%d:", efipart_dev.dv_name, i);
+ if (zfs_probe_dev(dname, &guid) == 0) {
+ (void)efi_handle_update_dev(h, &zfs_dev, unit++, guid);
+ }
+ }
+}
+#endif
+
+static int
+backend_parsedev(struct devdesc **dev, const char *devspec, const char **path)
+{
+ struct devdesc *idev;
+ struct devsw *dv;
+ char *cp;
+ const char *np;
+ int i;
+
+ /* minimum length check */
+ if (strlen(devspec) < 2)
+ return (EINVAL);
+
+ /* look for a device that matches */
+ for (i = 0; backend_devsw[i] != NULL; i++) {
+ dv = backend_devsw[i];
+ if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name)))
+ break;
+ }
+ if (backend_devsw[i] == NULL) {
+ return (ENOENT);
+ }
+
+ np = devspec + strlen(dv->dv_name);
+
+#ifdef EFI_ZFS_BOOT
+ if (dv->dv_type == DEVT_ZFS) {
+ int err;
+
+ idev = malloc(sizeof(struct zfs_devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
+
+ err = zfs_parsedev((struct zfs_devdesc*)idev, np, path);
+ if (err != 0) {
+ free(idev);
+ return (err);
+ }
+ *dev = idev;
+ cp = strchr(np + 1, ':');
+ } else
+#endif
+ {
+ idev = malloc(sizeof(struct devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
+
+ idev->d_dev = dv;
+ idev->d_type = dv->dv_type;
+ idev->d_unit = -1;
+ if (*np != '\0' && *np != ':') {
+ idev->d_unit = strtol(np, &cp, 0);
+ if (cp == np) {
+ idev->d_unit = -1;
+ free(idev);
+ return (EUNIT);
+ }
+ }
+ }
+
+ if (*cp != '\0' && *cp != ':') {
+ free(idev);
+ return (EINVAL);
+ }
+
+ if (path != NULL)
+ *path = (*cp == 0) ? cp : cp + 1;
+ if (dev != NULL)
+ *dev = idev;
+ else
+ free(idev);
+ return (0);
+}
+
+static int
+backend_getdev(void **vdev, const char *devspec, const char **path)
+{
+ struct devdesc **dev = (struct devdesc **)vdev;
+ int rv;
+
+ /*
+ * If it looks like this is just a path and no device, then
+ * use the current device instead.
+ */
+ if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) {
+ rv = backend_parsedev(dev, getenv("currdev"), NULL);
+ if (rv == 0 && path != NULL)
+ *path = devspec;
+ return (rv);
+ }
+
+ /* Parse the device name off the beginning of the devspec. */
+ return (backend_parsedev(dev, devspec, path));
+}
+
+static void
+init(void)
+{
+ EFI_HANDLE h;
+ EFI_STATUS status;
+ u_int unit;
+ int i;
+ struct devsw *dev;
+ uint64_t pool_guid;
+ int (*old_getdev)(void **, const char *, const char **) =
+ archsw.arch_getdev;
+
+ archsw.arch_getdev = backend_getdev;
+#ifdef EFI_ZFS_BOOT
+ /* Note this needs to be set before ZFS init. */
+ archsw.arch_zfs_probe = efi_zfs_probe;
+#endif
+
+ /* Initialize all the backend drivers */
+ for (i = 0; backend_devsw[i] != NULL; i++) {
+ if (backend_devsw[i]->dv_init != NULL)
+ (backend_devsw[i]->dv_init)();
+ }
+
+ /* Attach SIMPLE_FILE_SYSTEM interfaces to all efipart devices */
+ unit = 0;
+ h = efi_find_handle(&efipart_dev, 0);
+ for (i = 0; h != NULL; h = efi_find_handle(&efipart_dev, ++i)) {
+ struct devdesc *currdev;
+
+ currdev = malloc(sizeof(struct devdesc));
+
+ if (currdev == NULL) {
+ continue;
+ }
+
+ if (efi_handle_lookup(h, &dev, &unit, &pool_guid) != 0) {
+ free(currdev);
+ continue;
+ }
+
+ currdev->d_dev = dev;
+ currdev->d_unit = unit;
+ currdev->d_opendata = NULL;
+ currdev->d_type = currdev->d_dev->dv_type;
+
+ status = bind_iface(h, currdev);
+
+ if (EFI_ERROR(status) && status != EFI_UNSUPPORTED &&
+ status != EFI_ACCESS_DENIED) {
+ printf("Failed to attach filesystem interface to efipart%u (%ld)\n",
+ unit, EFI_ERROR_CODE(status));
+ free(currdev);
+ }
+ }
+
+ /* Attach SIMPLE_FILE_SYSTEM interface to all ZFS devices */
+#ifdef EFI_ZFS_BOOT
+ unit = 0;
+ h = efi_find_handle(&zfs_dev, 0);
+ for (i = 0; h != NULL; h = efi_find_handle(&zfs_dev, ++i)) {
+ struct zfs_devdesc *currdev;
+
+ currdev = malloc(sizeof(struct zfs_devdesc));
+
+ if (currdev == NULL) {
+ continue;
+ }
+
+ if (efi_handle_lookup(h, &dev, &unit, &pool_guid) != 0) {
+ free(currdev);
+ continue;
+ }
+
+ currdev->d_dev = dev;
+ currdev->d_unit = unit;
+ currdev->d_opendata = NULL;
+ currdev->d_type = currdev->d_dev->dv_type;
+ currdev->pool_guid = pool_guid;
+ currdev->root_guid = 0;
+
+ status = bind_iface(h, (struct devdesc*)currdev);
+
+ if (EFI_ERROR(status)) {
+ printf("Failed to attach filesystem interface to zfs%u (%ld)\n",
+ unit, EFI_ERROR_CODE(status));
+ }
+ }
+#endif
+ archsw.arch_getdev = old_getdev;
+}
+
+const efi_driver_t fs_driver =
+{
+ .name = "FS Backend",
+ .init = init,
+};
diff --git sys/boot/efi/include/efilib.h sys/boot/efi/include/efilib.h
index 09ccc2f3647..15d4b487d40 100644
--- sys/boot/efi/include/efilib.h
+++ sys/boot/efi/include/efilib.h
@@ -31,22 +31,26 @@
#define _LOADER_EFILIB_H
#include <stand.h>
+#include <time.h>
extern EFI_HANDLE IH;
-extern EFI_SYSTEM_TABLE *ST;
+extern EFI_SYSTEM_TABLE *ST;
extern EFI_BOOT_SERVICES *BS;
extern EFI_RUNTIME_SERVICES *RS;
-extern struct devsw efipart_dev;
+extern struct devsw efifs_dev;
extern struct devsw efinet_dev;
+extern struct fs_ops efifs_fsops;
extern struct netif_driver efinetif;
void *efi_get_table(EFI_GUID *tbl);
int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
+int efi_register_handle(struct devsw *, EFI_HANDLE, EFI_HANDLE);
EFI_HANDLE efi_find_handle(struct devsw *, int);
int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *, uint64_t *);
int efi_handle_update_dev(EFI_HANDLE, struct devsw *, int, uint64_t);
+int efi_handle_remove_dev(EFI_HANDLE);
EFI_DEVICE_PATH *efi_lookup_image_devpath(EFI_HANDLE);
EFI_DEVICE_PATH *efi_lookup_devpath(EFI_HANDLE);
@@ -57,6 +61,7 @@ CHAR16 *efi_devpath_name(EFI_DEVICE_PATH *);
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);
@@ -65,4 +70,7 @@ EFI_STATUS main(int argc, CHAR16 *argv[]);
void exit(EFI_STATUS status);
void delay(int usecs);
+time_t from_efi_time(EFI_TIME *efi_time);
+void to_efi_time(EFI_TIME *efi_time, time_t time);
+
#endif /* _LOADER_EFILIB_H */
diff --git sys/boot/efi/include/efiprot.h sys/boot/efi/include/efiprot.h
index 28cec5991e3..22215777cab 100644
--- sys/boot/efi/include/efiprot.h
+++ sys/boot/efi/include/efiprot.h
@@ -27,6 +27,8 @@ Revision History
--*/
+#include <efidef.h>
+
//
// Device Path protocol
//
@@ -307,9 +309,9 @@ typedef struct {
//
// The FileName field of the EFI_FILE_INFO data structure is variable length.
// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to
-// be the size of the data structure without the FileName field. The following macro
+// be the size of the data structure without the FileName field. The following macro
// computes this size correctly no matter how big the FileName array is declared.
-// This is required to make the EFI_FILE_INFO data structure ANSI compilant.
+// This is required to make the EFI_FILE_INFO data structure ANSI compilant.
//
#define SIZE_OF_EFI_FILE_INFO EFI_FIELD_OFFSET(EFI_FILE_INFO,FileName)
@@ -329,9 +331,9 @@ typedef struct {
//
// The VolumeLabel field of the EFI_FILE_SYSTEM_INFO data structure is variable length.
// Whenever code needs to know the size of the EFI_FILE_SYSTEM_INFO data structure, it needs
-// to be the size of the data structure without the VolumeLable field. The following macro
+// to be the size of the data structure without the VolumeLable field. The following macro
// computes this size correctly no matter how big the VolumeLable array is declared.
-// This is required to make the EFI_FILE_SYSTEM_INFO data structure ANSI compilant.
+// This is required to make the EFI_FILE_SYSTEM_INFO data structure ANSI compilant.
//
#define SIZE_OF_EFI_FILE_SYSTEM_INFO EFI_FIELD_OFFSET(EFI_FILE_SYSTEM_INFO,VolumeLabel)
@@ -411,7 +413,7 @@ typedef struct {
EFI_DEVICE_IO Write;
} EFI_IO_ACCESS;
-typedef
+typedef
EFI_STATUS
(EFIAPI *EFI_PCI_DEVICE_PATH) (
IN struct _EFI_DEVICE_IO_INTERFACE *This,
@@ -555,4 +557,47 @@ typedef struct _EFI_UNICODE_COLLATION_INTERFACE {
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;
+
#endif
diff --git sys/boot/efi/include/string16.h sys/boot/efi/include/string16.h
new file mode 100644
index 00000000000..5e4f9c1ef1a
--- /dev/null
+++ sys/boot/efi/include/string16.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 _STRING16_H_
+#define _STRING16_H_
+
+#include <efi.h>
+#include <stddef.h>
+
+/*
+ * These are 16-bit variants of string,h functions for use with EFI code.
+ */
+
+extern size_t strlen16(const CHAR16 *str);
+extern CHAR16* strcpy16(CHAR16 *dst, const CHAR16 *src);
+extern CHAR16* stpcpy16(CHAR16 *dst, const CHAR16 *src);
+extern CHAR16* strcpy_to_16(CHAR16 *dst, const char *src);
+extern char* strcpy_from_16(char *dst, const CHAR16 *src);
+
+#endif
diff --git sys/boot/efi/libefi/Makefile sys/boot/efi/libefi/Makefile
index d9619bef89d..8684403cd11 100644
--- sys/boot/efi/libefi/Makefile
+++ sys/boot/efi/libefi/Makefile
@@ -10,8 +10,8 @@ LIB= efi
INTERNALLIB=
WARNS?= 2
-SRCS= delay.c devpath.c efi_console.c efinet.c efipart.c errno.c \
- handles.c libefi.c
+SRCS= delay.c devpath.c efi_console.c efifs.c efinet.c env.c errno.c \
+ handles.c libefi.c string16.c
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
SRCS+= time.c
diff --git sys/boot/efi/libefi/efifs.c sys/boot/efi/libefi/efifs.c
new file mode 100644
index 00000000000..dd9fb0f0b41
--- /dev/null
+++ sys/boot/efi/libefi/efifs.c
@@ -0,0 +1,464 @@
+/*-
+ * 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 <efi.h>
+#include <efilib.h>
+#include <efiprot.h>
+#include <stand.h>
+#include <stdarg.h>
+#include <bootstrap.h>
+#include <string16.h>
+
+static EFI_GUID FileInfoGUID = EFI_FILE_INFO_ID;;
+static EFI_GUID SimpleFileSystemProtocolGUID = SIMPLE_FILE_SYSTEM_PROTOCOL;
+static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
+static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
+
+static int efifs_open(const char *path, struct open_file *f);
+static int efifs_write(struct open_file *f, void *buf, size_t size, size_t *resid);
+static int efifs_close(struct open_file *f);
+static int efifs_read(struct open_file *f, void *buf, size_t size, size_t *resid);
+static off_t efifs_seek(struct open_file *f, off_t offset, int where);
+static int efifs_stat(struct open_file *f, struct stat *sb);
+static int efifs_readdir(struct open_file *f, struct dirent *d);
+
+static int efifs_dev_init(void);
+static int efifs_dev_strategy(void *, int, daddr_t, size_t, size_t, char *, size_t *);
+static int efifs_dev_open(struct open_file *, ...);
+static int efifs_dev_close(struct open_file *);
+static int efifs_dev_print(int);
+
+struct devsw efifs_dev = {
+ .dv_name = "EFI",
+ .dv_type = DEVT_EFI,
+ .dv_init = efifs_dev_init,
+ .dv_strategy = efifs_dev_strategy,
+ .dv_open = efifs_dev_open,
+ .dv_close = efifs_dev_close,
+ .dv_ioctl = noioctl,
+ .dv_print = efifs_dev_print,
+ .dv_cleanup = NULL
+};
+
+struct fs_ops efifs_fsops = {
+ "EFI",
+ efifs_open,
+ efifs_close,
+ efifs_read,
+ efifs_write,
+ efifs_seek,
+ efifs_stat,
+ efifs_readdir
+};
+
+static int
+efifs_dev_init(void)
+{
+ EFI_HANDLE *hin;
+ EFI_STATUS status;
+ UINTN sz;
+ u_int n, nin, unit;
+ int err;
+
+ sz = 0;
+ hin = NULL;
+ status = BS->LocateHandle(ByProtocol, &SimpleFileSystemProtocolGUID,
+ 0, &sz, 0);
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ hin = (EFI_HANDLE *)malloc(sz);
+ status = BS->LocateHandle(ByProtocol,
+ &SimpleFileSystemProtocolGUID, 0, &sz, hin);
+ if (EFI_ERROR(status))
+ free(hin);
+ }
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ /* Filter handles to only include FreeBSD partitions. */
+ nin = sz / sizeof(EFI_HANDLE);
+ unit = 0;
+
+ for (n = 0; n < nin; n++) {
+ status = BS->OpenProtocol(hin[n], &SimpleFileSystemProtocolGUID,
+ NULL, IH, NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+ if (EFI_ERROR(status))
+ continue;
+
+ efi_handle_update_dev(hin[n], &efifs_dev, unit++, 0);
+ }
+
+ free(hin);
+ return (err);
+}
+
+
+static int
+efifs_dev_print(int verbose)
+{
+ char line[80];
+ EFI_DEVICE_PATH *devpath;
+ EFI_BLOCK_IO *blkio;
+ EFI_HANDLE h, *hin;
+ EFI_STATUS status;
+ u_int unit, n;
+
+ for (unit = 0, h = efi_find_handle(&efifs_dev, 0);
+ h != NULL; h = efi_find_handle(&efifs_dev, ++unit)) {
+ sprintf(line, " %s%d:", efifs_dev.dv_name, unit);
+ pager_output(line);
+ pager_output(" EFI(SIMPLE_FILE_SYSTEM");
+
+ status = BS->HandleProtocol(hin[n], &DevicePathGUID,
+ (void **)&devpath);
+ if (!EFI_ERROR(status)) {
+ pager_output(", DEVICE_PATH");
+ }
+
+ status = BS->HandleProtocol(hin[n], &BlockIoProtocolGUID,
+ (void **)&blkio);
+ if (!EFI_ERROR(status)) {
+ pager_output(", BLOCK_IO");
+ }
+ pager_output(")\n");
+ }
+ return (0);
+}
+
+static int
+efifs_dev_open(struct open_file *f, ...)
+{
+ va_list args;
+ struct devdesc *dev;
+ EFI_FILE_IO_INTERFACE *fsiface;
+ EFI_HANDLE h;
+ EFI_STATUS status;
+
+ va_start(args, f);
+ dev = va_arg(args, struct devdesc*);
+ va_end(args);
+
+ h = efi_find_handle(&efifs_dev, dev->d_unit);
+
+ if (h == NULL)
+ return (EINVAL);
+
+ status = BS->OpenProtocol(h, &SimpleFileSystemProtocolGUID,
+ (void**)&fsiface, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR(status)) {
+ return (efi_status_to_errno(status));
+ }
+
+ dev->d_opendata = fsiface;
+ return (0);
+}
+
+static int
+efifs_dev_close(struct open_file *f)
+{
+ struct devdesc *dev;
+ EFI_HANDLE h;
+ EFI_STATUS status;
+
+ dev = (struct devdesc *)(f->f_devdata);
+ h = efi_find_handle(&efifs_dev, dev->d_unit);
+
+ if (h == NULL)
+ return (EINVAL);
+
+ if (dev->d_opendata == NULL)
+ return (EINVAL);
+
+ status = BS->CloseProtocol(h, &SimpleFileSystemProtocolGUID, IH, NULL);
+
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ dev->d_opendata = NULL;
+ return (0);
+}
+
+
+/* Raw I/O isn't supported on EFI FS devices, as they talk through
+ * SIMPLE_FILE_SYSTEM_INTERFACE.
+ */
+static int
+efifs_dev_strategy(void *devdata __unused, int rw __unused, daddr_t blk __unused,
+ size_t offset, size_t size __unused, char *buf __unused,
+ size_t *rsize __unused)
+{
+ printf("Raw I/O not supported on EFI FS interface\n");
+ return ENOTSUP;
+}
+
+/*
+ * Open a file.
+ */
+static int
+efifs_open(const char *upath, struct open_file *f)
+{
+ struct devdesc *dev;
+ EFI_FILE_IO_INTERFACE *fsiface;
+ EFI_FILE_HANDLE root;
+ EFI_STATUS status;
+ CHAR16 path[strlen(upath) + 1];
+
+ dev = (struct devdesc *)(f->f_devdata);
+ fsiface = dev->d_opendata;
+
+ if (!strcmp(upath, "") || !strcmp(upath, "/")) {
+ return (fsiface->OpenVolume(fsiface,
+ (EFI_FILE_HANDLE*)&(f->f_fsdata)));
+ } else {
+ status = fsiface->OpenVolume(fsiface, &root);
+
+ if (EFI_ERROR(status)) {
+ return (efi_status_to_errno(status));
+ }
+
+ strcpy_to_16(path, upath);
+ status = root->Open(root, (EFI_FILE_HANDLE*)&(f->f_fsdata), path,
+ EFI_FILE_MODE_READ, 0);
+
+ root->Close(root);
+
+ if (EFI_ERROR(status)) {
+ return (efi_status_to_errno(status));
+ }
+
+ return 0;
+ }
+}
+
+static int
+efifs_close(struct open_file *f)
+{
+ EFI_FILE_HANDLE file = (EFI_FILE_HANDLE)f->f_fsdata;
+ EFI_STATUS status;
+
+ status = file->Close(file);
+
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ return (0);
+}
+
+static int
+efifs_read(struct open_file *f, void *start, size_t size, size_t *resid /* out */)
+{
+ EFI_FILE_HANDLE file = (EFI_FILE_HANDLE)f->f_fsdata;
+ UINTN readsize = size;
+ EFI_STATUS status;
+
+ status = file->Read(file, &readsize, start);
+
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ if (resid)
+ *resid = size - readsize;
+
+ return (0);
+}
+
+static int
+efifs_write(struct open_file *f, void *start, size_t size,
+ size_t *resid /* out */)
+{
+ EFI_FILE_HANDLE file = (EFI_FILE_HANDLE)f->f_fsdata;
+ UINTN writesize = size;
+ EFI_STATUS status;
+
+ status = file->Write(file, &writesize, start);
+
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ if (resid)
+ *resid = size - writesize;
+
+ return (0);
+}
+
+static off_t
+efifs_seek(struct open_file *f, off_t offset, int where)
+{
+ EFI_FILE_HANDLE file = (EFI_FILE_HANDLE)f->f_fsdata;
+ UINT64 pos;
+ EFI_STATUS status;
+
+ switch (where) {
+ case SEEK_SET:
+ status = file->SetPosition(file, offset);
+
+ if (status != EFI_SUCCESS) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+
+ break;
+ case SEEK_CUR:
+ status = file->GetPosition(file, &pos);
+
+ if (status != EFI_SUCCESS) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+
+ status = file->SetPosition(file, pos + offset);
+
+ if (status != EFI_SUCCESS) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+
+ break;
+ case SEEK_END:
+ status = file->SetPosition(file, 0xffffffffffffffff);
+
+ if (status != EFI_SUCCESS) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ status = file->GetPosition(file, &pos);
+
+ if (status != EFI_SUCCESS) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+
+ return (pos);
+}
+
+/* SIMPLE_FILE_SYSTEM_PROTOCOL is geared towards FAT, so we can't
+ * reproduce stat with absolute fidelity.
+ */
+static int
+efifs_stat(struct open_file *f, struct stat *sb)
+{
+ EFI_FILE_HANDLE file;
+ UINTN size = 0;
+ EFI_FILE_INFO *finfo;;
+ EFI_STATUS status;
+
+ file = (EFI_FILE_HANDLE)f->f_fsdata;
+ status = file->GetInfo(file, &FileInfoGUID, &size, NULL);
+
+ if (status != EFI_BUFFER_TOO_SMALL) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+
+ finfo = malloc(size);
+ status = file->GetInfo(file, &FileInfoGUID, &size, finfo);
+
+ if (status != EFI_SUCCESS) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+
+ /* We can't properly fill these in... */
+ sb->st_ino = 0;
+ sb->st_nlink = 0;
+ sb->st_uid = 0;
+ sb->st_gid = 0;
+ sb->st_blksize = 512;
+ /* Build the mode field */
+ if (finfo->Attribute & EFI_FILE_DIRECTORY) {
+ sb->st_mode = S_IFDIR;
+ } else {
+ sb->st_mode = S_IFREG;
+ }
+
+ if (finfo->Attribute & EFI_FILE_MODE_READ) {
+ sb->st_mode = S_IRUSR | S_IXUSR | S_IRGRP |
+ S_IXGRP | S_IROTH | S_IXOTH;
+ }
+
+ if (finfo->Attribute & EFI_FILE_MODE_READ) {
+ sb->st_mode = S_IWUSR | S_IWGRP | S_IWOTH;
+ }
+ /* This may or may not be supported, depending on the FS driver */
+ sb->st_blocks = finfo->PhysicalSize / 512;
+ /* These fields we can get right */
+ sb->st_size = finfo->FileSize;
+ sb->st_atime = from_efi_time(&(finfo->LastAccessTime));
+ sb->st_mtime = from_efi_time(&(finfo->ModificationTime));
+ sb->st_ctime = from_efi_time(&(finfo->CreateTime));
+
+ free(finfo);
+
+ return (0);
+}
+
+static int
+efifs_readdir(struct open_file *f, struct dirent *d)
+{
+ EFI_FILE_HANDLE file;
+ UINTN size = 0;
+ EFI_FILE_INFO *finfo;;
+ EFI_STATUS status;
+
+ file = (EFI_FILE_HANDLE)f->f_fsdata;
+ status = file->Read(file, &size, NULL);
+
+ if (status != EFI_BUFFER_TOO_SMALL) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+
+ if (size == 0) {
+ return (ENOENT);
+ }
+
+ finfo = malloc(size);
+ status = file->Read(file, &size, finfo);
+
+ if (status != EFI_SUCCESS) {
+ errno = (efi_status_to_errno(status));
+ return -1;
+ }
+
+ strcpy_from_16(d->d_name, finfo->FileName);
+ d->d_namlen = strlen(d->d_name);
+ d->d_reclen = sizeof(struct dirent);
+ /* We can't faithfully reproduce this due to the limitations
+ * of the SIMPLE_FILE_SYSTEM interface */
+ d->d_fileno = 0;
+
+ free(finfo);
+
+ return (0);
+}
diff --git sys/boot/efi/libefi/errno.c sys/boot/efi/libefi/errno.c
index fac903faf27..0f354c3f3c8 100644
--- sys/boot/efi/libefi/errno.c
+++ sys/boot/efi/libefi/errno.c
@@ -30,6 +30,69 @@ __FBSDID("$FreeBSD$");
#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)
{
diff --git sys/boot/efi/libefi/handles.c sys/boot/efi/libefi/handles.c
index 1e4ef6ffbd5..c118085c1c9 100644
--- sys/boot/efi/libefi/handles.c
+++ sys/boot/efi/libefi/handles.c
@@ -41,21 +41,36 @@ struct entry {
struct entry *entry;
int nentries;
+static int
+get_next_unit(struct devsw *sw)
+{
+ int i, idx;
+
+ for (i = 0, idx = 0; i < nentries; i++) {
+ if (entry[i].dev == sw) {
+ idx++;
+ }
+ }
+
+ return (idx);
+}
+
int
efi_register_handles(struct devsw *sw, EFI_HANDLE *handles,
EFI_HANDLE *aliases, int count)
{
size_t sz;
- int idx, unit;
+ int idx, unit, i;
idx = nentries;
nentries += count;
sz = nentries * sizeof(struct entry);
+ unit = get_next_unit(sw);
entry = (entry == NULL) ? malloc(sz) : realloc(entry, sz);
- for (unit = 0; idx < nentries; idx++, unit++) {
- entry[idx].handle = handles[unit];
+ for (i = 0; idx < nentries; idx++, unit++, i++) {
+ entry[idx].handle = handles[i];
if (aliases != NULL)
- entry[idx].alias = aliases[unit];
+ entry[idx].alias = aliases[i];
else
entry[idx].alias = NULL;
entry[idx].dev = sw;
@@ -64,6 +79,16 @@ efi_register_handles(struct devsw *sw, EFI_HANDLE *handles,
return (0);
}
+int
+efi_register_handle(struct devsw *sw, EFI_HANDLE handle, EFI_HANDLE alias)
+{
+ if (alias == NULL) {
+ return efi_register_handles(sw, &handle, NULL, 1);
+ } else {
+ return efi_register_handles(sw, &handle, &alias, 1);
+ }
+}
+
EFI_HANDLE
efi_find_handle(struct devsw *dev, int unit)
{
@@ -116,3 +141,29 @@ efi_handle_update_dev(EFI_HANDLE h, struct devsw *dev, int unit,
return (ENOENT);
}
+
+int
+efi_handle_remove_dev(EFI_HANDLE h)
+{
+ int idx;
+
+ /* Find the entry */
+ for (idx = 0; idx < nentries; idx++) {
+ if (entry[idx].handle != h)
+ continue;
+ }
+
+ if (idx >= nentries)
+ return (ENOENT);
+ else if (idx == nentries - 1) {
+ nentries--;
+ entry = realloc(entry, nentries * sizeof(struct entry));
+ } else {
+ memcpy(entry + idx, entry + idx + 1,
+ sizeof(struct entry) * (nentries - (idx + 1)));
+ nentries--;
+ entry = realloc(entry, nentries * sizeof(struct entry));
+ }
+
+ return (0);
+}
diff --git sys/boot/efi/libefi/string16.c sys/boot/efi/libefi/string16.c
new file mode 100644
index 00000000000..299d72dd0f0
--- /dev/null
+++ sys/boot/efi/libefi/string16.c
@@ -0,0 +1,88 @@
+/*-
+ * 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 "string16.h"
+#include <stddef.h>
+
+size_t
+strlen16(const CHAR16 *str)
+{
+ size_t i;
+
+ for (i = 0; str[i] != 0; i++);
+
+ return i;
+}
+
+CHAR16 *
+strcpy16(CHAR16 *dst, const CHAR16 *src)
+{
+ stpcpy16(dst, src);
+
+ return (dst);
+}
+
+CHAR16 *
+stpcpy16(CHAR16 *dst, const CHAR16 *src)
+{
+ for (; *src != 0; src++, dst++) {
+ *dst = *src;
+ }
+
+ *dst = *src;
+
+ return dst;
+}
+
+char *
+strcpy_from_16(char *dst, const CHAR16 *src)
+{
+ int i;
+
+ for (i = 0; src[i] != 0; i++) {
+ dst[i] = src[i];
+ }
+
+ dst[i] = 0;
+
+ return (dst);
+}
+
+CHAR16 *
+strcpy_to_16(CHAR16 *dst, const char *src)
+{
+ int i;
+
+ for (i = 0; src[i] != 0; i++) {
+ dst[i] = src[i];
+ }
+
+ dst[i] = 0;
+
+ return (dst);
+}
diff --git sys/boot/efi/libefi/time.c sys/boot/efi/libefi/time.c
index 99831e1cf1a..2df466e57b7 100644
--- sys/boot/efi/libefi/time.c
+++ sys/boot/efi/libefi/time.c
@@ -2,28 +2,28 @@
* Copyright (c) 1999, 2000
* Intel Corporation.
* 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.
- *
+ *
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- *
+ *
* This product includes software developed by Intel Corporation and
* its contributors.
- *
+ *
* 4. Neither the name of Intel Corporation or its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION 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
@@ -35,7 +35,7 @@
* 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/cdefs.h>
@@ -58,6 +58,41 @@ __FBSDID("$FreeBSD$");
#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 @@ efi_time_fini(void)
{
}
-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;
/*
@@ -134,7 +170,7 @@ efi_time(EFI_TIME *ETime)
/*
// UTime should now be set to 00:00:00 on Jan 1 of the file's year.
//
- // Months
+ // Months
*/
UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] * SECSPERDAY);
@@ -170,7 +206,7 @@ efi_time(EFI_TIME *ETime)
*/
UTime += (ETime->TimeZone * 60);
}
-
+
return UTime;
}
@@ -196,7 +232,7 @@ EFI_GetTimeOfDay(
// 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; */
/*
@@ -221,7 +257,7 @@ time(time_t *tloc)
{
struct timeval tv;
EFI_GetTimeOfDay(&tv, 0);
-
+
if (tloc)
*tloc = tv.tv_sec;
return tv.tv_sec;
diff --git sys/boot/efi/loader/Makefile sys/boot/efi/loader/Makefile
index d9d3532014f..300c65b10d9 100644
--- sys/boot/efi/loader/Makefile
+++ sys/boot/efi/loader/Makefile
@@ -50,6 +50,7 @@ CWARNFLAGS.main.c+= -Wno-format
CFLAGS+= -I${.CURDIR}
CFLAGS+= -I${.CURDIR}/arch/${MACHINE}
CFLAGS+= -I${.CURDIR}/../include
+CFLAGS+= -I${.CURDIR}/../drivers
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
@@ -68,6 +69,8 @@ CFLAGS+= -DNO_PCI -DEFI
LIBSTAND= ${.OBJDIR}/../../../../lib/libstand/libstand.a
.endif
+LIBEFI_DRIVERS= ${.OBJDIR}/../drivers/libefi_drivers.a
+
.if !defined(BOOT_HIDE_SERIAL_NUMBERS)
# Export serial numbers, UUID, and asset tag from loader.
CFLAGS+= -DSMBIOS_SERIAL_NUMBERS
@@ -150,9 +153,10 @@ loader.efi: ${PROG}
LIBEFI= ${.OBJDIR}/../libefi/libefi.a
-DPADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND} \
- ${LDSCRIPT}
-LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND}
+DPADD= ${LIBFICL} ${LIBEFI} ${LIBEFI_DRIVERS} ${LIBFDT} ${LIBEFI_FDT} \
+ ${LIBSTAND} ${LDSCRIPT}
+LDADD= ${LIBFICL} ${LIBEFI} ${LIBEFI_DRIVERS} ${LIBFDT} ${LIBEFI_FDT} \
+ ${LIBSTAND}
.include <bsd.prog.mk>
diff --git sys/boot/efi/loader/conf.c sys/boot/efi/loader/conf.c
index 3596a6360c3..56733ffa899 100644
--- sys/boot/efi/loader/conf.c
+++ sys/boot/efi/loader/conf.c
@@ -31,30 +31,22 @@ __FBSDID("$FreeBSD$");
#include <bootstrap.h>
#include <efi.h>
#include <efilib.h>
-#ifdef EFI_ZFS_BOOT
-#include <libzfs.h>
-#endif
+
+#include "efi_drivers.h"
+
+const efi_driver_t *efi_drivers[] = {
+ &fs_driver,
+ NULL
+};
struct devsw *devsw[] = {
- &efipart_dev,
+ &efifs_dev,
&efinet_dev,
-#ifdef EFI_ZFS_BOOT
- &zfs_dev,
-#endif
NULL
};
struct fs_ops *file_system[] = {
-#ifdef EFI_ZFS_BOOT
- &zfs_fsops,
-#endif
- &dosfs_fsops,
- &ufs_fsops,
- &cd9660_fsops,
- &tftp_fsops,
- &nfs_fsops,
- &gzipfs_fsops,
- &bzipfs_fsops,
+ &efifs_fsops,
NULL
};
diff --git sys/boot/efi/loader/loader_efi.h sys/boot/efi/loader/loader_efi.h
index ee7c4bb72eb..dbd36bfb4ca 100644
--- sys/boot/efi/loader/loader_efi.h
+++ sys/boot/efi/loader/loader_efi.h
@@ -33,6 +33,10 @@
#include <stand.h>
+#include "efi_drivers.h"
+
+extern const efi_driver_t *efi_drivers[];
+
int efi_autoload(void);
int efi_getdev(void **vdev, const char *devspec, const char **path);
diff --git sys/boot/efi/loader/main.c sys/boot/efi/loader/main.c
index b97f2afb851..42e3ebe1830 100644
--- sys/boot/efi/loader/main.c
+++ sys/boot/efi/loader/main.c
@@ -87,10 +87,6 @@ EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_GUID fdtdtb = FDT_TABLE_GUID;
EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
-#ifdef EFI_ZFS_BOOT
-static void efi_zfs_probe(void);
-#endif
-
/*
* cpy8to16 copies a traditional C string into a CHAR16 string and
* 0 terminates it. len is the size of *dst in bytes.
@@ -125,7 +121,7 @@ has_keyboard(void)
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.
@@ -182,7 +178,7 @@ has_keyboard(void)
} 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 */
@@ -263,10 +259,6 @@ main(int argc, CHAR16 *argv[])
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
/* Init the time source */
efi_time_init();
@@ -391,6 +383,10 @@ main(int argc, CHAR16 *argv[])
/*
* March through the device switch probing for things.
*/
+ for (i = 0; efi_drivers[i] != NULL; i++)
+ if (efi_drivers[i]->init != NULL)
+ (efi_drivers[i]->init)();
+
for (i = 0; devsw[i] != NULL; i++)
if (devsw[i]->dv_init != NULL)
(devsw[i]->dv_init)();
@@ -427,6 +423,7 @@ main(int argc, CHAR16 *argv[])
if (find_currdev(img, &dev, &unit, &pool_guid) != 0)
return (EFI_NOT_FOUND);
+ printf("Found efi device under %s\n", dev->dv_name);
switch (dev->dv_type) {
#ifdef EFI_ZFS_BOOT
case DEVT_ZFS: {
@@ -1093,23 +1090,3 @@ command_fdt(int argc, char *argv[])
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
#endif
-
-#ifdef EFI_ZFS_BOOT
-static void
-efi_zfs_probe(void)
-{
- EFI_HANDLE h;
- u_int unit;
- int i;
- char dname[SPECNAMELEN + 1];
- uint64_t guid;
-
- unit = 0;
- h = efi_find_handle(&efipart_dev, 0);
- for (i = 0; h != NULL; h = efi_find_handle(&efipart_dev, ++i)) {
- snprintf(dname, sizeof(dname), "%s%d:", efipart_dev.dv_name, i);
- if (zfs_probe_dev(dname, &guid) == 0)
- (void)efi_handle_update_dev(h, &zfs_dev, unit++, guid);
- }
-}
-#endif
More information about the freebsd-amd64
mailing list