Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 08 Jun 2015 18:59:36 -0400
From:      Eric McCorkle <eric@metricspace.net>
To:        freebsd-hackers@freebsd.org
Subject:   Re: EFI ZFS loader successful load and boot
Message-ID:  <55761E58.6040704@metricspace.net>
In-Reply-To: <98598C0A-D09A-4BC7-A15C-5422BBA2EE4C@gmail.com>
References:  <5560F4FE.4030502@metricspace.net> <5560F743.9000507@metricspace.net> <7CD9D028-8BCE-4361-966B-140642BAE341@metricspace.net> <98598C0A-D09A-4BC7-A15C-5422BBA2EE4C@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
--9mXtQcxIOTeBwJJoa4u3PEkLG2JCiT7t8
Content-Type: multipart/mixed;
 boundary="------------040508010102090007040903"

This is a multi-part message in MIME format.
--------------040508010102090007040903
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

OK, finally got time to turn the knobs.  This patch should make it
through a buildworld.

I will at some point add functionality to boot1 to actually check the
partition type GUIDs.

That aside, this is ready for testing, and I've been EFI-booting a ZFS
partition from GRUB using this patch for a while now.

On 05/26/2015 10:22 AM, Garrett Cooper wrote:
>=20
>> On May 26, 2015, at 05:34, Eric McCorkle <eric@metricspace.net> wrote:=

>>
>> Updates: with a new kernel, and the vt terminal, this works fine.=20
>>
>> Unfortunately, the patch doesn't seem to work with a buildworld build =
(I was doing make from within the directories). This is related to a hack=
 I do of copying zfs.c into the efi loader directory so it can be built w=
ith fPIC. The build system seems to get tripped up in mkdep as a result. =

>>
>> Could someone with more knowledge of the build system give me some poi=
nters here? Otherwise, is all set for testing.
>=20
> DPSRCS/CLEANFILES are probably the knobs you're looking for...
> _______________________________________________
> freebsd-hackers@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.o=
rg"
>=20

--------------040508010102090007040903
Content-Type: text/x-patch;
 name="zfsefi.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
 filename="zfsefi.diff"

Index: sys/boot/efi/boot1/Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/boot1/Makefile	(revision 283525)
+++ sys/boot/efi/boot1/Makefile	(working copy)
@@ -13,7 +13,7 @@
 INTERNALPROG=3D
=20
 # architecture-specific loader code
-SRCS=3D	boot1.c self_reloc.c start.S
+SRCS=3D	boot1.c self_reloc.c start.S ufs_module.c zfs_module.c
=20
 CFLAGS+=3D	-I.
 CFLAGS+=3D	-I${.CURDIR}/../include
@@ -20,6 +20,8 @@
 CFLAGS+=3D	-I${.CURDIR}/../include/${MACHINE}
 CFLAGS+=3D	-I${.CURDIR}/../../../contrib/dev/acpica/include
 CFLAGS+=3D	-I${.CURDIR}/../../..
+CFLAGS+=3D	-I${.CURDIR}/../../zfs/
+CFLAGS+=3D	-I${.CURDIR}/../../../cddl/boot/zfs/
=20
 # Always add MI sources and REGULAR efi loader bits
 .PATH:		${.CURDIR}/../loader/arch/${MACHINE}
Index: sys/boot/efi/boot1/boot1.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/boot1/boot1.c	(revision 283525)
+++ sys/boot/efi/boot1/boot1.c	(working copy)
@@ -5,6 +5,8 @@
  * All rights reserved.
  * Copyright (c) 2014 Nathan Whitehorn
  * All rights reserved.
+ * Copyright (c) 2014 Eric McCorkle
+ * All rights reverved.
  *
  * Redistribution and use in source and binary forms are freely
  * permitted provided that the above copyright notice and this
@@ -21,7 +23,6 @@
 __FBSDID("$FreeBSD$");
=20
 #include <sys/param.h>
-#include <sys/dirent.h>
 #include <machine/elf.h>
 #include <machine/stdarg.h>
=20
@@ -28,6 +29,8 @@
 #include <efi.h>
 #include <eficonsctl.h>
=20
+#include "boot_module.h"
+
 #define _PATH_LOADER	"/boot/loader.efi"
 #define _PATH_KERNEL	"/boot/kernel/kernel"
=20
@@ -41,14 +44,20 @@
 	u_int	sp_size;
 };
=20
+static const boot_module_t* const boot_modules[] =3D
+{
+#ifdef ZFS_EFI_BOOT
+        &zfs_module,
+#endif
+#ifdef UFS_EFI_BOOT
+        &ufs_module
+#endif
+};
+
+#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*))=

+
 static const char digits[] =3D "0123456789abcdef";
=20
-static void panic(const char *fmt, ...) __dead2;
-static int printf(const char *fmt, ...);
-static int putchar(char c, void *arg);
-static int vprintf(const char *fmt, va_list ap);
-static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);=

-
 static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_li=
st ap);
 static int __putc(char c, void *arg);
 static int __puts(const char *s, putc_func_t *putc, void *arg);
@@ -62,9 +71,80 @@
 static EFI_SYSTEM_TABLE *systab;
 static EFI_HANDLE *image;
=20
-static void
-bcopy(const void *src, void *dst, size_t len)
+
+void* Malloc(size_t len, const char* file, int line)
 {
+        void* out;
+        if (systab->BootServices->AllocatePool(EfiLoaderData,
+                                               len, &out) !=3D
+            EFI_SUCCESS) {
+                printf("Can't allocate memory pool\n");
+                return NULL;
+        }
+        return out;
+}
+
+char* strcpy(char* dst, const char* src) {
+        for(int i =3D 0; src[i]; i++)
+                dst[i] =3D src[i];
+
+        return dst;
+}
+
+char* strchr(const char* s, int c) {
+        for(int i =3D 0; s[i]; i++)
+                if (s[i] =3D=3D c)
+                        return (char*)(s + i);
+
+        return NULL;
+}
+
+int strncmp(const char *a, const char *b, size_t len)
+{
+        for (int i =3D 0; i < len; i++)
+                if(a[i] =3D=3D '\0' && b[i] =3D=3D '\0') {
+                        return 0;
+                } else if(a[i] < b[i]) {
+                        return -1;
+                } else if(a[i] > b[i]) {
+                        return 1;
+                }
+
+        return 0;
+}
+
+char* strdup(const char* s) {
+        int len;
+
+        for(len =3D 1; s[len]; len++);
+
+        char* out =3D malloc(len);
+
+        for(int i =3D 0; i < len; i++)
+                out[i] =3D s[i];
+
+        return out;
+}
+
+int bcmp(const void *a, const void *b, size_t len)
+{
+        const char *sa =3D a;
+        const char *sb =3D b;
+
+        for (int i =3D 0; i < len; i++)
+                if(sa[i] !=3D sb[i])
+                        return 1;
+
+        return 0;
+}
+
+int memcmp(const void *a, const void *b, size_t len)
+{
+        return bcmp(a, b, len);
+}
+
+void bcopy(const void *src, void *dst, size_t len)
+{
 	const char *s =3D src;
 	char *d =3D dst;
=20
@@ -72,23 +152,24 @@
 		*d++ =3D *s++;
 }
=20
-static void
-memcpy(void *dst, const void *src, size_t len)
+void* memcpy(void *dst, const void *src, size_t len)
 {
 	bcopy(src, dst, len);
+        return dst;
 }
=20
-static void
-bzero(void *b, size_t len)
+
+void* memset(void *b, int val, size_t len)
 {
 	char *p =3D b;
=20
 	while (len-- !=3D 0)
-		*p++ =3D 0;
+		*p++ =3D val;
+
+        return b;
 }
=20
-static int
-strcmp(const char *s1, const char *s2)
+int strcmp(const char *s1, const char *s2)
 {
 	for (; *s1 =3D=3D *s2 && *s1; s1++, s2++)
 		;
@@ -95,30 +176,99 @@
 	return ((u_char)*s1 - (u_char)*s2);
 }
=20
+int putchr(char c, void *arg)
+{
+	CHAR16 buf[2];
+
+	if (c =3D=3D '\n') {
+		buf[0] =3D '\r';
+		buf[1] =3D 0;
+		systab->ConOut->OutputString(systab->ConOut, buf);
+	}
+	buf[0] =3D c;
+	buf[1] =3D 0;
+        systab->ConOut->OutputString(systab->ConOut, buf);
+	return (1);
+}
+
 static EFI_GUID BlockIoProtocolGUID =3D BLOCK_IO_PROTOCOL;
 static EFI_GUID DevicePathGUID =3D DEVICE_PATH_PROTOCOL;
+static EFI_GUID ConsoleControlGUID =3D EFI_CONSOLE_CONTROL_PROTOCOL_GUID=
;
 static EFI_GUID LoadedImageGUID =3D LOADED_IMAGE_PROTOCOL;
-static EFI_GUID ConsoleControlGUID =3D EFI_CONSOLE_CONTROL_PROTOCOL_GUID=
;
=20
-static EFI_BLOCK_IO *bootdev;
-static EFI_DEVICE_PATH *bootdevpath;
-static EFI_HANDLE *bootdevhandle;
+#define MAX_DEVS 128
=20
-EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
+void try_load(const boot_module_t* const mod,
+              const dev_info_t devs[],
+              size_t ndevs)
 {
-	EFI_HANDLE handles[128];
+        int idx;
+        size_t bufsize;
+        void* const buffer =3D mod->load(devs, ndevs, _PATH_LOADER, &idx=
, &bufsize);
+        EFI_HANDLE loaderhandle;
+        EFI_LOADED_IMAGE *loaded_image;
+
+        if (NULL =3D=3D buffer) {
+                printf("Could not load file\n");
+                return;
+        }
+        //printf("Loaded file %s, image at %p\n"
+        //       "Attempting to load as bootable image...",
+        //       _PATH_LOADER, image);
+        if (systab->BootServices->LoadImage(TRUE, image, devs[idx].devpa=
th,
+                                            buffer, bufsize, &loaderhand=
le) !=3D
+            EFI_SUCCESS) {
+                //printf("failed\n");
+                return;
+        }
+        //printf("success\n"
+        //       "Preparing to execute image...");
+
+        if (systab->BootServices->HandleProtocol(loaderhandle,
+                                                 &LoadedImageGUID,
+                                                 (VOID**)&loaded_image) =
!=3D
+            EFI_SUCCESS) {
+                //printf("failed\n");
+                return;
+        }
+
+        //printf("success\n");
+
+        loaded_image->DeviceHandle =3D  devs[idx].devhandle;
+
+	//printf("Image prepared, attempting to execute\n");
+        // XXX Set up command args first
+        if (systab->BootServices->StartImage(loaderhandle, NULL, NULL) !=
=3D
+            EFI_SUCCESS) {
+                //printf("Failed to execute loader\n");
+                return;
+        }
+        //printf("Shouldn't be here!\n");
+}
+
+void efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
+{
+	EFI_HANDLE handles[MAX_DEVS];
+        dev_info_t module_devs[NUM_BOOT_MODULES][MAX_DEVS];
+        size_t dev_offsets[NUM_BOOT_MODULES];
 	EFI_BLOCK_IO *blkio;
-	UINTN i, nparts =3D sizeof(handles), cols, rows, max_dim, best_mode;
+	UINTN nparts =3D sizeof(handles);
 	EFI_STATUS status;
 	EFI_DEVICE_PATH *devpath;
 	EFI_BOOT_SERVICES *BS;
 	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl =3D NULL;
 	SIMPLE_TEXT_OUTPUT_INTERFACE *conout =3D NULL;
-	char *path =3D _PATH_LOADER;
=20
+        // Basic initialization
 	systab =3D Xsystab;
 	image =3D Ximage;
=20
+        for(int i =3D 0; i < NUM_BOOT_MODULES; i++)
+        {
+                dev_offsets[i] =3D 0;
+        }
+
+        // Set up the console, so printf works.
 	BS =3D systab->BootServices;
 	status =3D BS->LocateProtocol(&ConsoleControlGUID, NULL,
 	    (VOID **)&ConsoleControl);
@@ -128,10 +278,14 @@
 	/*
 	 * Reset the console and find the best text mode.
 	 */
+        UINTN max_dim;
+        UINTN best_mode;
+        UINTN cols;
+        UINTN rows;
 	conout =3D systab->ConOut;
 	conout->Reset(conout, TRUE);
 	max_dim =3D best_mode =3D 0;
-	for (i =3D 0; ; i++) {
+	for (int i =3D 0; ; i++) {
 		status =3D conout->QueryMode(conout, i,
 		    &cols, &rows);
 		if (EFI_ERROR(status))
@@ -141,6 +295,7 @@
 			best_mode =3D i;
 		}
 	}
+
 	if (max_dim > 0)
 		conout->SetMode(conout, best_mode);
 	conout->EnableCursor(conout, TRUE);
@@ -147,206 +302,94 @@
 	conout->ClearScreen(conout);
=20
 	printf("\n"
-	       ">> FreeBSD EFI boot block\n");
-	printf("   Loader path: %s\n", path);
+	       ">> FreeBSD ZFS-enabled EFI boot block\n");
+	printf("   Loader path: %s\n\n", _PATH_LOADER);
=20
+	printf("   Initializing modules:");
+        for(int i =3D 0; i < NUM_BOOT_MODULES; i++)
+        {
+                if (NULL !=3D boot_modules[i])
+                {
+                        printf(" %s", boot_modules[i]->name);
+                        boot_modules[i]->init(image, systab, BS);
+                }
+        }
+        putchr('\n', NULL);
+
+        // Get all the device handles
 	status =3D systab->BootServices->LocateHandle(ByProtocol,
 	    &BlockIoProtocolGUID, NULL, &nparts, handles);
 	nparts /=3D sizeof(handles[0]);
+	//printf("   Scanning %lu device handles\n", nparts);
=20
-	for (i =3D 0; i < nparts; i++) {
+        // Scan all partitions, probing with all modules.
+	for (int i =3D 0; i < nparts; i++) {
+                dev_info_t devinfo;
+
+                // Figure out if we're dealing with an actual partition
 		status =3D systab->BootServices->HandleProtocol(handles[i],
 		    &DevicePathGUID, (void **)&devpath);
-		if (EFI_ERROR(status))
+		if (EFI_ERROR(status)) {
+                        //printf("        Not a device path protocol\n")=
;
 			continue;
+                }
=20
-		while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+		while (!IsDevicePathEnd(NextDevicePathNode(devpath))) {
+                        //printf("        Advancing to next device\n");
 			devpath =3D NextDevicePathNode(devpath);
+                }
=20
 		status =3D systab->BootServices->HandleProtocol(handles[i],
 		    &BlockIoProtocolGUID, (void **)&blkio);
-		if (EFI_ERROR(status))
+		if (EFI_ERROR(status)) {
+                        //printf("        Not a block device\n");
 			continue;
+                }
=20
-		if (!blkio->Media->LogicalPartition)
+		if (!blkio->Media->LogicalPartition) {
+                        //printf("        Logical partition\n");
 			continue;
+                }
=20
-		if (domount(devpath, blkio, 1) >=3D 0)
-			break;
-	}
+                // Setup devinfo
+                devinfo.dev =3D blkio;
+                devinfo.devpath =3D devpath;
+                devinfo.devhandle =3D handles[i];
+                devinfo.devdata =3D NULL;
=20
-	if (i =3D=3D nparts)
-		panic("No bootable partition found");
-
-	bootdevhandle =3D handles[i];
-	load(path);
-
-	panic("Load failed");
-
-	return EFI_SUCCESS;
-}
-
-static int
-dskread(void *buf, u_int64_t lba, int nblk)
-{
-	EFI_STATUS status;
-	int size;
-
-	lba =3D lba / (bootdev->Media->BlockSize / DEV_BSIZE);
-	size =3D nblk * DEV_BSIZE;
-	status =3D bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
-	    size, buf);
-
-	if (EFI_ERROR(status))
-		return (-1);
-
-	return (0);
-}
-
-#include "ufsread.c"
-
-static ssize_t
-fsstat(ufs_ino_t inode)
-{
-#ifndef UFS2_ONLY
-	static struct ufs1_dinode dp1;
-	ufs1_daddr_t addr1;
-#endif
-#ifndef UFS1_ONLY
-	static struct ufs2_dinode dp2;
-#endif
-	static struct fs fs;
-	static ufs_ino_t inomap;
-	char *blkbuf;
-	void *indbuf;
-	size_t n, nb, size, off, vboff;
-	ufs_lbn_t lbn;
-	ufs2_daddr_t addr2, vbaddr;
-	static ufs2_daddr_t blkmap, indmap;
-	u_int u;
-
-	blkbuf =3D dmadat->blkbuf;
-	indbuf =3D dmadat->indbuf;
-	if (!dsk_meta) {
-		inomap =3D 0;
-		for (n =3D 0; sblock_try[n] !=3D -1; n++) {
-			if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
-			    SBLOCKSIZE / DEV_BSIZE))
-				return -1;
-			memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
-			if ((
-#if defined(UFS1_ONLY)
-			    fs.fs_magic =3D=3D FS_UFS1_MAGIC
-#elif defined(UFS2_ONLY)
-			    (fs.fs_magic =3D=3D FS_UFS2_MAGIC &&
-			    fs.fs_sblockloc =3D=3D sblock_try[n])
-#else
-			    fs.fs_magic =3D=3D FS_UFS1_MAGIC ||
-			    (fs.fs_magic =3D=3D FS_UFS2_MAGIC &&
-			    fs.fs_sblockloc =3D=3D sblock_try[n])
-#endif
-			    ) &&
-			    fs.fs_bsize <=3D MAXBSIZE &&
-			    fs.fs_bsize >=3D sizeof(struct fs))
-				break;
-		}
-		if (sblock_try[n] =3D=3D -1) {
-			printf("Not ufs\n");
-			return -1;
-		}
-		dsk_meta++;
-	} else
-		memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
-	if (!inode)
-		return 0;
-	if (inomap !=3D inode) {
-		n =3D IPERVBLK(&fs);
-		if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
-			return -1;
-		n =3D INO_TO_VBO(n, inode);
-#if defined(UFS1_ONLY)
-		memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
-		    sizeof(struct ufs1_dinode));
-#elif defined(UFS2_ONLY)
-		memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
-		    sizeof(struct ufs2_dinode));
-#else
-		if (fs.fs_magic =3D=3D FS_UFS1_MAGIC)
-			memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
-			    sizeof(struct ufs1_dinode));
-		else
-			memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
-			    sizeof(struct ufs2_dinode));
-#endif
-		inomap =3D inode;
-		fs_off =3D 0;
-		blkmap =3D indmap =3D 0;
+                // Run through each module, see if it can load this part=
ition
+                for (int j =3D 0; j < NUM_BOOT_MODULES; j++ )
+                {
+                        if (NULL !=3D boot_modules[j] &&
+                            boot_modules[j]->probe(&devinfo))
+                        {
+                                // If it can, save it to the device list=
 for
+                                // that module
+                                module_devs[j][dev_offsets[j]++] =3D dev=
info;
+                        }
+                }
 	}
-	size =3D DIP(di_size);
-	n =3D size - fs_off;
-	return (n);
-}
=20
-static struct dmadat __dmadat;
+        // Select a partition to boot.  We do this by trying each
+        // module in order.
+        for (int i =3D 0; i < NUM_BOOT_MODULES; i++)
+        {
+                if (NULL !=3D boot_modules[i])
+                {
+                        //printf("   Trying to load from %lu %s partitio=
ns\n",
+                        //       dev_offsets[i], boot_modules[i]->name);=

+                        try_load(boot_modules[i], module_devs[i],
+                                 dev_offsets[i]);
+                        //printf("   Failed\n");
+                }
+        }
=20
-static int
-domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
-{
-
-	dmadat =3D &__dmadat;
-	bootdev =3D blkio;
-	bootdevpath =3D device;
-	if (fsread(0, NULL, 0)) {
-		if (!quiet)
-			printf("domount: can't read superblock\n");
-		return (-1);
-	}
-	if (!quiet)
-		printf("Succesfully mounted UFS filesystem\n");
-	return (0);
+        // If we get here, we're out of luck...
+        panic("No bootable partitions found!");
 }
=20
-static void
-load(const char *fname)
+void panic(const char *fmt, ...)
 {
-	ufs_ino_t ino;
-	EFI_STATUS status;
-	EFI_HANDLE loaderhandle;
-	EFI_LOADED_IMAGE *loaded_image;
-	void *buffer;
-	size_t bufsize;
-
-	if ((ino =3D lookup(fname)) =3D=3D 0) {
-		printf("File %s not found\n", fname);
-		return;
-	}
-
-	bufsize =3D fsstat(ino);
-	status =3D systab->BootServices->AllocatePool(EfiLoaderData,
-	    bufsize, &buffer);
-	fsread(ino, buffer, bufsize);
-
-	/* XXX: For secure boot, we need our own loader here */
-	status =3D systab->BootServices->LoadImage(TRUE, image, bootdevpath,
-	    buffer, bufsize, &loaderhandle);
-	if (EFI_ERROR(status))
-		printf("LoadImage failed with error %lx\n", status);
-
-	status =3D systab->BootServices->HandleProtocol(loaderhandle,
-	    &LoadedImageGUID, (VOID**)&loaded_image);
-	if (EFI_ERROR(status))
-		printf("HandleProtocol failed with error %lx\n", status);
-
-	loaded_image->DeviceHandle =3D bootdevhandle;
-
-	status =3D systab->BootServices->StartImage(loaderhandle, NULL, NULL);
-	if (EFI_ERROR(status))
-		printf("StartImage failed with error %lx\n", status);
-}
-
-static void
-panic(const char *fmt, ...)
-{
 	char buf[128];
 	va_list ap;
=20
@@ -358,50 +401,25 @@
 	while (1) {}
 }
=20
-static int
-printf(const char *fmt, ...)
+int printf(const char *fmt, ...)
 {
 	va_list ap;
 	int ret;
=20
-	/* Don't annoy the user as we probe for partitions */
-	if (strcmp(fmt,"Not ufs\n") =3D=3D 0)
-		return 0;
=20
 	va_start(ap, fmt);
-	ret =3D vprintf(fmt, ap);
+	ret =3D __printf(fmt, putchr, 0, ap);
 	va_end(ap);
 	return (ret);
 }
=20
-static int
-putchar(char c, void *arg)
+void vprintf(const char *fmt, va_list ap)
 {
-	CHAR16 buf[2];
-
-	if (c =3D=3D '\n') {
-		buf[0] =3D '\r';
-		buf[1] =3D 0;
-		systab->ConOut->OutputString(systab->ConOut, buf);
-	}
-	buf[0] =3D c;
-	buf[1] =3D 0;
-	systab->ConOut->OutputString(systab->ConOut, buf);
-	return (1);
+	__printf(fmt, putchr, 0, ap);
 }
=20
-static int
-vprintf(const char *fmt, va_list ap)
+int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
 {
-	int ret;
-
-	ret =3D __printf(fmt, putchar, 0, ap);
-	return (ret);
-}
-
-static int
-vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
-{
 	struct sp_data sp;
 	int ret;
=20
Index: sys/boot/efi/boot1/boot_module.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/boot1/boot_module.h	(revision 0)
+++ sys/boot/efi/boot1/boot_module.h	(working copy)
@@ -0,0 +1,60 @@
+#ifndef _BOOT_MODULE_H_
+#define _BOOT_MODULE_H_
+
+#include <stdbool.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <eficonsctl.h>
+
+#define UFS_EFI_BOOT 1
+#define ZFS_EFI_BOOT 1
+
+// EFI device info
+typedef struct dev_info_t
+{
+      EFI_BLOCK_IO *dev;
+      EFI_DEVICE_PATH *devpath;
+      EFI_HANDLE *devhandle;
+      void *devdata;
+} 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* const name;
+
+        // Initialize the module.
+        void (* const init)(EFI_HANDLE image,
+                            EFI_SYSTEM_TABLE* systab,
+                            EFI_BOOT_SERVICES *bootsrv);
+
+        // Check to see if curr_dev is a device that this module can han=
dle.
+        bool (* const probe)(dev_info_t* dev);
+
+        // Select the best out of a set of devices that probe indicated =
were
+        // loadable, and load it.
+        void* (* const load)(const dev_info_t devs[],
+                             size_t ndevs,
+                             const char* loader_path,
+                             int* idxref,
+                             size_t* bufsizeref);
+} boot_module_t;
+
+// Standard boot modules
+#ifdef UFS_EFI_BOOT
+extern const boot_module_t ufs_module;
+#endif
+#ifdef ZFS_EFI_BOOT
+extern const boot_module_t zfs_module;
+#endif
+
+// Functions available to modules
+extern int strcmp(const char *s1, const char *s2);
+extern void bcopy(const void *src, void *dst, size_t len);
+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);=

+
+#endif

Property changes on: sys/boot/efi/boot1/boot_module.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=3D%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: sys/boot/efi/boot1/ufs_module.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/boot1/ufs_module.c	(revision 0)
+++ sys/boot/efi/boot1/ufs_module.c	(working copy)
@@ -0,0 +1,210 @@
+/*-
+ * 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 are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+#include <stdarg.h>
+#include <stdbool.h>
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+
+#include <efi.h>
+
+#include "boot_module.h"
+
+static EFI_HANDLE image;
+static EFI_SYSTEM_TABLE* systab;
+static EFI_BOOT_SERVICES *bootsrv;
+static dev_info_t devinfo;
+static EFI_GUID LoadedImageGUID =3D LOADED_IMAGE_PROTOCOL;
+
+static int
+dskread(void *buf, u_int64_t lba, int nblk)
+{
+	EFI_STATUS status;
+	int size;
+
+	lba =3D lba / (devinfo.dev->Media->BlockSize / DEV_BSIZE);
+	size =3D nblk * DEV_BSIZE;
+	status =3D devinfo.dev->ReadBlocks(devinfo.dev,
+                                         devinfo.dev->Media->MediaId, lb=
a,
+	    size, buf);
+
+	if (EFI_ERROR(status))
+		return (-1);
+
+	return (0);
+}
+
+#include "ufsread.c"
+
+static ssize_t
+fsstat(ufs_ino_t inode)
+{
+#ifndef UFS2_ONLY
+	static struct ufs1_dinode dp1;
+	ufs1_daddr_t addr1;
+#endif
+#ifndef UFS1_ONLY
+	static struct ufs2_dinode dp2;
+#endif
+	static struct fs fs;
+	static ufs_ino_t inomap;
+	char *blkbuf;
+	void *indbuf;
+	size_t n, nb, size, off, vboff;
+	ufs_lbn_t lbn;
+	ufs2_daddr_t addr2, vbaddr;
+	static ufs2_daddr_t blkmap, indmap;
+	u_int u;
+
+	blkbuf =3D dmadat->blkbuf;
+	indbuf =3D dmadat->indbuf;
+	if (!dsk_meta) {
+		inomap =3D 0;
+		for (n =3D 0; sblock_try[n] !=3D -1; n++) {
+			if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
+			    SBLOCKSIZE / DEV_BSIZE))
+				return -1;
+			memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
+			if ((
+#if defined(UFS1_ONLY)
+			    fs.fs_magic =3D=3D FS_UFS1_MAGIC
+#elif defined(UFS2_ONLY)
+			    (fs.fs_magic =3D=3D FS_UFS2_MAGIC &&
+			    fs.fs_sblockloc =3D=3D sblock_try[n])
+#else
+			    fs.fs_magic =3D=3D FS_UFS1_MAGIC ||
+			    (fs.fs_magic =3D=3D FS_UFS2_MAGIC &&
+			    fs.fs_sblockloc =3D=3D sblock_try[n])
+#endif
+			    ) &&
+			    fs.fs_bsize <=3D MAXBSIZE &&
+			    fs.fs_bsize >=3D sizeof(struct fs))
+				break;
+		}
+		if (sblock_try[n] =3D=3D -1) {
+			return -1;
+		}
+		dsk_meta++;
+	} else
+		memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
+	if (!inode)
+		return 0;
+	if (inomap !=3D inode) {
+		n =3D IPERVBLK(&fs);
+		if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
+			return -1;
+		n =3D INO_TO_VBO(n, inode);
+#if defined(UFS1_ONLY)
+		memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
+		    sizeof(struct ufs1_dinode));
+#elif defined(UFS2_ONLY)
+		memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
+		    sizeof(struct ufs2_dinode));
+#else
+		if (fs.fs_magic =3D=3D FS_UFS1_MAGIC)
+			memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
+			    sizeof(struct ufs1_dinode));
+		else
+			memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
+			    sizeof(struct ufs2_dinode));
+#endif
+		inomap =3D inode;
+		fs_off =3D 0;
+		blkmap =3D indmap =3D 0;
+	}
+	size =3D DIP(di_size);
+	n =3D size - fs_off;
+	return (n);
+}
+
+static struct dmadat __dmadat;
+
+static bool
+probe(dev_info_t* const dev)
+{
+        devinfo =3D *dev;
+	dmadat =3D &__dmadat;
+	if (fsread(0, NULL, 0)) {
+		return 0;
+	}
+	return 1;
+}
+
+static void*
+try_load(const dev_info_t dev,
+         const char* const loader_path,
+         size_t* const bufsizeref)
+{
+	ufs_ino_t ino;
+	EFI_STATUS status;
+	void *buffer;
+	size_t bufsize;
+
+        devinfo =3D dev;
+	if ((ino =3D lookup(loader_path)) =3D=3D 0) {
+		printf("File %s not found\n", loader_path);
+		return NULL;
+	}
+
+	bufsize =3D fsstat(ino);
+        *bufsizeref =3D bufsize;
+	status =3D systab->BootServices->AllocatePool(EfiLoaderData,
+	    bufsize, &buffer);
+	fsread(ino, buffer, bufsize);
+        return buffer;
+}
+
+static void*
+load(const dev_info_t devs[],
+     const size_t ndevs,
+     const char* const loader_path,
+     int* const idxref,
+     size_t* const bufsizeref)
+{
+        for(int i =3D 0; i < ndevs; i++)
+        {
+               void* const out =3D try_load(devs[i], loader_path, bufsiz=
eref);
+               if (out !=3D NULL)
+               {
+                       *idxref =3D i;
+                       return out;
+               }
+        }
+        return NULL;
+}
+
+
+static void init(EFI_HANDLE xImage,
+                 EFI_SYSTEM_TABLE* xSystab,
+                 EFI_BOOT_SERVICES * xBootsrv)
+{
+        image =3D xImage;
+        systab =3D xSystab;
+        bootsrv =3D xBootsrv;
+}
+
+const boot_module_t ufs_module =3D
+{
+        .name =3D "UFS",
+        .init =3D init,
+        .probe =3D probe,
+        .load =3D load
+};

Property changes on: sys/boot/efi/boot1/ufs_module.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=3D%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: sys/boot/efi/boot1/zfs_module.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/boot1/zfs_module.c	(revision 0)
+++ sys/boot/efi/boot1/zfs_module.c	(working copy)
@@ -0,0 +1,201 @@
+/* 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.
+ *
+ * 3. Neither the name of the author nor the names of any contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
+ */
+#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"
+
+#define PATH_CONFIG "/boot/config"
+#define PATH_DOTCONFIG "/boot/.config"
+
+static EFI_HANDLE image;
+static EFI_SYSTEM_TABLE* systab;
+static EFI_BOOT_SERVICES *bootsrv;
+
+static int
+vdev_read(vdev_t * const vdev,
+          void * const priv,
+          const off_t off,
+          void * const buf,
+          const size_t bytes)
+{
+        const dev_info_t* const devinfo =3D (const dev_info_t*) priv;
+        const off_t lba =3D off / devinfo->dev->Media->BlockSize;
+	const EFI_STATUS status =3D
+          devinfo->dev->ReadBlocks(devinfo->dev,
+                                   devinfo->dev->Media->MediaId,
+                                   lba, bytes, buf);
+	if (EFI_ERROR(status))
+		return (-1);
+
+	return (0);
+}
+
+static bool probe(dev_info_t* const dev)
+{
+        spa_t* spa;
+        int result =3D vdev_probe(vdev_read, dev, &spa);
+        dev->devdata =3D spa;
+
+        return result =3D=3D 0;
+}
+
+static void* try_load(const dev_info_t devinfo,
+                      const char* const loader_path,
+                      size_t* const bufsizeref)
+{
+        spa_t *spa =3D devinfo.devdata;
+        struct zfsmount zfsmount;
+        dnode_phys_t dn;
+        bool autoboot =3D true;
+
+        if (zfs_spa_init(spa) !=3D 0) {
+                // Mount failed.  Don't report this loudly
+                return NULL;
+        }
+
+        // First, try mounting the ZFS volume
+        if (zfs_mount(spa, 0, &zfsmount) !=3D 0) {
+                // Mount failed.  Don't report this loudly
+                return NULL;
+        }
+
+        //vdev_t * const primary_vdev =3D spa_get_primary_vdev(spa);
+
+        if (zfs_lookup(&zfsmount, loader_path, &dn) !=3D 0) {
+                return NULL;
+        }
+
+        struct stat st;
+        if (zfs_dnode_stat(spa, &dn, &st)) {
+                return NULL;
+        }
+
+        const size_t bufsize =3D st.st_size;
+        void* buffer;
+        EFI_STATUS status;
+
+        *bufsizeref =3D bufsize;
+
+        if (systab->BootServices->AllocatePool(EfiLoaderData,
+                                               bufsize, &buffer) !=3D
+            EFI_SUCCESS) {
+                return NULL;
+        }
+
+        if (dnode_read(spa, &dn, 0, buffer, bufsize) < 0) {
+                return NULL;
+        }
+
+        return buffer;
+}
+
+static int zfs_mount_ds(const char * const dsname,
+                        struct zfsmount * const zfsmount,
+                        spa_t ** const spa)
+{
+        uint64_t newroot;
+        spa_t *newspa;
+        char *q;
+
+        q =3D strchr(dsname, '/');
+        if (q)
+	        *q++ =3D '\0';
+        newspa =3D spa_find_by_name(dsname);
+        if (newspa =3D=3D NULL) {
+	        printf("\nCan't find ZFS pool %s\n", dsname);
+	        return -1;
+        }
+
+        if (zfs_spa_init(newspa))
+                return -1;
+
+        newroot =3D 0;
+        if (q) {
+                if (zfs_lookup_dataset(newspa, q, &newroot)) {
+                        printf("\nCan't find dataset %s in ZFS pool %s\n=
",
+                               q, newspa->spa_name);
+                        return -1;
+                }
+        }
+        if (zfs_mount(newspa, newroot, zfsmount)) {
+                printf("\nCan't mount ZFS dataset\n");
+                return -1;
+        }
+        *spa =3D newspa;
+        return (0);
+}
+
+static void* load(const dev_info_t devs[],
+                  const size_t ndevs,
+                  const char* const loader_path,
+                  int* const idxref,
+                  size_t* const bufsizeref)
+{
+        for(int i =3D 0; i < ndevs; i++) {
+                void* const out =3D try_load(devs[i], loader_path, bufsi=
zeref);
+                if (out !=3D NULL)
+                {
+                        *idxref =3D i;
+                        return out;
+                }
+        }
+        return NULL;
+}
+
+static void init(EFI_HANDLE xImage,
+                 EFI_SYSTEM_TABLE* xSystab,
+                 EFI_BOOT_SERVICES * xBootsrv)
+{
+        image =3D xImage;
+        systab =3D xSystab;
+        bootsrv =3D xBootsrv;
+        zfs_init();
+}
+
+const boot_module_t zfs_module =3D
+{
+        .name =3D "ZFS",
+        .init =3D init,
+        .probe =3D probe,
+        .load =3D load
+};

Property changes on: sys/boot/efi/boot1/zfs_module.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=3D%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: sys/boot/efi/include/efilib.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/include/efilib.h	(revision 283525)
+++ sys/boot/efi/include/efilib.h	(working copy)
@@ -43,7 +43,8 @@
=20
 int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int=
);
 EFI_HANDLE efi_find_handle(struct devsw *, int);
-int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *);
+void efi_handle_update_dev(EFI_HANDLE, struct devsw *, int, uint64_t);
+int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *,  uint64_t *);
=20
 int efi_status_to_errno(EFI_STATUS);
 time_t efi_time(EFI_TIME *);
Index: sys/boot/efi/libefi/handles.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/libefi/handles.c	(revision 283525)
+++ sys/boot/efi/libefi/handles.c	(working copy)
@@ -35,6 +35,7 @@
 	EFI_HANDLE alias;
 	struct devsw *dev;
 	int unit;
+        uint64_t extra;
 };
=20
 struct entry *entry;
@@ -78,8 +79,28 @@
 	return (NULL);
 }
=20
+void efi_handle_update_dev(const EFI_HANDLE handle,
+                           struct devsw * const dev,
+                           int unit,
+                           uint64_t guid)
+{
+	int idx;
+
+	for (idx =3D 0; idx < nentries; idx++) {
+		if (entry[idx].handle !=3D handle)
+			continue;
+		entry[idx].dev =3D dev;
+                entry[idx].unit =3D unit;
+                entry[idx].alias =3D NULL;
+                entry[idx].extra =3D guid;
+	}
+}
+
 int
-efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit)
+efi_handle_lookup(EFI_HANDLE h,
+                  struct devsw **dev,
+                  int *unit,
+                  uint64_t *extra)
 {
 	int idx;
=20
@@ -90,6 +111,8 @@
 			*dev =3D entry[idx].dev;
 		if (unit !=3D NULL)
 			*unit =3D entry[idx].unit;
+                if (extra !=3D NULL)
+                        *extra =3D entry[idx].extra;
 		return (0);
 	}
 	return (ENOENT);
Index: sys/boot/efi/loader/Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/loader/Makefile	(revision 283525)
+++ sys/boot/efi/loader/Makefile	(working copy)
@@ -12,6 +12,8 @@
 PROG=3D		loader.sym
 INTERNALPROG=3D
=20
+#LIBZFSBOOT=3D	${.OBJDIR}/../../zfs/libzfsboot.a
+
 .PATH: ${.CURDIR}/../../efi/loader
 # architecture-specific loader code
 SRCS=3D	autoload.c \
@@ -22,8 +24,11 @@
 	main.c \
 	self_reloc.c \
 	smbios.c \
-	vers.c
+	vers.c \
+        ${ZFS_C}
=20
+ZFS_C =3D ${.CURDIR}/../../zfs/zfs.c
+
 .PATH: ${.CURDIR}/arch/${MACHINE}
 # For smbios.c
 .PATH: ${.CURDIR}/../../i386/libi386
@@ -36,6 +41,8 @@
 CFLAGS+=3D	-I${.CURDIR}/../../../contrib/dev/acpica/include
 CFLAGS+=3D	-I${.CURDIR}/../../..
 CFLAGS+=3D	-I${.CURDIR}/../../i386/libi386
+CFLAGS+=3D	-I${.CURDIR}/../../zfs
+CFLAGS+=3D	-I${.CURDIR}/../../../cddl/boot/zfs
 CFLAGS+=3D	-DNO_PCI -DEFI
=20
 # make buildenv doesn't set DESTDIR, this means LIBSTAND
@@ -68,7 +75,7 @@
 CFLAGS+=3D	-DEFI_STAGING_SIZE=3D${EFI_STAGING_SIZE}
 .endif
=20
-# Always add MI sources=20
+# Always add MI sources
 .PATH:		${.CURDIR}/../../common
 .include	"${.CURDIR}/../../common/Makefile.inc"
 CFLAGS+=3D	-I${.CURDIR}/../../common
Index: sys/boot/efi/loader/conf.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/loader/conf.c	(revision 283525)
+++ sys/boot/efi/loader/conf.c	(working copy)
@@ -31,14 +31,17 @@
 #include <bootstrap.h>
 #include <efi.h>
 #include <efilib.h>
+#include "../zfs/libzfs.h"
=20
 struct devsw *devsw[] =3D {
 	&efipart_dev,
 	&efinet_dev,
+        &zfs_dev,
 	NULL
 };
=20
 struct fs_ops *file_system[] =3D {
+        &zfs_fsops,
 	&dosfs_fsops,
 	&ufs_fsops,
 	&cd9660_fsops,
Index: sys/boot/efi/loader/devicename.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/loader/devicename.c	(revision 283525)
+++ sys/boot/efi/loader/devicename.c	(working copy)
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <sys/disklabel.h>
 #include "bootstrap.h"
+#include "libzfs.h"
=20
 #include <efi.h>
 #include <efilib.h>
@@ -38,7 +39,7 @@
=20
 static int efi_parsedev(struct devdesc **, const char *, const char **);=

=20
-/*=20
+/*
  * Point (dev) at an allocated device specifier for the device matching =
the
  * path in (devspec). If it contains an explicit device specification,
  * use that.  If not, use the default device.
@@ -48,7 +49,6 @@
 {
 	struct devdesc **dev =3D (struct devdesc **)vdev;
 	int rv;
-
 	/*
 	 * If it looks like this is just a path and no device, then
 	 * use the current device instead.
@@ -61,7 +61,8 @@
 	}
=20
 	/* Parse the device name off the beginning of the devspec. */
-	return (efi_parsedev(dev, devspec, path));
+	const int out =3D efi_parsedev(dev, devspec, path);
+        return out;
 }
=20
 /*
@@ -87,8 +88,9 @@
 	int i, err;
=20
 	/* minimum length check */
-	if (strlen(devspec) < 2)
+	if (strlen(devspec) < 2) {
 		return (EINVAL);
+        }
=20
 	/* look for a device that matches */
 	for (i =3D 0; devsw[i] !=3D NULL; i++) {
@@ -96,27 +98,39 @@
 		if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name)))
 			break;
 	}
-	if (devsw[i] =3D=3D NULL)
+	if (devsw[i] =3D=3D NULL) {
 		return (ENOENT);
+        }
+	np =3D devspec + strlen(dv->dv_name);
=20
-	idev =3D malloc(sizeof(struct devdesc));
-	if (idev =3D=3D NULL)
-		return (ENOMEM);
+        if (DEVT_ZFS =3D=3D dv->dv_type) {
+                idev =3D malloc(sizeof(struct zfs_devdesc));
+                int out =3D zfs_parsedev((struct zfs_devdesc*)idev, np, =
path);
+                if (0 =3D=3D out) {
+                        *dev =3D idev;
+                        cp =3D strchr(np + 1, ':');
+                } else {
+                        free(idev);
+                        return out;
+                }
+        } else {
+                idev =3D malloc(sizeof(struct devdesc));
+                if (idev =3D=3D NULL)
+                        return (ENOMEM);
=20
-	idev->d_dev =3D dv;
-	idev->d_type =3D dv->dv_type;
-	idev->d_unit =3D -1;
-
+                idev->d_dev =3D dv;
+                idev->d_type =3D dv->dv_type;
+                idev->d_unit =3D -1;
+                if (*np !=3D '\0' && *np !=3D ':') {
+                        idev->d_unit =3D strtol(np, &cp, 0);
+                        if (cp =3D=3D np) {
+                                idev->d_unit =3D -1;
+                                free(idev);
+                                return (EUNIT);
+                        }
+                }
+        }
 	err =3D 0;
-	np =3D devspec + strlen(dv->dv_name);
-	if (*np !=3D '\0' && *np !=3D ':') {
-		idev->d_unit =3D strtol(np, &cp, 0);
-		if (cp =3D=3D np) {
-			idev->d_unit =3D -1;
-			free(idev);
-			return (EUNIT);
-		}
-	}
 	if (*cp !=3D '\0' && *cp !=3D ':') {
 		free(idev);
 		return (EINVAL);
@@ -138,10 +152,11 @@
 	static char buf[32];	/* XXX device length constant? */
=20
 	switch(dev->d_type) {
+        case DEVT_ZFS:
+                return zfs_fmtdev(dev);
 	case DEVT_NONE:
 		strcpy(buf, "(no device)");
 		break;
-
 	default:
 		sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
 		break;
Index: sys/boot/efi/loader/main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/efi/loader/main.c	(revision 283525)
+++ sys/boot/efi/loader/main.c	(working copy)
@@ -39,6 +39,7 @@
 #include <smbios.h>
=20
 #include "loader_efi.h"
+#include "libzfs.h"
=20
 extern char bootprog_name[];
 extern char bootprog_rev[];
@@ -45,8 +46,9 @@
 extern char bootprog_date[];
 extern char bootprog_maker[];
=20
-struct devdesc currdev;		/* our current device */
-struct arch_switch archsw;	/* MI/MD interface boundary */
+/* our current device */
+/* MI/MD interface boundary */
+struct arch_switch archsw;
=20
 EFI_GUID acpi =3D ACPI_TABLE_GUID;
 EFI_GUID acpi20 =3D ACPI_20_TABLE_GUID;
@@ -61,6 +63,70 @@
 EFI_GUID debugimg =3D DEBUG_IMAGE_INFO_TABLE_GUID;
 EFI_GUID fdtdtb =3D FDT_TABLE_GUID;
=20
+static void efi_zfs_probe(void);
+
+static void
+print_str16(const CHAR16* const str)
+{
+        for(int i; str[i]; i++)
+        {
+                printf("%c", str[i]);
+        }
+}
+
+/*
+static int
+str16cmp(const CHAR16 const *a,
+         const char* const b)
+{
+        for(int i =3D 0; a[i] || b[i]; i++)
+        {
+                const CHAR16 achr =3D a[i];
+                const CHAR16 bchr =3D b[i];
+                if (achr < bchr)
+                {
+                        return -1;
+                } else if (achr > bchr)
+                {
+                        return 1;
+                }
+        }
+        return 0;
+}
+
+// Split an arg of the form "argname=3Dargval", replacing the '=3D' with=
 a \0
+static CHAR16*
+split_arg(CHAR16 *const str)
+{
+        for (int i =3D 0; str[i]; i++)
+        {
+                if ('=3D' =3D=3D str[i])
+                {
+                        str[i] =3D 0;
+                        return str + i + 1;
+                }
+        }
+        return NULL;
+}
+
+static void
+handle_arg(CHAR16 *const arg)
+{
+        const CHAR16* const argval =3D split_arg(arg);
+        const CHAR16* const argname =3D arg;
+
+        if (NULL !=3D argval)
+        {
+                printf("Unrecognized argument \"");
+                print_arg(argname);
+                printf("\n");
+        } else {
+                printf("Unrecognized argument \"");
+                print_arg(argname);
+                printf("\n");
+        }
+}
+*/
 EFI_STATUS
 main(int argc, CHAR16 *argv[])
 {
@@ -69,7 +135,15 @@
 	EFI_GUID *guid;
 	int i;
=20
-	/*
+	archsw.arch_autoload =3D efi_autoload;
+	archsw.arch_getdev =3D efi_getdev;
+	archsw.arch_copyin =3D efi_copyin;
+	archsw.arch_copyout =3D efi_copyout;
+	archsw.arch_readin =3D efi_readin;
+        // Note this needs to be set before ZFS init
+        archsw.arch_zfs_probe =3D efi_zfs_probe;
+
+        /*
 	 * XXX Chicken-and-egg problem; we want to have console output
 	 * early, but some console attributes may depend on reading from
 	 * eg. the boot device, which we can't do yet.  We can use
@@ -85,13 +159,22 @@
 	/*
 	 * March through the device switch probing for things.
 	 */
-	for (i =3D 0; devsw[i] !=3D NULL; i++)
-		if (devsw[i]->dv_init !=3D NULL)
+	for (i =3D 0; devsw[i] !=3D NULL; i++) {
+                if (devsw[i]->dv_init !=3D NULL) {
+                        printf("Initializing %s\n", devsw[i]->dv_name);
 			(devsw[i]->dv_init)();
-
+                }
+        }
 	/* Get our loaded image protocol interface structure. */
 	BS->HandleProtocol(IH, &imgid, (VOID**)&img);
=20
+	printf("Command line arguments:");
+        for(i =3D 0; i < argc; i++) {
+                printf(" ");
+                print_str16(argv[i]);
+        }
+	printf("\n");
+
 	printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
 	printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
 	    ST->Hdr.Revision & 0xffff);
@@ -105,8 +188,13 @@
 	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
 	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
=20
-	efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit);
-	currdev.d_type =3D currdev.d_dev->dv_type;
+        // Handle command-line arguments
+        /*
+        for(i =3D 1; i < argc; i++)
+        {
+                handle_arg(argv[i]);
+        }
+        */
=20
 	/*
 	 * Disable the watchdog timer. By default the boot manager sets
@@ -119,19 +207,39 @@
 	 */
 	BS->SetWatchdogTimer(0, 0, 0, NULL);
=20
-	env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
-	    efi_setcurrdev, env_nounset);
-	env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
-	    env_nounset);
+        struct devsw *dev;
+        int unit;
+        uint64_t pool_guid;
+        efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid);
+        switch (dev->dv_type) {
+        case DEVT_ZFS: {
+                struct zfs_devdesc currdev;
+                currdev.d_dev =3D dev;
+                currdev.d_unit =3D unit;
+                currdev.d_type =3D currdev.d_dev->dv_type;
+                currdev.d_opendata =3D NULL;
+                currdev.pool_guid =3D pool_guid;
+                currdev.root_guid =3D 0;
+                env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),=

+                           efi_setcurrdev, env_nounset);
+                env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev),=
 env_noset,
+                           env_nounset);
+        } break;
+        default: {
+                struct devdesc currdev;
+                currdev.d_dev =3D dev;
+                currdev.d_unit =3D unit;
+                currdev.d_opendata =3D NULL;
+                currdev.d_type =3D currdev.d_dev->dv_type;
+                env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),=

+                           efi_setcurrdev, env_nounset);
+                env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev),=
 env_noset,
+                           env_nounset);
+        } break;
+        }
=20
 	setenv("LINES", "24", 1);	/* optional */
=20
-	archsw.arch_autoload =3D efi_autoload;
-	archsw.arch_getdev =3D efi_getdev;
-	archsw.arch_copyin =3D efi_copyin;
-	archsw.arch_copyout =3D efi_copyout;
-	archsw.arch_readin =3D efi_readin;
-
 	for (i =3D 0; i < ST->NumberOfTableEntries; i++) {
 		guid =3D &ST->ConfigurationTable[i].VendorGuid;
 		if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
@@ -350,7 +458,6 @@
 	return (CMD_OK);
 }
=20
-
 COMMAND_SET(nvram, "nvram", "get or set NVRAM variables", command_nvram)=
;
=20
 static int
@@ -402,6 +509,27 @@
 	return (CMD_OK);
 }
=20
+COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
+    command_lszfs);
+
+static int
+command_lszfs(int argc, char *argv[])
+{
+    int err;
+
+    if (argc !=3D 2) {
+	command_errmsg =3D "wrong number of arguments";
+	return (CMD_ERROR);
+    }
+
+    err =3D zfs_list(argv[1]);
+    if (err !=3D 0) {
+	command_errmsg =3D strerror(err);
+	return (CMD_ERROR);
+    }
+    return (CMD_OK);
+}
+
 #ifdef LOADER_FDT_SUPPORT
 extern int command_fdt_internal(int argc, char *argv[]);
=20
@@ -420,3 +548,23 @@
=20
 COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
 #endif
+
+static void
+efi_zfs_probe(void)
+{
+	EFI_BLOCK_IO *blkio;
+	EFI_HANDLE h;
+	EFI_STATUS status;
+	u_int unit =3D 0;
+        char devname[32];
+        uint64_t pool_guid;
+
+	for (int i =3D 0, h =3D efi_find_handle(&efipart_dev, 0);
+	    h !=3D NULL; h =3D efi_find_handle(&efipart_dev, ++i)) {
+                snprintf(devname, sizeof devname, "%s%d:",
+                         efipart_dev.dv_name, i);
+                if(0 =3D=3D zfs_probe_dev(devname, &pool_guid)) {
+                        efi_handle_update_dev(h, &zfs_dev, unit++, pool_=
guid);
+                }
+        }
+}
Index: sys/boot/zfs/zfs.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/zfs/zfs.c	(revision 283525)
+++ sys/boot/zfs/zfs.c	(working copy)
@@ -140,7 +140,7 @@
 	n =3D size;
 	if (fp->f_seekp + n > sb.st_size)
 		n =3D sb.st_size - fp->f_seekp;
-=09
+
 	rc =3D dnode_read(spa, &fp->f_dnode, fp->f_seekp, start, n);
 	if (rc)
 		return (rc);
@@ -493,7 +493,7 @@
 		}
 	}
 	close(pa.fd);
-	return (0);
+	return (ret);
 }
=20
 /*

--------------040508010102090007040903--

--9mXtQcxIOTeBwJJoa4u3PEkLG2JCiT7t8
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAEBAgAGBQJVdh5gAAoJEEGB2s+NNG0FiowQAL/TyR5NDvsJyybuIMCPigzD
2eSU5raV1osBX4v7bCTBl3bcXlbmKD4qKnsdSJ3l7Uq2Dcx5N0NuhrvDwexomT2G
II3uQGpiTILin6/KGuGj+TySed59QEiTEe0Ue/GMi3hIjDZ16EoHamgTU5fdraG6
92zW/wfPCQS/hmruhnw6cUnHR0p4LwCERm0GnfHhoTYnLEVmiv9PLVoyWBoViRel
R4A0WIIUJGDteonwCGo0u19fqnPvOuUs2Pfw9+T+Ds6QHE6QP6gOGHbRlkJKxYD6
Ci1iRZXGiCgs7YAgyv8k1uf9JELR4IOgsde39U0nY6h6WHAtPxGbXlrMH5rLlpQ8
5+vbXK9ndBf4a/YphrjfPWAr4vX/KJbC7UXIA88vgszPe6KPl1TBD7Z3GuGpotGK
snS5yvFquWyXJkXq1V23da/aaaqLquILuZKeUqqcdRs80hkvRVCk2OZPuJYxMsQ/
IZG9AqYTjKzz+wN8J+IcRGFOtxmp+4TZFsFv8eBvY8FOuUHkCCwwpszFpTOW6qRc
/cpfHODnMcpqjP7dBktShVgjP5/EZ4Yh/fg4vwVGWQeJC7MQgMXA/sTqf3V0+sde
/5sgATJX4QE1fvu3ORD3oJTW730GVpPHd2YeUi9juYcoZ0dU3X1sxG6Y6jypgBJX
m53qFGGi1Bj8PzLWlbq7
=YoaN
-----END PGP SIGNATURE-----

--9mXtQcxIOTeBwJJoa4u3PEkLG2JCiT7t8--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?55761E58.6040704>