Page MenuHomeFreeBSD
Authored By
smh
Dec 9 2015, 6:21 AM
Size
43 KB
Referenced Files
None
Subscribers
None

efi-zfs.patch

Index: sys/boot/efi/boot1/Makefile
===================================================================
--- sys/boot/efi/boot1/Makefile (revision 292005)
+++ sys/boot/efi/boot1/Makefile (working copy)
@@ -3,6 +3,7 @@
MAN=
.include <bsd.own.mk>
+.include <src.opts.mk>
# In-tree GCC does not support __attribute__((ms_abi)).
.if ${COMPILER_TYPE} != "gcc"
@@ -13,7 +14,10 @@ PROG= boot1.sym
INTERNALPROG=
# architecture-specific loader code
-SRCS= boot1.c self_reloc.c start.S
+SRCS= boot1.c self_reloc.c start.S ufs_module.c
+.if ${MK_ZFS} != "no"
+SRCS+= zfs_module.c
+.endif
CFLAGS+= -I.
CFLAGS+= -I${.CURDIR}/../include
@@ -20,6 +24,11 @@ CFLAGS+= -I${.CURDIR}/../include
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
+.if ${MK_ZFS} != "no"
+CFLAGS+= -I${.CURDIR}/../../zfs/
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs/
+CFLAGS+= -DZFS_EFI_BOOT
+.endif
# Always add MI sources and REGULAR efi loader bits
.PATH: ${.CURDIR}/../loader/arch/${MACHINE}
Index: sys/boot/efi/boot1/boot1.c
===================================================================
--- sys/boot/efi/boot1/boot1.c (revision 292005)
+++ 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) 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
@@ -21,7 +23,6 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/dirent.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
@@ -28,6 +29,8 @@ __FBSDID("$FreeBSD$");
#include <efi.h>
#include <eficonsctl.h>
+#include "boot_module.h"
+
#define _PATH_LOADER "/boot/loader.efi"
#define _PATH_KERNEL "/boot/kernel/kernel"
@@ -41,14 +44,20 @@ struct sp_data {
u_int sp_size;
};
+static const boot_module_t* const boot_modules[] =
+{
+#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[] = "0123456789abcdef";
-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_list ap);
static int __putc(char c, void *arg);
static int __puts(const char *s, putc_func_t *putc, void *arg);
@@ -58,11 +67,115 @@ static char *__ultoa(char *buf, u_long val, int ba
static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet);
static void load(const char *fname);
+static void try_load(const boot_module_t* mod, const dev_info_t devs[],
+ size_t ndevs);
static EFI_SYSTEM_TABLE *systab;
static EFI_HANDLE *image;
-static void
+void *
+Malloc(size_t len, const char *file, int line)
+{
+ void *out;
+
+ if (systab->BootServices->AllocatePool(EfiLoaderData,
+ len, &out) != EFI_SUCCESS) {
+ printf("Can't allocate memory pool\n");
+ return (NULL);
+ }
+
+ return (out);
+}
+
+char *
+strcpy(char *dst, const char *src)
+{
+ int i;
+
+ for (i = 0; src[i]; i++)
+ dst[i] = src[i];
+
+ return (dst);
+}
+
+char *
+strchr(const char *s, int c)
+{
+ int i;
+
+ for (i = 0; s[i]; i++)
+ if (s[i] == c)
+ return ((char*)(s + i));
+
+ return (NULL);
+}
+
+int
+strncmp(const char *a, const char *b, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (a[i] == '\0' && b[i] == '\0')
+ return (0);
+ else if (a[i] < b[i])
+ return (-1);
+ else if (a[i] > b[i])
+ return (1);
+ }
+
+ return (0);
+}
+
+size_t
+strlen(const char *s)
+{
+ size_t len = 0;
+
+ for (; *s != '\0'; s++, len++)
+ ;
+
+ return (len);
+}
+
+char *
+strdup(const char *s)
+{
+ int len;
+ char* out;
+ int i;
+
+ len = strlen(s);
+ out = malloc(len);
+ if (out == NULL)
+ return (NULL);
+ for (i = 0; i < len; i++)
+ out[i] = s[i];
+
+ return (out);
+}
+
+int
+bcmp(const void *a, const void *b, size_t len)
+{
+ const char *sa = a;
+ const char *sb = b;
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (sa[i] != 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 = src;
@@ -72,22 +185,28 @@ bcopy(const void *src, void *dst, size_t len)
*d++ = *s++;
}
-static void
+void *
memcpy(void *dst, const void *src, size_t len)
{
+
+
bcopy(src, dst, len);
+
+ return (dst);
}
-static void
-bzero(void *b, size_t len)
+void*
+memset(void *b, int val, size_t len)
{
char *p = b;
while (len-- != 0)
- *p++ = 0;
+ *p++ = val;
+
+ return (b);
}
-static int
+int
strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2 && *s1; s1++, s2++)
@@ -95,30 +214,86 @@ strcmp(const char *s1, const char *s2)
return ((u_char)*s1 - (u_char)*s2);
}
+int
+putchr(char c, void *arg)
+{
+ 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);
+
+ return (1);
+}
+
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
-static EFI_BLOCK_IO *bootdev;
-static EFI_DEVICE_PATH *bootdevpath;
-static EFI_HANDLE *bootdevhandle;
+#define MAX_DEVS 128
-EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
+/*
+ * This function only returns if it fails to load the kernel. If it
+ * succeeds, it simply boots the kernel.
+ */
+void
+try_load(const boot_module_t *mod, const dev_info_t devs[], size_t ndevs)
{
- EFI_HANDLE handles[128];
+ int idx;
+ size_t bufsize;
+ void *buffer;
+ EFI_HANDLE loaderhandle;
+ EFI_LOADED_IMAGE *loaded_image;
+
+ buffer = mod->load(devs, ndevs, _PATH_LOADER, &idx, &bufsize);
+ if (buffer == NULL) {
+ printf("Could not load file\n");
+ return;
+ }
+
+ if (systab->BootServices->LoadImage(TRUE, image, devs[idx].devpath,
+ buffer, bufsize, &loaderhandle) != EFI_SUCCESS)
+ return;
+
+ if (systab->BootServices->HandleProtocol(loaderhandle,
+ &LoadedImageGUID, (VOID**)&loaded_image) != EFI_SUCCESS)
+ return;
+
+ loaded_image->DeviceHandle = devs[idx].devhandle;
+
+ if (systab->BootServices->StartImage(loaderhandle, NULL, NULL) !=
+ EFI_SUCCESS)
+ return;
+}
+
+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 = sizeof(handles), cols, rows, max_dim, best_mode;
EFI_STATUS status;
EFI_DEVICE_PATH *devpath;
EFI_BOOT_SERVICES *BS;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
- char *path = _PATH_LOADER;
+ UINTN i, j, max_dim, best_mode, cols, rows, nparts;
+ /* Basic initialization*/
+ nparts = sizeof(handles);
systab = Xsystab;
image = Ximage;
+ memset(dev_offsets, 0, NUM_BOOT_MODULES * sizeof(size_t));
+
+ /* Set up the console, so printf works. */
BS = systab->BootServices;
status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
(VOID **)&ConsoleControl);
@@ -132,8 +307,7 @@ static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_C
conout->Reset(conout, TRUE);
max_dim = best_mode = 0;
for (i = 0; ; i++) {
- status = conout->QueryMode(conout, i,
- &cols, &rows);
+ status = conout->QueryMode(conout, i, &cols, &rows);
if (EFI_ERROR(status))
break;
if (cols * rows > max_dim) {
@@ -146,15 +320,27 @@ static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_C
conout->EnableCursor(conout, TRUE);
conout->ClearScreen(conout);
- printf("\n"
- ">> FreeBSD EFI boot block\n");
- printf(" Loader path: %s\n", path);
+ printf("\n>> FreeBSD EFI boot block\n");
+ printf(" Loader path: %s\n\n", _PATH_LOADER);
+ printf(" Initializing modules:");
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] != NULL) {
+ printf(" %s", boot_modules[i]->name);
+ boot_modules[i]->init(image, systab, BS);
+ }
+ }
+ putchr('\n', NULL);
+ /* Get all the device handles */
status = systab->BootServices->LocateHandle(ByProtocol,
&BlockIoProtocolGUID, NULL, &nparts, handles);
nparts /= sizeof(handles[0]);
+ /* Scan all partitions, probing with all modules. */
for (i = 0; i < nparts; i++) {
+ dev_info_t devinfo;
+
+ /* Figure out if we're dealing with an actual partition. */
status = systab->BootServices->HandleProtocol(handles[i],
&DevicePathGUID, (void **)&devpath);
if (EFI_ERROR(status))
@@ -170,181 +356,39 @@ static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_C
if (!blkio->Media->LogicalPartition)
continue;
+ /* Setup devinfo */
+ devinfo.dev = blkio;
+ devinfo.devpath = devpath;
+ devinfo.devhandle = handles[i];
+ devinfo.devdata = NULL;
- if (domount(devpath, blkio, 1) >= 0)
- break;
- }
-
- if (i == nparts)
- panic("No bootable partition found");
-
- bootdevhandle = 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 = lba / (bootdev->Media->BlockSize / DEV_BSIZE);
- size = nblk * DEV_BSIZE;
- status = 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 = dmadat->blkbuf;
- indbuf = dmadat->indbuf;
- if (!dsk_meta) {
- inomap = 0;
- for (n = 0; sblock_try[n] != -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 == FS_UFS1_MAGIC
-#elif defined(UFS2_ONLY)
- (fs.fs_magic == FS_UFS2_MAGIC &&
- fs.fs_sblockloc == sblock_try[n])
-#else
- fs.fs_magic == FS_UFS1_MAGIC ||
- (fs.fs_magic == FS_UFS2_MAGIC &&
- fs.fs_sblockloc == sblock_try[n])
-#endif
- ) &&
- fs.fs_bsize <= MAXBSIZE &&
- fs.fs_bsize >= sizeof(struct fs))
- break;
+ /* Run through each module, see if it can load this partition */
+ for (j = 0; j < NUM_BOOT_MODULES; j++ ) {
+ if (boot_modules[j] != NULL &&
+ boot_modules[j]->probe(&devinfo)) {
+ /*
+ * If we can, save it to the device list for
+ * that module.
+ */
+ module_devs[j][dev_offsets[j]++] = devinfo;
+ }
}
- if (sblock_try[n] == -1) {
- printf("Not ufs\n");
- return -1;
- }
- dsk_meta++;
- } else
- memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
- if (!inode)
- return 0;
- if (inomap != inode) {
- n = IPERVBLK(&fs);
- if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
- return -1;
- n = 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 == 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 = inode;
- fs_off = 0;
- blkmap = indmap = 0;
}
- size = DIP(di_size);
- n = size - fs_off;
- return (n);
-}
-static struct dmadat __dmadat;
-
-static int
-domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
-{
-
- dmadat = &__dmadat;
- bootdev = blkio;
- bootdevpath = device;
- if (fsread(0, NULL, 0)) {
- if (!quiet)
- printf("domount: can't read superblock\n");
- return (-1);
+ /*
+ * Select a partition to boot by trying each module in order.
+ */
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
+ try_load(boot_modules[i], module_devs[i], dev_offsets[i]);
}
- if (!quiet)
- printf("Succesfully mounted UFS filesystem\n");
- return (0);
-}
-static void
-load(const char *fname)
-{
- ufs_ino_t ino;
- EFI_STATUS status;
- EFI_HANDLE loaderhandle;
- EFI_LOADED_IMAGE *loaded_image;
- void *buffer;
- size_t bufsize;
-
- if ((ino = lookup(fname)) == 0) {
- printf("File %s not found\n", fname);
- return;
- }
-
- bufsize = fsstat(ino);
- status = systab->BootServices->AllocatePool(EfiLoaderData,
- bufsize, &buffer);
- fsread(ino, buffer, bufsize);
-
- /* XXX: For secure boot, we need our own loader here */
- status = systab->BootServices->LoadImage(TRUE, image, bootdevpath,
- buffer, bufsize, &loaderhandle);
- if (EFI_ERROR(status))
- printf("LoadImage failed with error %lx\n", status);
-
- status = systab->BootServices->HandleProtocol(loaderhandle,
- &LoadedImageGUID, (VOID**)&loaded_image);
- if (EFI_ERROR(status))
- printf("HandleProtocol failed with error %lx\n", status);
-
- loaded_image->DeviceHandle = bootdevhandle;
-
- status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
- if (EFI_ERROR(status))
- printf("StartImage failed with error %lx\n", status);
+ /* If we get here, we're out of luck... */
+ panic("No bootable partitions found!");
}
-static void
+void
panic(const char *fmt, ...)
{
char buf[128];
@@ -358,7 +402,7 @@ panic(const char *fmt, ...)
while (1) {}
}
-static int
+int
printf(const char *fmt, ...)
{
va_list ap;
@@ -369,39 +413,18 @@ printf(const char *fmt, ...)
return 0;
va_start(ap, fmt);
- ret = vprintf(fmt, ap);
+ ret = __printf(fmt, putchr, 0, ap);
va_end(ap);
return (ret);
}
-static int
-putchar(char c, void *arg)
+void vprintf(const char *fmt, va_list ap)
{
- 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);
- return (1);
+ __printf(fmt, putchr, 0, ap);
}
-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 = __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;
@@ -416,15 +439,10 @@ static int
__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
{
char buf[(sizeof(long) * 8) + 1];
- char *nbuf;
+ char *nbuf, *s;
u_long ul;
u_int ui;
- int lflag;
- int sflag;
- char *s;
- int pad;
- int ret;
- int c;
+ int lflag, sflag, pad, ret, c;
nbuf = &buf[sizeof buf - 1];
ret = 0;
Index: sys/boot/efi/boot1/boot_module.h
===================================================================
--- sys/boot/efi/boot1/boot_module.h (nonexistent)
+++ sys/boot/efi/boot1/boot_module.h (working copy)
@@ -0,0 +1,59 @@
+#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
+
+/* 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 handle. */
+ 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=%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
===================================================================
--- sys/boot/efi/boot1/ufs_module.c (nonexistent)
+++ sys/boot/efi/boot1/ufs_module.c (working copy)
@@ -0,0 +1,212 @@
+/*-
+ * 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 = LOADED_IMAGE_PROTOCOL;
+
+static int
+dskread(void *buf, u_int64_t lba, int nblk)
+{
+ int size;
+
+ lba = lba / (devinfo.dev->Media->BlockSize / DEV_BSIZE);
+ size = nblk * DEV_BSIZE;
+
+ if (devinfo.dev->ReadBlocks(devinfo.dev,
+ devinfo.dev->Media->MediaId, lba, size, buf) != EFI_SUCCESS)
+ 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 = dmadat->blkbuf;
+ indbuf = dmadat->indbuf;
+ if (!dsk_meta) {
+ inomap = 0;
+ for (n = 0; sblock_try[n] != -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 == FS_UFS1_MAGIC
+#elif defined(UFS2_ONLY)
+ (fs.fs_magic == FS_UFS2_MAGIC &&
+ fs.fs_sblockloc == sblock_try[n])
+#else
+ fs.fs_magic == FS_UFS1_MAGIC ||
+ (fs.fs_magic == FS_UFS2_MAGIC &&
+ fs.fs_sblockloc == sblock_try[n])
+#endif
+ ) &&
+ fs.fs_bsize <= MAXBSIZE &&
+ fs.fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[n] == -1) {
+ return (-1);
+ }
+ dsk_meta++;
+ } else
+ memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
+ if (!inode)
+ return (0);
+ if (inomap != inode) {
+ n = IPERVBLK(&fs);
+ if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
+ return (-1);
+ n = 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 == 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 = inode;
+ fs_off = 0;
+ blkmap = indmap = 0;
+ }
+ size = DIP(di_size);
+ n = size - fs_off;
+
+ return (n);
+}
+
+static struct dmadat __dmadat;
+
+static bool
+probe(const dev_info_t* dev)
+{
+
+
+ devinfo = *dev;
+ dmadat = &__dmadat;
+ if (fsread(0, NULL, 0) < 0) {
+ return (false);
+ }
+ return (true);
+}
+
+static void*
+try_load(dev_info_t dev, const char *loader_path, size_t *bufsizeref)
+{
+ ufs_ino_t ino;
+ EFI_STATUS status;
+ void *buffer;
+ size_t bufsize;
+
+ devinfo = dev;
+ if ((ino = lookup(loader_path)) == 0) {
+ printf("File %s not found\n", loader_path);
+ return (NULL);
+ }
+
+ bufsize = fsstat(ino);
+ *bufsizeref = bufsize;
+ if (systab->BootServices->AllocatePool(EfiLoaderData,
+ bufsize, &buffer) != EFI_SUCCESS)
+ return (NULL);
+
+ if (fsread(ino, buffer, bufsize) < 0) {
+ systab->BootServices->FreePool(buffer);
+ return (NULL);
+ }
+
+ return (buffer);
+}
+
+static void *
+load(const dev_info_t devs[], size_t ndevs, const char *loader_path,
+ int *idxref, size_t *bufsizeref)
+{
+ void *out;
+ int i;
+
+ for (i = 0; i < ndevs; i++) {
+ out = try_load(devs[i], loader_path, bufsizeref);
+ if (out != NULL) {
+ *idxref = i;
+ return (out);
+ }
+ }
+
+ return (NULL);
+}
+
+
+static void
+init(EFI_HANDLE xImage, EFI_SYSTEM_TABLE* xSystab, EFI_BOOT_SERVICES * xBootsrv)
+{
+ image = xImage;
+ systab = xSystab;
+ bootsrv = xBootsrv;
+}
+
+const boot_module_t ufs_module =
+{
+ .name = "UFS",
+ .init = init,
+ .probe = probe,
+ .load = 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=%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
===================================================================
--- sys/boot/efi/boot1/zfs_module.c (nonexistent)
+++ sys/boot/efi/boot1/zfs_module.c (working copy)
@@ -0,0 +1,197 @@
+/* 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 *vdev, void *priv, off_t off, void *buf, size_t bytes)
+{
+ dev_info_t *devinfo;
+ off_t lba;
+
+ devinfo = (dev_info_t *)priv;
+ lba = off / devinfo->dev->Media->BlockSize;
+
+ if (devinfo->dev->ReadBlocks(devinfo->dev,
+ devinfo->dev->Media->MediaId, lba, bytes, buf) != EFI_SUCCESS)
+ return (-1);
+
+ return (0);
+}
+
+static bool
+probe(dev_info_t *dev)
+{
+ spa_t *spa;
+ int err;
+
+ err = vdev_probe(vdev_read, dev, &spa);
+ if (err != 0)
+ return (false);
+
+ dev->devdata = spa;
+
+ return (true);
+}
+
+static void*
+try_load(dev_info_t devinfo, const char *loader_path, size_t *bufsizeref)
+{
+ spa_t *spa = devinfo.devdata;
+ struct zfsmount zfsmount;
+ dnode_phys_t dn;
+ size_t bufsize;
+ void *buffer;
+ struct stat st;
+
+ if (zfs_spa_init(spa) != 0) {
+ /* Mount failed, don't report this loudly. */
+ return (NULL);
+ }
+
+ /* First, try mounting the ZFS volume. */
+ if (zfs_mount(spa, 0, &zfsmount) != 0) {
+ /* Mount failed, don't report this loudly. */
+ return (NULL);
+ }
+
+ if (zfs_lookup(&zfsmount, loader_path, &dn) != 0)
+ return (NULL);
+
+ if (zfs_dnode_stat(spa, &dn, &st) != 0)
+ return (NULL);
+
+ if (systab->BootServices->AllocatePool(EfiLoaderData, (UINTN)st.st_size,
+ &buffer) != EFI_SUCCESS)
+ return (NULL);
+
+ if (dnode_read(spa, &dn, 0, buffer, st.st_size) != 0) {
+ (void)systab->BootServices->FreePool(buffer);
+ return (NULL);
+ }
+
+ *bufsizeref = st.st_size;
+
+ return (buffer);
+}
+
+static int
+zfs_mount_ds(const char *dsname, struct zfsmount *zfsmount, spa_t **spa)
+{
+ uint64_t newroot;
+ spa_t *newspa;
+ char *q;
+
+ q = strchr(dsname, '/');
+ if (q != NULL)
+ *q++ = '\0';
+
+ newspa = spa_find_by_name(dsname);
+ if (newspa == NULL) {
+ printf("\nCan't find ZFS pool %s\n", dsname);
+ return (-1);
+ }
+
+ if (zfs_spa_init(newspa) != 0)
+ return (-1);
+
+ newroot = 0;
+ if (q) {
+ if (zfs_lookup_dataset(newspa, q, &newroot) != 0) {
+ printf("\nCan't find dataset %s in ZFS pool %s\n",
+ q, newspa->spa_name);
+ return (-1);
+ }
+ }
+
+ if (zfs_mount(newspa, newroot, zfsmount) != 0) {
+ printf("\nCan't mount ZFS dataset\n");
+ return (-1);
+ }
+ *spa = newspa;
+
+ return (0);
+}
+
+static void*
+load(const dev_info_t devs[], size_t ndevs, const char *loader_path,
+ int *idxref, size_t *bufsizeref)
+{
+ void *out;
+ int i;
+
+ for (i = 0; i < ndevs; i++) {
+ out = try_load(devs[i], loader_path, bufsizeref);
+ if (out != NULL) {
+ *idxref = i;
+ return (out);
+ }
+ }
+
+ return (NULL);
+}
+
+static void
+init(EFI_HANDLE xImage, EFI_SYSTEM_TABLE *xSystab, EFI_BOOT_SERVICES *xBootsrv)
+{
+ image = xImage;
+ systab = xSystab;
+ bootsrv = xBootsrv;
+ zfs_init();
+}
+
+const boot_module_t zfs_module =
+{
+ .name = "ZFS",
+ .init = init,
+ .probe = probe,
+ .load = 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=%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
===================================================================
--- sys/boot/efi/include/efilib.h (revision 292005)
+++ sys/boot/efi/include/efilib.h (working copy)
@@ -43,7 +43,8 @@ void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_
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 *);
+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_status_to_errno(EFI_STATUS);
time_t efi_time(EFI_TIME *);
Index: sys/boot/efi/libefi/handles.c
===================================================================
--- sys/boot/efi/libefi/handles.c (revision 292005)
+++ sys/boot/efi/libefi/handles.c (working copy)
@@ -35,6 +35,7 @@ struct entry {
EFI_HANDLE alias;
struct devsw *dev;
int unit;
+ uint64_t extra;
};
struct entry *entry;
@@ -79,7 +80,7 @@ efi_find_handle(struct devsw *dev, int unit)
}
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;
@@ -90,7 +91,28 @@ int
*dev = entry[idx].dev;
if (unit != NULL)
*unit = entry[idx].unit;
+ if (extra != NULL)
+ *extra = entry[idx].extra;
return (0);
}
return (ENOENT);
}
+
+int
+efi_handle_update_dev(EFI_HANDLE h, struct devsw *dev, int unit,
+ uint64_t guid)
+{
+ int idx;
+
+ for (idx = 0; idx < nentries; idx++) {
+ if (entry[idx].handle != h)
+ continue;
+ entry[idx].dev = dev;
+ entry[idx].unit = unit;
+ entry[idx].alias = NULL;
+ entry[idx].extra = guid;
+ return (0);
+ }
+
+ return (ENOENT);
+}
Index: sys/boot/efi/loader/Makefile
===================================================================
--- sys/boot/efi/loader/Makefile (revision 292005)
+++ sys/boot/efi/loader/Makefile (working copy)
@@ -23,6 +23,10 @@ SRCS= autoload.c \
smbios.c \
vers.c
+.if ${MK_ZFS} != "no"
+SRCS+= ${.CURDIR}/../../zfs/zfs.c
+.endif
+
.PATH: ${.CURDIR}/arch/${MACHINE}
# For smbios.c
.PATH: ${.CURDIR}/../../i386/libi386
@@ -35,6 +39,11 @@ CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
CFLAGS+= -I${.CURDIR}/../../i386/libi386
+.if ${MK_ZFS} != "no"
+CFLAGS+= -I${.CURDIR}/../../zfs
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
+CFLAGS+= -DZFS_EFI_BOOT
+.endif
CFLAGS+= -DNO_PCI -DEFI
# make buildenv doesn't set DESTDIR, this means LIBSTAND
@@ -67,7 +76,7 @@ HAVE_BCACHE= yes
CFLAGS+= -DEFI_STAGING_SIZE=${EFI_STAGING_SIZE}
.endif
-# Always add MI sources
+# Always add MI sources
.PATH: ${.CURDIR}/../../common
.include "${.CURDIR}/../../common/Makefile.inc"
CFLAGS+= -I${.CURDIR}/../../common
Index: sys/boot/efi/loader/conf.c
===================================================================
--- sys/boot/efi/loader/conf.c (revision 292005)
+++ sys/boot/efi/loader/conf.c (working copy)
@@ -31,14 +31,23 @@ __FBSDID("$FreeBSD$");
#include <bootstrap.h>
#include <efi.h>
#include <efilib.h>
+#ifdef ZFS_EFI_BOOT
+#include "../zfs/libzfs.h"
+#endif
struct devsw *devsw[] = {
&efipart_dev,
&efinet_dev,
+#ifdef ZFS_EFI_BOOT
+ &zfs_dev,
+#endif
NULL
};
struct fs_ops *file_system[] = {
+#ifdef ZFS_EFI_BOOT
+ &zfs_fsops,
+#endif
&dosfs_fsops,
&ufs_fsops,
&cd9660_fsops,
Index: sys/boot/efi/loader/devicename.c
===================================================================
--- sys/boot/efi/loader/devicename.c (revision 292005)
+++ sys/boot/efi/loader/devicename.c (working copy)
@@ -31,7 +31,11 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include <string.h>
#include <sys/disklabel.h>
+#include <sys/param.h>
#include "bootstrap.h"
+#ifdef ZFS_EFI_BOOT
+#include "libzfs.h"
+#endif
#include <efi.h>
#include <efilib.h>
@@ -38,7 +42,7 @@ __FBSDID("$FreeBSD$");
static int efi_parsedev(struct devdesc **, const char *, const char **);
-/*
+/*
* 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.
@@ -84,7 +88,7 @@ efi_parsedev(struct devdesc **dev, const char *dev
struct devsw *dv;
char *cp;
const char *np;
- int i, err;
+ int i;
/* minimum length check */
if (strlen(devspec) < 2)
@@ -99,24 +103,44 @@ efi_parsedev(struct devdesc **dev, const char *dev
if (devsw[i] == NULL)
return (ENOENT);
- idev = malloc(sizeof(struct devdesc));
- if (idev == NULL)
- return (ENOMEM);
+ np = devspec + strlen(dv->dv_name);
- idev->d_dev = dv;
- idev->d_type = dv->dv_type;
- idev->d_unit = -1;
+#ifdef ZFS_EFI_BOOT
+ if (dv->dv_type == DEVT_ZFS) {
+ int err;
- err = 0;
- np = devspec + strlen(dv->dv_name);
- if (*np != '\0' && *np != ':') {
- idev->d_unit = strtol(np, &cp, 0);
- if (cp == np) {
- idev->d_unit = -1;
+ 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 (EUNIT);
+ 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);
+ }
+ }
+#ifdef ZFS_EFI_BOOT
}
+#endif
+
if (*cp != '\0' && *cp != ':') {
free(idev);
return (EINVAL);
@@ -135,9 +159,13 @@ char *
efi_fmtdev(void *vdev)
{
struct devdesc *dev = (struct devdesc *)vdev;
- static char buf[32]; /* XXX device length constant? */
+ static char buf[SPECNAMELEN + 1];
switch(dev->d_type) {
+#ifdef ZFS_EFI_BOOT
+ case DEVT_ZFS:
+ return (zfs_fmtdev(dev));
+#endif
case DEVT_NONE:
strcpy(buf, "(no device)");
break;
@@ -147,7 +175,7 @@ efi_fmtdev(void *vdev)
break;
}
- return(buf);
+ return (buf);
}
/*
@@ -161,7 +189,7 @@ efi_setcurrdev(struct env_var *ev, int flags, cons
rv = efi_parsedev(&ncurr, value, NULL);
if (rv != 0)
- return(rv);
+ return (rv);
free(ncurr);
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
Index: sys/boot/efi/loader/main.c
===================================================================
--- sys/boot/efi/loader/main.c (revision 292005)
+++ sys/boot/efi/loader/main.c (working copy)
@@ -28,6 +28,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/param.h>
#include <stand.h>
#include <string.h>
#include <setjmp.h>
@@ -39,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <smbios.h>
#include "loader_efi.h"
+#include "libzfs.h"
extern char bootprog_name[];
extern char bootprog_rev[];
@@ -45,7 +47,6 @@ extern char bootprog_rev[];
extern char bootprog_date[];
extern char bootprog_maker[];
-struct devdesc currdev; /* our current device */
struct arch_switch archsw; /* MI/MD interface boundary */
EFI_GUID acpi = ACPI_TABLE_GUID;
@@ -61,6 +62,22 @@ EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_G
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_GUID fdtdtb = FDT_TABLE_GUID;
+static void efi_zfs_probe(void);
+
+/*
+ * Need this because EFI uses UTF-16 unicode string constants, but we
+ * use UTF-8. We can't use printf due to the possiblity of \0 and we
+ * don't support support wide characters either.
+ */
+static void
+print_str16(const CHAR16 *str)
+{
+ int i;
+
+ for (i = 0; str[i]; i++)
+ printf("%c", (char)str[i]);
+}
+
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
@@ -67,8 +84,20 @@ main(int argc, CHAR16 *argv[])
char vendor[128];
EFI_LOADED_IMAGE *img;
EFI_GUID *guid;
- int i;
+ int i, unit;
+ struct devsw *dev;
+ uint64_t pool_guid;
+ archsw.arch_autoload = efi_autoload;
+ archsw.arch_getdev = efi_getdev;
+ archsw.arch_copyin = efi_copyin;
+ archsw.arch_copyout = efi_copyout;
+ archsw.arch_readin = efi_readin;
+#ifdef ZFS_EFI_BOOT
+ /* Note this needs to be set before ZFS init. */
+ archsw.arch_zfs_probe = efi_zfs_probe;
+#endif
+
/*
* XXX Chicken-and-egg problem; we want to have console output
* early, but some console attributes may depend on reading from
@@ -92,6 +121,13 @@ main(int argc, CHAR16 *argv[])
/* Get our loaded image protocol interface structure. */
BS->HandleProtocol(IH, &imgid, (VOID**)&img);
+ printf("Command line arguments:");
+ for (i = 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,9 +141,6 @@ main(int argc, CHAR16 *argv[])
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
- efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit);
- currdev.d_type = currdev.d_dev->dv_type;
-
/*
* Disable the watchdog timer. By default the boot manager sets
* the timer to 5 minutes before invoking a boot option. If we
@@ -119,19 +152,44 @@ main(int argc, CHAR16 *argv[])
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
- env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
- efi_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
- env_nounset);
+ if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid) != 0)
+ return (EFI_NOT_FOUND);
+ switch (dev->dv_type) {
+#ifdef ZFS_EFI_BOOT
+ case DEVT_ZFS: {
+ struct zfs_devdesc currdev;
+
+ currdev.d_dev = dev;
+ currdev.d_unit = unit;
+ currdev.d_type = currdev.d_dev->dv_type;
+ currdev.d_opendata = NULL;
+ currdev.pool_guid = pool_guid;
+ currdev.root_guid = 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;
+ }
+#endif
+ default: {
+ struct devdesc currdev;
+
+ currdev.d_dev = dev;
+ currdev.d_unit = unit;
+ currdev.d_opendata = NULL;
+ currdev.d_type = 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;
+ }
+ }
+
setenv("LINES", "24", 1); /* optional */
- 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 < ST->NumberOfTableEntries; i++) {
guid = &ST->ConfigurationTable[i].VendorGuid;
if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
@@ -204,50 +262,47 @@ command_memmap(int argc, char *argv[])
status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
if (status != EFI_BUFFER_TOO_SMALL) {
printf("Can't determine memory map size\n");
- return CMD_ERROR;
+ return (CMD_ERROR);
}
map = malloc(sz);
status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
if (EFI_ERROR(status)) {
printf("Can't read memory map\n");
- return CMD_ERROR;
+ return (CMD_ERROR);
}
ndesc = sz / dsz;
printf("%23s %12s %12s %8s %4s\n",
- "Type", "Physical", "Virtual", "#Pages", "Attr");
+ "Type", "Physical", "Virtual", "#Pages", "Attr");
for (i = 0, p = map; i < ndesc;
- i++, p = NextMemoryDescriptor(p, dsz)) {
- printf("%23s %012lx %012lx %08lx ",
- types[p->Type],
- p->PhysicalStart,
- p->VirtualStart,
- p->NumberOfPages);
- if (p->Attribute & EFI_MEMORY_UC)
- printf("UC ");
- if (p->Attribute & EFI_MEMORY_WC)
- printf("WC ");
- if (p->Attribute & EFI_MEMORY_WT)
- printf("WT ");
- if (p->Attribute & EFI_MEMORY_WB)
- printf("WB ");
- if (p->Attribute & EFI_MEMORY_UCE)
- printf("UCE ");
- if (p->Attribute & EFI_MEMORY_WP)
- printf("WP ");
- if (p->Attribute & EFI_MEMORY_RP)
- printf("RP ");
- if (p->Attribute & EFI_MEMORY_XP)
- printf("XP ");
- printf("\n");
+ i++, p = NextMemoryDescriptor(p, dsz)) {
+ printf("%23s %012lx %012lx %08lx ", types[p->Type],
+ p->PhysicalStart, p->VirtualStart, p->NumberOfPages);
+ if (p->Attribute & EFI_MEMORY_UC)
+ printf("UC ");
+ if (p->Attribute & EFI_MEMORY_WC)
+ printf("WC ");
+ if (p->Attribute & EFI_MEMORY_WT)
+ printf("WT ");
+ if (p->Attribute & EFI_MEMORY_WB)
+ printf("WB ");
+ if (p->Attribute & EFI_MEMORY_UCE)
+ printf("UCE ");
+ if (p->Attribute & EFI_MEMORY_WP)
+ printf("WP ");
+ if (p->Attribute & EFI_MEMORY_RP)
+ printf("RP ");
+ if (p->Attribute & EFI_MEMORY_XP)
+ printf("XP ");
+ printf("\n");
}
- return CMD_OK;
+ return (CMD_OK);
}
-COMMAND_SET(configuration, "configuration",
- "print configuration tables", command_configuration);
+COMMAND_SET(configuration, "configuration", "print configuration tables",
+ command_configuration);
static const char *
guid_to_string(EFI_GUID *guid)
@@ -295,7 +350,7 @@ command_configuration(int argc, char *argv[])
printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
}
- return CMD_OK;
+ return (CMD_OK);
}
@@ -370,8 +425,7 @@ command_nvram(int argc, char *argv[])
status = RS->GetNextVariableName(&varsz, NULL, NULL);
for (; status != EFI_NOT_FOUND; ) {
- status = RS->GetNextVariableName(&varsz, var,
- &varguid);
+ status = RS->GetNextVariableName(&varsz, var, &varguid);
//if (EFI_ERROR(status))
//break;
@@ -378,12 +432,10 @@ command_nvram(int argc, char *argv[])
conout->OutputString(conout, var);
printf("=");
datasz = 0;
- status = RS->GetVariable(var, &varguid, NULL, &datasz,
- NULL);
+ status = RS->GetVariable(var, &varguid, NULL, &datasz, NULL);
/* XXX: check status */
data = malloc(datasz);
- status = RS->GetVariable(var, &varguid, NULL, &datasz,
- data);
+ status = RS->GetVariable(var, &varguid, NULL, &datasz, data);
if (EFI_ERROR(status))
printf("<error retrieving variable>");
else {
@@ -402,6 +454,27 @@ command_nvram(int argc, char *argv[])
return (CMD_OK);
}
+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 != 2) {
+ command_errmsg = "wrong number of arguments";
+ return (CMD_ERROR);
+ }
+
+ err = zfs_list(argv[1]);
+ if (err != 0) {
+ command_errmsg = strerror(err);
+ return (CMD_ERROR);
+ }
+ return (CMD_OK);
+}
+
#ifdef LOADER_FDT_SUPPORT
extern int command_fdt_internal(int argc, char *argv[]);
@@ -415,8 +488,27 @@ static int
command_fdt(int argc, char *argv[])
{
+
return (command_fdt_internal(argc, argv));
}
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
#endif
+
+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);
+ }
+}
Index: sys/boot/zfs/zfs.c
===================================================================
--- sys/boot/zfs/zfs.c (revision 292005)
+++ sys/boot/zfs/zfs.c (working copy)
@@ -140,7 +140,7 @@ zfs_read(struct open_file *f, void *start, size_t
n = size;
if (fp->f_seekp + n > sb.st_size)
n = sb.st_size - fp->f_seekp;
-
+
rc = dnode_read(spa, &fp->f_dnode, fp->f_seekp, start, n);
if (rc)
return (rc);
@@ -493,7 +493,7 @@ zfs_probe_dev(const char *devname, uint64_t *pool_
}
}
close(pa.fd);
- return (0);
+ return (ret);
}
/*

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
320551
Default Alt Text
efi-zfs.patch (43 KB)

Event Timeline