Date: Fri, 23 Oct 2015 07:18:59 -0400 From: Eric McCorkle <eric@metricspace.net> To: freebsd-hackers@freebsd.org Subject: Re: EFI/ZFS Update: successful tests, need more complex vdevs Message-ID: <562A17A3.6090803@metricspace.net> In-Reply-To: <201510220733.32997.ganael.laplanche@corp.ovh.com> References: <56211825.3080403@metricspace.net> <201510211345.29460.ganael.laplanche@corp.ovh.com> <5ED4AE5E-8508-409B-B323-2CBFEBE77088@metricspace.net> <201510220733.32997.ganael.laplanche@corp.ovh.com>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --]
This is a patch pulled fresh from my /usr/src after an svn update.
Therefore, it should represent a patch against the current head
On 10/22/15 01:33, Ganael Laplanche wrote:
> On Wednesday, October 21, 2015 05:28:52 PM Eric McCorkle wrote:
>
> Hi Eric,
>
>> Based on these tests, the reports of successful testing of UFS loading, the
>> fact that PCBSD and NextBSD have apparently picked it up, and the fact
>> that I've been using it for months, I think it's time to move towards
>> getting it committed.
>>
>> I'll post an updated patch by the end of the week.
>
> Good news :)
>
> Best regards,
>
[-- Attachment #2 --]
Index: sys/boot/efi/boot1/Makefile
===================================================================
--- sys/boot/efi/boot1/Makefile (revision 289821)
+++ sys/boot/efi/boot1/Makefile (working copy)
@@ -13,7 +13,7 @@
INTERNALPROG=
# architecture-specific loader code
-SRCS= boot1.c self_reloc.c start.S
+SRCS= boot1.c self_reloc.c start.S ufs_module.c zfs_module.c
CFLAGS+= -I.
CFLAGS+= -I${.CURDIR}/../include
@@ -20,6 +20,8 @@
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
+CFLAGS+= -I${.CURDIR}/../../zfs/
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs/
# 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 289821)
+++ 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$");
#include <sys/param.h>
-#include <sys/dirent.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
@@ -28,6 +29,8 @@
#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 @@
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);
@@ -62,9 +71,80 @@
static EFI_SYSTEM_TABLE *systab;
static EFI_HANDLE *image;
-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) !=
+ EFI_SUCCESS) {
+ printf("Can't allocate memory pool\n");
+ return NULL;
+ }
+ return out;
+}
+
+char* strcpy(char* dst, const char* src) {
+ for(int i = 0; src[i]; i++)
+ dst[i] = src[i];
+
+ return dst;
+}
+
+char* strchr(const char* s, int c) {
+ for(int 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)
+{
+ for (int 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;
+}
+
+char* strdup(const char* s) {
+ int len;
+
+ for(len = 1; s[len]; len++);
+
+ char* out = malloc(len);
+
+ for(int 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;
+
+ for (int 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;
char *d = dst;
@@ -72,23 +152,24 @@
*d++ = *s++;
}
-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;
}
-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
-strcmp(const char *s1, const char *s2)
+int strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2 && *s1; s1++, s2++)
;
@@ -95,30 +176,99 @@
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 ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
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)
+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 = mod->load(devs, ndevs, _PATH_LOADER, &idx, &bufsize);
+ EFI_HANDLE loaderhandle;
+ EFI_LOADED_IMAGE *loaded_image;
+
+ if (NULL == 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].devpath,
+ buffer, bufsize, &loaderhandle) !=
+ EFI_SUCCESS) {
+ //printf("failed\n");
+ return;
+ }
+ //printf("success\n"
+ // "Preparing to execute image...");
+
+ if (systab->BootServices->HandleProtocol(loaderhandle,
+ &LoadedImageGUID,
+ (VOID**)&loaded_image) !=
+ EFI_SUCCESS) {
+ //printf("failed\n");
+ return;
+ }
+
+ //printf("success\n");
+
+ loaded_image->DeviceHandle = devs[idx].devhandle;
+
+ //printf("Image prepared, attempting to execute\n");
+ // XXX Set up command args first
+ if (systab->BootServices->StartImage(loaderhandle, NULL, NULL) !=
+ 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 = sizeof(handles), cols, rows, max_dim, best_mode;
+ UINTN nparts = sizeof(handles);
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;
+ // Basic initialization
systab = Xsystab;
image = Ximage;
+ for(int i = 0; i < NUM_BOOT_MODULES; i++)
+ {
+ dev_offsets[i] = 0;
+ }
+
+ // Set up the console, so printf works.
BS = systab->BootServices;
status = 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 = systab->ConOut;
conout->Reset(conout, TRUE);
max_dim = best_mode = 0;
- for (i = 0; ; i++) {
+ for (int i = 0; ; i++) {
status = conout->QueryMode(conout, i,
&cols, &rows);
if (EFI_ERROR(status))
@@ -141,6 +295,7 @@
best_mode = i;
}
}
+
if (max_dim > 0)
conout->SetMode(conout, best_mode);
conout->EnableCursor(conout, TRUE);
@@ -147,206 +302,94 @@
conout->ClearScreen(conout);
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);
+ printf(" Initializing modules:");
+ for(int i = 0; i < NUM_BOOT_MODULES; i++)
+ {
+ if (NULL != 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 = systab->BootServices->LocateHandle(ByProtocol,
&BlockIoProtocolGUID, NULL, &nparts, handles);
nparts /= sizeof(handles[0]);
+ //printf(" Scanning %lu device handles\n", nparts);
- for (i = 0; i < nparts; i++) {
+ // Scan all partitions, probing with all modules.
+ for (int 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))
+ if (EFI_ERROR(status)) {
+ //printf(" Not a device path protocol\n");
continue;
+ }
- while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+ while (!IsDevicePathEnd(NextDevicePathNode(devpath))) {
+ //printf(" Advancing to next device\n");
devpath = NextDevicePathNode(devpath);
+ }
status = systab->BootServices->HandleProtocol(handles[i],
&BlockIoProtocolGUID, (void **)&blkio);
- if (EFI_ERROR(status))
+ if (EFI_ERROR(status)) {
+ //printf(" Not a block device\n");
continue;
+ }
- if (!blkio->Media->LogicalPartition)
+ if (!blkio->Media->LogicalPartition) {
+ //printf(" Logical partition\n");
continue;
+ }
- if (domount(devpath, blkio, 1) >= 0)
- break;
- }
+ // Setup devinfo
+ devinfo.dev = blkio;
+ devinfo.devpath = devpath;
+ devinfo.devhandle = handles[i];
+ devinfo.devdata = NULL;
- 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;
- }
- 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;
+ // Run through each module, see if it can load this partition
+ for (int j = 0; j < NUM_BOOT_MODULES; j++ )
+ {
+ if (NULL != 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]++] = devinfo;
+ }
+ }
}
- size = DIP(di_size);
- n = size - fs_off;
- return (n);
-}
-static struct dmadat __dmadat;
+ // Select a partition to boot. We do this by trying each
+ // module in order.
+ for (int i = 0; i < NUM_BOOT_MODULES; i++)
+ {
+ if (NULL != boot_modules[i])
+ {
+ //printf(" Trying to load from %lu %s partitions\n",
+ // dev_offsets[i], boot_modules[i]->name);
+ try_load(boot_modules[i], module_devs[i],
+ dev_offsets[i]);
+ //printf(" Failed\n");
+ }
+ }
-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);
- }
- if (!quiet)
- printf("Succesfully mounted UFS filesystem\n");
- return (0);
+ // If we get here, we're out of luck...
+ panic("No bootable partitions found!");
}
-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 = 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);
-}
-
-static void
-panic(const char *fmt, ...)
-{
char buf[128];
va_list ap;
@@ -358,50 +401,25 @@
while (1) {}
}
-static int
-printf(const char *fmt, ...)
+int printf(const char *fmt, ...)
{
va_list ap;
int ret;
- /* Don't annoy the user as we probe for partitions */
- if (strcmp(fmt,"Not ufs\n") == 0)
- 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;
Index: sys/boot/efi/include/efilib.h
===================================================================
--- sys/boot/efi/include/efilib.h (revision 289821)
+++ sys/boot/efi/include/efilib.h (working copy)
@@ -43,7 +43,8 @@
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 *);
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 289821)
+++ sys/boot/efi/libefi/handles.c (working copy)
@@ -35,6 +35,7 @@
EFI_HANDLE alias;
struct devsw *dev;
int unit;
+ uint64_t extra;
};
struct entry *entry;
@@ -78,8 +79,28 @@
return (NULL);
}
+void efi_handle_update_dev(const EFI_HANDLE handle,
+ struct devsw * const dev,
+ int unit,
+ uint64_t guid)
+{
+ int idx;
+
+ for (idx = 0; idx < nentries; idx++) {
+ if (entry[idx].handle != handle)
+ continue;
+ entry[idx].dev = dev;
+ entry[idx].unit = unit;
+ entry[idx].alias = NULL;
+ entry[idx].extra = 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;
@@ -90,6 +111,8 @@
*dev = entry[idx].dev;
if (unit != NULL)
*unit = entry[idx].unit;
+ if (extra != NULL)
+ *extra = entry[idx].extra;
return (0);
}
return (ENOENT);
Index: sys/boot/efi/loader/Makefile
===================================================================
--- sys/boot/efi/loader/Makefile (revision 289821)
+++ sys/boot/efi/loader/Makefile (working copy)
@@ -21,7 +21,8 @@
main.c \
self_reloc.c \
smbios.c \
- vers.c
+ vers.c \
+ ${.CURDIR}/zfs.c
.PATH: ${.CURDIR}/arch/${MACHINE}
# For smbios.c
@@ -35,6 +36,8 @@
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
CFLAGS+= -I${.CURDIR}/../../i386/libi386
+CFLAGS+= -I${.CURDIR}/../../zfs
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
CFLAGS+= -DNO_PCI -DEFI
# make buildenv doesn't set DESTDIR, this means LIBSTAND
@@ -67,7 +70,7 @@
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
@@ -78,7 +81,7 @@
LDSCRIPT= ${.CURDIR}/arch/${MACHINE}/ldscript.${MACHINE}
LDFLAGS+= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared
-CLEANFILES+= vers.c loader.efi
+CLEANFILES+= zfs.c vers.c loader.efi
NEWVERSWHAT= "EFI loader" ${MACHINE}
@@ -85,6 +88,9 @@
vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../../efi/loader/version
sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
+zfs.c:
+ cp ${.CURDIR}/../../zfs/zfs.c ${.CURDIR}
+
OBJCOPY?= objcopy
OBJDUMP?= objdump
@@ -108,9 +114,9 @@
LIBEFI= ${.OBJDIR}/../libefi/libefi.a
-DPADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND} \
+DPADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ../../../../lib/libstand/libstand.a \
${LDSCRIPT}
-LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND}
+LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ../../../../lib/libstand/libstand.a
.endif # ${COMPILER_TYPE} != "gcc"
Index: sys/boot/efi/loader/conf.c
===================================================================
--- sys/boot/efi/loader/conf.c (revision 289821)
+++ 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"
struct devsw *devsw[] = {
&efipart_dev,
&efinet_dev,
+ &zfs_dev,
NULL
};
struct fs_ops *file_system[] = {
+ &zfs_fsops,
&dosfs_fsops,
&ufs_fsops,
&cd9660_fsops,
Index: sys/boot/efi/loader/devicename.c
===================================================================
--- sys/boot/efi/loader/devicename.c (revision 289821)
+++ 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"
#include <efi.h>
#include <efilib.h>
@@ -38,7 +39,7 @@
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.
@@ -48,7 +49,6 @@
{
struct devdesc **dev = (struct devdesc **)vdev;
int rv;
-
/*
* If it looks like this is just a path and no device, then
* use the current device instead.
@@ -61,7 +61,8 @@
}
/* Parse the device name off the beginning of the devspec. */
- return (efi_parsedev(dev, devspec, path));
+ const int out = efi_parsedev(dev, devspec, path);
+ return out;
}
/*
@@ -87,8 +88,9 @@
int i, err;
/* minimum length check */
- if (strlen(devspec) < 2)
+ if (strlen(devspec) < 2) {
return (EINVAL);
+ }
/* look for a device that matches */
for (i = 0; devsw[i] != NULL; i++) {
@@ -96,27 +98,39 @@
if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name)))
break;
}
- if (devsw[i] == NULL)
+ if (devsw[i] == NULL) {
return (ENOENT);
+ }
+ np = devspec + strlen(dv->dv_name);
- idev = malloc(sizeof(struct devdesc));
- if (idev == NULL)
- return (ENOMEM);
+ if (DEVT_ZFS == dv->dv_type) {
+ idev = malloc(sizeof(struct zfs_devdesc));
+ int out = zfs_parsedev((struct zfs_devdesc*)idev, np, path);
+ if (0 == out) {
+ *dev = idev;
+ cp = strchr(np + 1, ':');
+ } else {
+ free(idev);
+ return out;
+ }
+ } else {
+ idev = malloc(sizeof(struct devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
- idev->d_dev = dv;
- idev->d_type = dv->dv_type;
- idev->d_unit = -1;
-
+ 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);
+ }
+ }
+ }
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;
- free(idev);
- return (EUNIT);
- }
- }
if (*cp != '\0' && *cp != ':') {
free(idev);
return (EINVAL);
@@ -138,10 +152,11 @@
static char buf[32]; /* XXX device length constant? */
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
===================================================================
--- sys/boot/efi/loader/main.c (revision 289821)
+++ sys/boot/efi/loader/main.c (working copy)
@@ -39,6 +39,7 @@
#include <smbios.h>
#include "loader_efi.h"
+#include "libzfs.h"
extern char bootprog_name[];
extern char bootprog_rev[];
@@ -45,8 +46,9 @@
extern char bootprog_date[];
extern char bootprog_maker[];
-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;
EFI_GUID acpi = ACPI_TABLE_GUID;
EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
@@ -61,6 +63,70 @@
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_GUID fdtdtb = FDT_TABLE_GUID;
+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 = 0; a[i] || b[i]; i++)
+ {
+ const CHAR16 achr = a[i];
+ const CHAR16 bchr = b[i];
+ if (achr < bchr)
+ {
+ return -1;
+ } else if (achr > bchr)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// Split an arg of the form "argname=argval", replacing the '=' with a \0
+static CHAR16*
+split_arg(CHAR16 *const str)
+{
+ for (int i = 0; str[i]; i++)
+ {
+ if ('=' == str[i])
+ {
+ str[i] = 0;
+ return str + i + 1;
+ }
+ }
+ return NULL;
+}
+
+static void
+handle_arg(CHAR16 *const arg)
+{
+ const CHAR16* const argval = split_arg(arg);
+ const CHAR16* const argname = arg;
+
+ if (NULL != 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;
- /*
+ 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;
+ // Note this needs to be set before ZFS init
+ archsw.arch_zfs_probe = 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 = 0; devsw[i] != NULL; i++)
- if (devsw[i]->dv_init != NULL)
+ for (i = 0; devsw[i] != NULL; i++) {
+ if (devsw[i]->dv_init != 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);
+ 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,8 +188,13 @@
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;
+ // Handle command-line arguments
+ /*
+ for(i = 1; i < argc; i++)
+ {
+ handle_arg(argv[i]);
+ }
+ */
/*
* Disable the watchdog timer. By default the boot manager sets
@@ -119,19 +207,39 @@
*/
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);
+ 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 = 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;
+ 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))) {
@@ -350,7 +458,6 @@
return (CMD_OK);
}
-
COMMAND_SET(nvram, "nvram", "get or set NVRAM variables", command_nvram);
static int
@@ -402,6 +509,27 @@
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[]);
@@ -420,3 +548,23 @@
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 = 0;
+ char devname[32];
+ uint64_t pool_guid;
+
+ for (int i = 0, h = efi_find_handle(&efipart_dev, 0);
+ h != NULL; h = efi_find_handle(&efipart_dev, ++i)) {
+ snprintf(devname, sizeof devname, "%s%d:",
+ efipart_dev.dv_name, i);
+ if(0 == zfs_probe_dev(devname, &pool_guid)) {
+ efi_handle_update_dev(h, &zfs_dev, unit++, pool_guid);
+ }
+ }
+}
Index: sys/boot/zfs/zfs.c
===================================================================
--- sys/boot/zfs/zfs.c (revision 289821)
+++ sys/boot/zfs/zfs.c (working copy)
@@ -140,7 +140,7 @@
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 @@
}
}
close(pa.fd);
- return (0);
+ return (ret);
}
/*
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?562A17A3.6090803>
