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>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------070902030409020404010705 Content-Type: text/plain; charset=iso-8859-15; format=flowed Content-Transfer-Encoding: 7bit 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, > --------------070902030409020404010705 Content-Type: text/x-patch; name="zfs_efi_curr.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="zfs_efi_curr.diff" 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); } /* --------------070902030409020404010705--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?562A17A3.6090803>