Date: Mon, 08 Jun 2015 18:59:36 -0400 From: Eric McCorkle <eric@metricspace.net> To: freebsd-hackers@freebsd.org Subject: Re: EFI ZFS loader successful load and boot Message-ID: <55761E58.6040704@metricspace.net> In-Reply-To: <98598C0A-D09A-4BC7-A15C-5422BBA2EE4C@gmail.com> References: <5560F4FE.4030502@metricspace.net> <5560F743.9000507@metricspace.net> <7CD9D028-8BCE-4361-966B-140642BAE341@metricspace.net> <98598C0A-D09A-4BC7-A15C-5422BBA2EE4C@gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --9mXtQcxIOTeBwJJoa4u3PEkLG2JCiT7t8 Content-Type: multipart/mixed; boundary="------------040508010102090007040903" This is a multi-part message in MIME format. --------------040508010102090007040903 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable OK, finally got time to turn the knobs. This patch should make it through a buildworld. I will at some point add functionality to boot1 to actually check the partition type GUIDs. That aside, this is ready for testing, and I've been EFI-booting a ZFS partition from GRUB using this patch for a while now. On 05/26/2015 10:22 AM, Garrett Cooper wrote: >=20 >> On May 26, 2015, at 05:34, Eric McCorkle <eric@metricspace.net> wrote:= >> >> Updates: with a new kernel, and the vt terminal, this works fine.=20 >> >> Unfortunately, the patch doesn't seem to work with a buildworld build = (I was doing make from within the directories). This is related to a hack= I do of copying zfs.c into the efi loader directory so it can be built w= ith fPIC. The build system seems to get tripped up in mkdep as a result. = >> >> Could someone with more knowledge of the build system give me some poi= nters here? Otherwise, is all set for testing. >=20 > DPSRCS/CLEANFILES are probably the knobs you're looking for... > _______________________________________________ > freebsd-hackers@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-hackers > To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.o= rg" >=20 --------------040508010102090007040903 Content-Type: text/x-patch; name="zfsefi.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="zfsefi.diff" Index: sys/boot/efi/boot1/Makefile =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/boot1/Makefile (revision 283525) +++ sys/boot/efi/boot1/Makefile (working copy) @@ -13,7 +13,7 @@ INTERNALPROG=3D =20 # architecture-specific loader code -SRCS=3D boot1.c self_reloc.c start.S +SRCS=3D boot1.c self_reloc.c start.S ufs_module.c zfs_module.c =20 CFLAGS+=3D -I. CFLAGS+=3D -I${.CURDIR}/../include @@ -20,6 +20,8 @@ CFLAGS+=3D -I${.CURDIR}/../include/${MACHINE} CFLAGS+=3D -I${.CURDIR}/../../../contrib/dev/acpica/include CFLAGS+=3D -I${.CURDIR}/../../.. +CFLAGS+=3D -I${.CURDIR}/../../zfs/ +CFLAGS+=3D -I${.CURDIR}/../../../cddl/boot/zfs/ =20 # Always add MI sources and REGULAR efi loader bits .PATH: ${.CURDIR}/../loader/arch/${MACHINE} Index: sys/boot/efi/boot1/boot1.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/boot1/boot1.c (revision 283525) +++ sys/boot/efi/boot1/boot1.c (working copy) @@ -5,6 +5,8 @@ * All rights reserved. * Copyright (c) 2014 Nathan Whitehorn * All rights reserved. + * Copyright (c) 2014 Eric McCorkle + * All rights reverved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this @@ -21,7 +23,6 @@ __FBSDID("$FreeBSD$"); =20 #include <sys/param.h> -#include <sys/dirent.h> #include <machine/elf.h> #include <machine/stdarg.h> =20 @@ -28,6 +29,8 @@ #include <efi.h> #include <eficonsctl.h> =20 +#include "boot_module.h" + #define _PATH_LOADER "/boot/loader.efi" #define _PATH_KERNEL "/boot/kernel/kernel" =20 @@ -41,14 +44,20 @@ u_int sp_size; }; =20 +static const boot_module_t* const boot_modules[] =3D +{ +#ifdef ZFS_EFI_BOOT + &zfs_module, +#endif +#ifdef UFS_EFI_BOOT + &ufs_module +#endif +}; + +#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*))= + static const char digits[] =3D "0123456789abcdef"; =20 -static void panic(const char *fmt, ...) __dead2; -static int printf(const char *fmt, ...); -static int putchar(char c, void *arg); -static int vprintf(const char *fmt, va_list ap); -static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);= - static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_li= st ap); static int __putc(char c, void *arg); static int __puts(const char *s, putc_func_t *putc, void *arg); @@ -62,9 +71,80 @@ static EFI_SYSTEM_TABLE *systab; static EFI_HANDLE *image; =20 -static void -bcopy(const void *src, void *dst, size_t len) + +void* Malloc(size_t len, const char* file, int line) { + void* out; + if (systab->BootServices->AllocatePool(EfiLoaderData, + len, &out) !=3D + EFI_SUCCESS) { + printf("Can't allocate memory pool\n"); + return NULL; + } + return out; +} + +char* strcpy(char* dst, const char* src) { + for(int i =3D 0; src[i]; i++) + dst[i] =3D src[i]; + + return dst; +} + +char* strchr(const char* s, int c) { + for(int i =3D 0; s[i]; i++) + if (s[i] =3D=3D c) + return (char*)(s + i); + + return NULL; +} + +int strncmp(const char *a, const char *b, size_t len) +{ + for (int i =3D 0; i < len; i++) + if(a[i] =3D=3D '\0' && b[i] =3D=3D '\0') { + return 0; + } else if(a[i] < b[i]) { + return -1; + } else if(a[i] > b[i]) { + return 1; + } + + return 0; +} + +char* strdup(const char* s) { + int len; + + for(len =3D 1; s[len]; len++); + + char* out =3D malloc(len); + + for(int i =3D 0; i < len; i++) + out[i] =3D s[i]; + + return out; +} + +int bcmp(const void *a, const void *b, size_t len) +{ + const char *sa =3D a; + const char *sb =3D b; + + for (int i =3D 0; i < len; i++) + if(sa[i] !=3D sb[i]) + return 1; + + return 0; +} + +int memcmp(const void *a, const void *b, size_t len) +{ + return bcmp(a, b, len); +} + +void bcopy(const void *src, void *dst, size_t len) +{ const char *s =3D src; char *d =3D dst; =20 @@ -72,23 +152,24 @@ *d++ =3D *s++; } =20 -static void -memcpy(void *dst, const void *src, size_t len) +void* memcpy(void *dst, const void *src, size_t len) { bcopy(src, dst, len); + return dst; } =20 -static void -bzero(void *b, size_t len) + +void* memset(void *b, int val, size_t len) { char *p =3D b; =20 while (len-- !=3D 0) - *p++ =3D 0; + *p++ =3D val; + + return b; } =20 -static int -strcmp(const char *s1, const char *s2) +int strcmp(const char *s1, const char *s2) { for (; *s1 =3D=3D *s2 && *s1; s1++, s2++) ; @@ -95,30 +176,99 @@ return ((u_char)*s1 - (u_char)*s2); } =20 +int putchr(char c, void *arg) +{ + CHAR16 buf[2]; + + if (c =3D=3D '\n') { + buf[0] =3D '\r'; + buf[1] =3D 0; + systab->ConOut->OutputString(systab->ConOut, buf); + } + buf[0] =3D c; + buf[1] =3D 0; + systab->ConOut->OutputString(systab->ConOut, buf); + return (1); +} + static EFI_GUID BlockIoProtocolGUID =3D BLOCK_IO_PROTOCOL; static EFI_GUID DevicePathGUID =3D DEVICE_PATH_PROTOCOL; +static EFI_GUID ConsoleControlGUID =3D EFI_CONSOLE_CONTROL_PROTOCOL_GUID= ; static EFI_GUID LoadedImageGUID =3D LOADED_IMAGE_PROTOCOL; -static EFI_GUID ConsoleControlGUID =3D EFI_CONSOLE_CONTROL_PROTOCOL_GUID= ; =20 -static EFI_BLOCK_IO *bootdev; -static EFI_DEVICE_PATH *bootdevpath; -static EFI_HANDLE *bootdevhandle; +#define MAX_DEVS 128 =20 -EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) +void try_load(const boot_module_t* const mod, + const dev_info_t devs[], + size_t ndevs) { - EFI_HANDLE handles[128]; + int idx; + size_t bufsize; + void* const buffer =3D mod->load(devs, ndevs, _PATH_LOADER, &idx= , &bufsize); + EFI_HANDLE loaderhandle; + EFI_LOADED_IMAGE *loaded_image; + + if (NULL =3D=3D buffer) { + printf("Could not load file\n"); + return; + } + //printf("Loaded file %s, image at %p\n" + // "Attempting to load as bootable image...", + // _PATH_LOADER, image); + if (systab->BootServices->LoadImage(TRUE, image, devs[idx].devpa= th, + buffer, bufsize, &loaderhand= le) !=3D + EFI_SUCCESS) { + //printf("failed\n"); + return; + } + //printf("success\n" + // "Preparing to execute image..."); + + if (systab->BootServices->HandleProtocol(loaderhandle, + &LoadedImageGUID, + (VOID**)&loaded_image) = !=3D + EFI_SUCCESS) { + //printf("failed\n"); + return; + } + + //printf("success\n"); + + loaded_image->DeviceHandle =3D devs[idx].devhandle; + + //printf("Image prepared, attempting to execute\n"); + // XXX Set up command args first + if (systab->BootServices->StartImage(loaderhandle, NULL, NULL) != =3D + EFI_SUCCESS) { + //printf("Failed to execute loader\n"); + return; + } + //printf("Shouldn't be here!\n"); +} + +void efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) +{ + EFI_HANDLE handles[MAX_DEVS]; + dev_info_t module_devs[NUM_BOOT_MODULES][MAX_DEVS]; + size_t dev_offsets[NUM_BOOT_MODULES]; EFI_BLOCK_IO *blkio; - UINTN i, nparts =3D sizeof(handles), cols, rows, max_dim, best_mode; + UINTN nparts =3D sizeof(handles); EFI_STATUS status; EFI_DEVICE_PATH *devpath; EFI_BOOT_SERVICES *BS; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl =3D NULL; SIMPLE_TEXT_OUTPUT_INTERFACE *conout =3D NULL; - char *path =3D _PATH_LOADER; =20 + // Basic initialization systab =3D Xsystab; image =3D Ximage; =20 + for(int i =3D 0; i < NUM_BOOT_MODULES; i++) + { + dev_offsets[i] =3D 0; + } + + // Set up the console, so printf works. BS =3D systab->BootServices; status =3D BS->LocateProtocol(&ConsoleControlGUID, NULL, (VOID **)&ConsoleControl); @@ -128,10 +278,14 @@ /* * Reset the console and find the best text mode. */ + UINTN max_dim; + UINTN best_mode; + UINTN cols; + UINTN rows; conout =3D systab->ConOut; conout->Reset(conout, TRUE); max_dim =3D best_mode =3D 0; - for (i =3D 0; ; i++) { + for (int i =3D 0; ; i++) { status =3D conout->QueryMode(conout, i, &cols, &rows); if (EFI_ERROR(status)) @@ -141,6 +295,7 @@ best_mode =3D i; } } + if (max_dim > 0) conout->SetMode(conout, best_mode); conout->EnableCursor(conout, TRUE); @@ -147,206 +302,94 @@ conout->ClearScreen(conout); =20 printf("\n" - ">> FreeBSD EFI boot block\n"); - printf(" Loader path: %s\n", path); + ">> FreeBSD ZFS-enabled EFI boot block\n"); + printf(" Loader path: %s\n\n", _PATH_LOADER); =20 + printf(" Initializing modules:"); + for(int i =3D 0; i < NUM_BOOT_MODULES; i++) + { + if (NULL !=3D boot_modules[i]) + { + printf(" %s", boot_modules[i]->name); + boot_modules[i]->init(image, systab, BS); + } + } + putchr('\n', NULL); + + // Get all the device handles status =3D systab->BootServices->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, &nparts, handles); nparts /=3D sizeof(handles[0]); + //printf(" Scanning %lu device handles\n", nparts); =20 - for (i =3D 0; i < nparts; i++) { + // Scan all partitions, probing with all modules. + for (int i =3D 0; i < nparts; i++) { + dev_info_t devinfo; + + // Figure out if we're dealing with an actual partition status =3D systab->BootServices->HandleProtocol(handles[i], &DevicePathGUID, (void **)&devpath); - if (EFI_ERROR(status)) + if (EFI_ERROR(status)) { + //printf(" Not a device path protocol\n")= ; continue; + } =20 - while (!IsDevicePathEnd(NextDevicePathNode(devpath))) + while (!IsDevicePathEnd(NextDevicePathNode(devpath))) { + //printf(" Advancing to next device\n"); devpath =3D NextDevicePathNode(devpath); + } =20 status =3D systab->BootServices->HandleProtocol(handles[i], &BlockIoProtocolGUID, (void **)&blkio); - if (EFI_ERROR(status)) + if (EFI_ERROR(status)) { + //printf(" Not a block device\n"); continue; + } =20 - if (!blkio->Media->LogicalPartition) + if (!blkio->Media->LogicalPartition) { + //printf(" Logical partition\n"); continue; + } =20 - if (domount(devpath, blkio, 1) >=3D 0) - break; - } + // Setup devinfo + devinfo.dev =3D blkio; + devinfo.devpath =3D devpath; + devinfo.devhandle =3D handles[i]; + devinfo.devdata =3D NULL; =20 - if (i =3D=3D nparts) - panic("No bootable partition found"); - - bootdevhandle =3D handles[i]; - load(path); - - panic("Load failed"); - - return EFI_SUCCESS; -} - -static int -dskread(void *buf, u_int64_t lba, int nblk) -{ - EFI_STATUS status; - int size; - - lba =3D lba / (bootdev->Media->BlockSize / DEV_BSIZE); - size =3D nblk * DEV_BSIZE; - status =3D bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba, - size, buf); - - if (EFI_ERROR(status)) - return (-1); - - return (0); -} - -#include "ufsread.c" - -static ssize_t -fsstat(ufs_ino_t inode) -{ -#ifndef UFS2_ONLY - static struct ufs1_dinode dp1; - ufs1_daddr_t addr1; -#endif -#ifndef UFS1_ONLY - static struct ufs2_dinode dp2; -#endif - static struct fs fs; - static ufs_ino_t inomap; - char *blkbuf; - void *indbuf; - size_t n, nb, size, off, vboff; - ufs_lbn_t lbn; - ufs2_daddr_t addr2, vbaddr; - static ufs2_daddr_t blkmap, indmap; - u_int u; - - blkbuf =3D dmadat->blkbuf; - indbuf =3D dmadat->indbuf; - if (!dsk_meta) { - inomap =3D 0; - for (n =3D 0; sblock_try[n] !=3D -1; n++) { - if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE, - SBLOCKSIZE / DEV_BSIZE)) - return -1; - memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); - if (( -#if defined(UFS1_ONLY) - fs.fs_magic =3D=3D FS_UFS1_MAGIC -#elif defined(UFS2_ONLY) - (fs.fs_magic =3D=3D FS_UFS2_MAGIC && - fs.fs_sblockloc =3D=3D sblock_try[n]) -#else - fs.fs_magic =3D=3D FS_UFS1_MAGIC || - (fs.fs_magic =3D=3D FS_UFS2_MAGIC && - fs.fs_sblockloc =3D=3D sblock_try[n]) -#endif - ) && - fs.fs_bsize <=3D MAXBSIZE && - fs.fs_bsize >=3D sizeof(struct fs)) - break; - } - if (sblock_try[n] =3D=3D -1) { - printf("Not ufs\n"); - return -1; - } - dsk_meta++; - } else - memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); - if (!inode) - return 0; - if (inomap !=3D inode) { - n =3D IPERVBLK(&fs); - if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK)) - return -1; - n =3D INO_TO_VBO(n, inode); -#if defined(UFS1_ONLY) - memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, - sizeof(struct ufs1_dinode)); -#elif defined(UFS2_ONLY) - memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, - sizeof(struct ufs2_dinode)); -#else - if (fs.fs_magic =3D=3D FS_UFS1_MAGIC) - memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, - sizeof(struct ufs1_dinode)); - else - memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, - sizeof(struct ufs2_dinode)); -#endif - inomap =3D inode; - fs_off =3D 0; - blkmap =3D indmap =3D 0; + // Run through each module, see if it can load this part= ition + for (int j =3D 0; j < NUM_BOOT_MODULES; j++ ) + { + if (NULL !=3D boot_modules[j] && + boot_modules[j]->probe(&devinfo)) + { + // If it can, save it to the device list= for + // that module + module_devs[j][dev_offsets[j]++] =3D dev= info; + } + } } - size =3D DIP(di_size); - n =3D size - fs_off; - return (n); -} =20 -static struct dmadat __dmadat; + // Select a partition to boot. We do this by trying each + // module in order. + for (int i =3D 0; i < NUM_BOOT_MODULES; i++) + { + if (NULL !=3D boot_modules[i]) + { + //printf(" Trying to load from %lu %s partitio= ns\n", + // dev_offsets[i], boot_modules[i]->name);= + try_load(boot_modules[i], module_devs[i], + dev_offsets[i]); + //printf(" Failed\n"); + } + } =20 -static int -domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet) -{ - - dmadat =3D &__dmadat; - bootdev =3D blkio; - bootdevpath =3D device; - if (fsread(0, NULL, 0)) { - if (!quiet) - printf("domount: can't read superblock\n"); - return (-1); - } - if (!quiet) - printf("Succesfully mounted UFS filesystem\n"); - return (0); + // If we get here, we're out of luck... + panic("No bootable partitions found!"); } =20 -static void -load(const char *fname) +void panic(const char *fmt, ...) { - ufs_ino_t ino; - EFI_STATUS status; - EFI_HANDLE loaderhandle; - EFI_LOADED_IMAGE *loaded_image; - void *buffer; - size_t bufsize; - - if ((ino =3D lookup(fname)) =3D=3D 0) { - printf("File %s not found\n", fname); - return; - } - - bufsize =3D fsstat(ino); - status =3D systab->BootServices->AllocatePool(EfiLoaderData, - bufsize, &buffer); - fsread(ino, buffer, bufsize); - - /* XXX: For secure boot, we need our own loader here */ - status =3D systab->BootServices->LoadImage(TRUE, image, bootdevpath, - buffer, bufsize, &loaderhandle); - if (EFI_ERROR(status)) - printf("LoadImage failed with error %lx\n", status); - - status =3D systab->BootServices->HandleProtocol(loaderhandle, - &LoadedImageGUID, (VOID**)&loaded_image); - if (EFI_ERROR(status)) - printf("HandleProtocol failed with error %lx\n", status); - - loaded_image->DeviceHandle =3D bootdevhandle; - - status =3D systab->BootServices->StartImage(loaderhandle, NULL, NULL); - if (EFI_ERROR(status)) - printf("StartImage failed with error %lx\n", status); -} - -static void -panic(const char *fmt, ...) -{ char buf[128]; va_list ap; =20 @@ -358,50 +401,25 @@ while (1) {} } =20 -static int -printf(const char *fmt, ...) +int printf(const char *fmt, ...) { va_list ap; int ret; =20 - /* Don't annoy the user as we probe for partitions */ - if (strcmp(fmt,"Not ufs\n") =3D=3D 0) - return 0; =20 va_start(ap, fmt); - ret =3D vprintf(fmt, ap); + ret =3D __printf(fmt, putchr, 0, ap); va_end(ap); return (ret); } =20 -static int -putchar(char c, void *arg) +void vprintf(const char *fmt, va_list ap) { - CHAR16 buf[2]; - - if (c =3D=3D '\n') { - buf[0] =3D '\r'; - buf[1] =3D 0; - systab->ConOut->OutputString(systab->ConOut, buf); - } - buf[0] =3D c; - buf[1] =3D 0; - systab->ConOut->OutputString(systab->ConOut, buf); - return (1); + __printf(fmt, putchr, 0, ap); } =20 -static int -vprintf(const char *fmt, va_list ap) +int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) { - int ret; - - ret =3D __printf(fmt, putchar, 0, ap); - return (ret); -} - -static int -vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) -{ struct sp_data sp; int ret; =20 Index: sys/boot/efi/boot1/boot_module.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/boot1/boot_module.h (revision 0) +++ sys/boot/efi/boot1/boot_module.h (working copy) @@ -0,0 +1,60 @@ +#ifndef _BOOT_MODULE_H_ +#define _BOOT_MODULE_H_ + +#include <stdbool.h> + +#include <efi.h> +#include <efilib.h> +#include <eficonsctl.h> + +#define UFS_EFI_BOOT 1 +#define ZFS_EFI_BOOT 1 + +// EFI device info +typedef struct dev_info_t +{ + EFI_BLOCK_IO *dev; + EFI_DEVICE_PATH *devpath; + EFI_HANDLE *devhandle; + void *devdata; +} dev_info_t; + +// A boot loader module. This is a standard interface for filesystem +// modules in the EFI system. +typedef struct boot_module_t +{ + const char* const name; + + // Initialize the module. + void (* const init)(EFI_HANDLE image, + EFI_SYSTEM_TABLE* systab, + EFI_BOOT_SERVICES *bootsrv); + + // Check to see if curr_dev is a device that this module can han= dle. + bool (* const probe)(dev_info_t* dev); + + // Select the best out of a set of devices that probe indicated = were + // loadable, and load it. + void* (* const load)(const dev_info_t devs[], + size_t ndevs, + const char* loader_path, + int* idxref, + size_t* bufsizeref); +} boot_module_t; + +// Standard boot modules +#ifdef UFS_EFI_BOOT +extern const boot_module_t ufs_module; +#endif +#ifdef ZFS_EFI_BOOT +extern const boot_module_t zfs_module; +#endif + +// Functions available to modules +extern int strcmp(const char *s1, const char *s2); +extern void bcopy(const void *src, void *dst, size_t len); +extern void panic(const char *fmt, ...) __dead2; +extern int printf(const char *fmt, ...); +extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);= + +#endif Property changes on: sys/boot/efi/boot1/boot_module.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=3D%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: sys/boot/efi/boot1/ufs_module.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/boot1/ufs_module.c (revision 0) +++ sys/boot/efi/boot1/ufs_module.c (working copy) @@ -0,0 +1,210 @@ +/*- + * Copyright (c) 1998 Robert Nordier + * All rights reserved. + * Copyright (c) 2001 Robert Drehmel + * All rights reserved. + * Copyright (c) 2014 Nathan Whitehorn + * All rights reserved. + * Copyright (c) 2015 Eric McCorkle + * All rights reverved. + * + * Redistribution and use in source and binary forms are freely + * permitted provided that the above copyright notice and this + * paragraph and the following disclaimer are duplicated in all + * such forms. + * + * This software is provided "AS IS" and without any express or + * implied warranties, including, without limitation, the implied + * warranties of merchantability and fitness for a particular + * purpose. + */ +#include <stdarg.h> +#include <stdbool.h> + +#include <sys/cdefs.h> +#include <sys/param.h> + +#include <efi.h> + +#include "boot_module.h" + +static EFI_HANDLE image; +static EFI_SYSTEM_TABLE* systab; +static EFI_BOOT_SERVICES *bootsrv; +static dev_info_t devinfo; +static EFI_GUID LoadedImageGUID =3D LOADED_IMAGE_PROTOCOL; + +static int +dskread(void *buf, u_int64_t lba, int nblk) +{ + EFI_STATUS status; + int size; + + lba =3D lba / (devinfo.dev->Media->BlockSize / DEV_BSIZE); + size =3D nblk * DEV_BSIZE; + status =3D devinfo.dev->ReadBlocks(devinfo.dev, + devinfo.dev->Media->MediaId, lb= a, + size, buf); + + if (EFI_ERROR(status)) + return (-1); + + return (0); +} + +#include "ufsread.c" + +static ssize_t +fsstat(ufs_ino_t inode) +{ +#ifndef UFS2_ONLY + static struct ufs1_dinode dp1; + ufs1_daddr_t addr1; +#endif +#ifndef UFS1_ONLY + static struct ufs2_dinode dp2; +#endif + static struct fs fs; + static ufs_ino_t inomap; + char *blkbuf; + void *indbuf; + size_t n, nb, size, off, vboff; + ufs_lbn_t lbn; + ufs2_daddr_t addr2, vbaddr; + static ufs2_daddr_t blkmap, indmap; + u_int u; + + blkbuf =3D dmadat->blkbuf; + indbuf =3D dmadat->indbuf; + if (!dsk_meta) { + inomap =3D 0; + for (n =3D 0; sblock_try[n] !=3D -1; n++) { + if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE, + SBLOCKSIZE / DEV_BSIZE)) + return -1; + memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); + if (( +#if defined(UFS1_ONLY) + fs.fs_magic =3D=3D FS_UFS1_MAGIC +#elif defined(UFS2_ONLY) + (fs.fs_magic =3D=3D FS_UFS2_MAGIC && + fs.fs_sblockloc =3D=3D sblock_try[n]) +#else + fs.fs_magic =3D=3D FS_UFS1_MAGIC || + (fs.fs_magic =3D=3D FS_UFS2_MAGIC && + fs.fs_sblockloc =3D=3D sblock_try[n]) +#endif + ) && + fs.fs_bsize <=3D MAXBSIZE && + fs.fs_bsize >=3D sizeof(struct fs)) + break; + } + if (sblock_try[n] =3D=3D -1) { + return -1; + } + dsk_meta++; + } else + memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); + if (!inode) + return 0; + if (inomap !=3D inode) { + n =3D IPERVBLK(&fs); + if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK)) + return -1; + n =3D INO_TO_VBO(n, inode); +#if defined(UFS1_ONLY) + memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, + sizeof(struct ufs1_dinode)); +#elif defined(UFS2_ONLY) + memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, + sizeof(struct ufs2_dinode)); +#else + if (fs.fs_magic =3D=3D FS_UFS1_MAGIC) + memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, + sizeof(struct ufs1_dinode)); + else + memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, + sizeof(struct ufs2_dinode)); +#endif + inomap =3D inode; + fs_off =3D 0; + blkmap =3D indmap =3D 0; + } + size =3D DIP(di_size); + n =3D size - fs_off; + return (n); +} + +static struct dmadat __dmadat; + +static bool +probe(dev_info_t* const dev) +{ + devinfo =3D *dev; + dmadat =3D &__dmadat; + if (fsread(0, NULL, 0)) { + return 0; + } + return 1; +} + +static void* +try_load(const dev_info_t dev, + const char* const loader_path, + size_t* const bufsizeref) +{ + ufs_ino_t ino; + EFI_STATUS status; + void *buffer; + size_t bufsize; + + devinfo =3D dev; + if ((ino =3D lookup(loader_path)) =3D=3D 0) { + printf("File %s not found\n", loader_path); + return NULL; + } + + bufsize =3D fsstat(ino); + *bufsizeref =3D bufsize; + status =3D systab->BootServices->AllocatePool(EfiLoaderData, + bufsize, &buffer); + fsread(ino, buffer, bufsize); + return buffer; +} + +static void* +load(const dev_info_t devs[], + const size_t ndevs, + const char* const loader_path, + int* const idxref, + size_t* const bufsizeref) +{ + for(int i =3D 0; i < ndevs; i++) + { + void* const out =3D try_load(devs[i], loader_path, bufsiz= eref); + if (out !=3D NULL) + { + *idxref =3D i; + return out; + } + } + return NULL; +} + + +static void init(EFI_HANDLE xImage, + EFI_SYSTEM_TABLE* xSystab, + EFI_BOOT_SERVICES * xBootsrv) +{ + image =3D xImage; + systab =3D xSystab; + bootsrv =3D xBootsrv; +} + +const boot_module_t ufs_module =3D +{ + .name =3D "UFS", + .init =3D init, + .probe =3D probe, + .load =3D load +}; Property changes on: sys/boot/efi/boot1/ufs_module.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=3D%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: sys/boot/efi/boot1/zfs_module.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/boot1/zfs_module.c (revision 0) +++ sys/boot/efi/boot1/zfs_module.c (working copy) @@ -0,0 +1,201 @@ +/* Copyright (c) 2015 Eric McCorkle. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the author nor the names of any contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <stddef.h> +#include <stdarg.h> +#include <stdbool.h> + +#include <sys/cdefs.h> +#include <sys/param.h> +#include <sys/queue.h> + +#include <efi.h> + +#include "boot_module.h" + +#include "libzfs.h" +#include "zfsimpl.c" + +#define PATH_CONFIG "/boot/config" +#define PATH_DOTCONFIG "/boot/.config" + +static EFI_HANDLE image; +static EFI_SYSTEM_TABLE* systab; +static EFI_BOOT_SERVICES *bootsrv; + +static int +vdev_read(vdev_t * const vdev, + void * const priv, + const off_t off, + void * const buf, + const size_t bytes) +{ + const dev_info_t* const devinfo =3D (const dev_info_t*) priv; + const off_t lba =3D off / devinfo->dev->Media->BlockSize; + const EFI_STATUS status =3D + devinfo->dev->ReadBlocks(devinfo->dev, + devinfo->dev->Media->MediaId, + lba, bytes, buf); + if (EFI_ERROR(status)) + return (-1); + + return (0); +} + +static bool probe(dev_info_t* const dev) +{ + spa_t* spa; + int result =3D vdev_probe(vdev_read, dev, &spa); + dev->devdata =3D spa; + + return result =3D=3D 0; +} + +static void* try_load(const dev_info_t devinfo, + const char* const loader_path, + size_t* const bufsizeref) +{ + spa_t *spa =3D devinfo.devdata; + struct zfsmount zfsmount; + dnode_phys_t dn; + bool autoboot =3D true; + + if (zfs_spa_init(spa) !=3D 0) { + // Mount failed. Don't report this loudly + return NULL; + } + + // First, try mounting the ZFS volume + if (zfs_mount(spa, 0, &zfsmount) !=3D 0) { + // Mount failed. Don't report this loudly + return NULL; + } + + //vdev_t * const primary_vdev =3D spa_get_primary_vdev(spa); + + if (zfs_lookup(&zfsmount, loader_path, &dn) !=3D 0) { + return NULL; + } + + struct stat st; + if (zfs_dnode_stat(spa, &dn, &st)) { + return NULL; + } + + const size_t bufsize =3D st.st_size; + void* buffer; + EFI_STATUS status; + + *bufsizeref =3D bufsize; + + if (systab->BootServices->AllocatePool(EfiLoaderData, + bufsize, &buffer) !=3D + EFI_SUCCESS) { + return NULL; + } + + if (dnode_read(spa, &dn, 0, buffer, bufsize) < 0) { + return NULL; + } + + return buffer; +} + +static int zfs_mount_ds(const char * const dsname, + struct zfsmount * const zfsmount, + spa_t ** const spa) +{ + uint64_t newroot; + spa_t *newspa; + char *q; + + q =3D strchr(dsname, '/'); + if (q) + *q++ =3D '\0'; + newspa =3D spa_find_by_name(dsname); + if (newspa =3D=3D NULL) { + printf("\nCan't find ZFS pool %s\n", dsname); + return -1; + } + + if (zfs_spa_init(newspa)) + return -1; + + newroot =3D 0; + if (q) { + if (zfs_lookup_dataset(newspa, q, &newroot)) { + printf("\nCan't find dataset %s in ZFS pool %s\n= ", + q, newspa->spa_name); + return -1; + } + } + if (zfs_mount(newspa, newroot, zfsmount)) { + printf("\nCan't mount ZFS dataset\n"); + return -1; + } + *spa =3D newspa; + return (0); +} + +static void* load(const dev_info_t devs[], + const size_t ndevs, + const char* const loader_path, + int* const idxref, + size_t* const bufsizeref) +{ + for(int i =3D 0; i < ndevs; i++) { + void* const out =3D try_load(devs[i], loader_path, bufsi= zeref); + if (out !=3D NULL) + { + *idxref =3D i; + return out; + } + } + return NULL; +} + +static void init(EFI_HANDLE xImage, + EFI_SYSTEM_TABLE* xSystab, + EFI_BOOT_SERVICES * xBootsrv) +{ + image =3D xImage; + systab =3D xSystab; + bootsrv =3D xBootsrv; + zfs_init(); +} + +const boot_module_t zfs_module =3D +{ + .name =3D "ZFS", + .init =3D init, + .probe =3D probe, + .load =3D load +}; Property changes on: sys/boot/efi/boot1/zfs_module.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=3D%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: sys/boot/efi/include/efilib.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/include/efilib.h (revision 283525) +++ sys/boot/efi/include/efilib.h (working copy) @@ -43,7 +43,8 @@ =20 int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int= ); EFI_HANDLE efi_find_handle(struct devsw *, int); -int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *); +void efi_handle_update_dev(EFI_HANDLE, struct devsw *, int, uint64_t); +int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *, uint64_t *); =20 int efi_status_to_errno(EFI_STATUS); time_t efi_time(EFI_TIME *); Index: sys/boot/efi/libefi/handles.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/libefi/handles.c (revision 283525) +++ sys/boot/efi/libefi/handles.c (working copy) @@ -35,6 +35,7 @@ EFI_HANDLE alias; struct devsw *dev; int unit; + uint64_t extra; }; =20 struct entry *entry; @@ -78,8 +79,28 @@ return (NULL); } =20 +void efi_handle_update_dev(const EFI_HANDLE handle, + struct devsw * const dev, + int unit, + uint64_t guid) +{ + int idx; + + for (idx =3D 0; idx < nentries; idx++) { + if (entry[idx].handle !=3D handle) + continue; + entry[idx].dev =3D dev; + entry[idx].unit =3D unit; + entry[idx].alias =3D NULL; + entry[idx].extra =3D guid; + } +} + int -efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit) +efi_handle_lookup(EFI_HANDLE h, + struct devsw **dev, + int *unit, + uint64_t *extra) { int idx; =20 @@ -90,6 +111,8 @@ *dev =3D entry[idx].dev; if (unit !=3D NULL) *unit =3D entry[idx].unit; + if (extra !=3D NULL) + *extra =3D entry[idx].extra; return (0); } return (ENOENT); Index: sys/boot/efi/loader/Makefile =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/loader/Makefile (revision 283525) +++ sys/boot/efi/loader/Makefile (working copy) @@ -12,6 +12,8 @@ PROG=3D loader.sym INTERNALPROG=3D =20 +#LIBZFSBOOT=3D ${.OBJDIR}/../../zfs/libzfsboot.a + .PATH: ${.CURDIR}/../../efi/loader # architecture-specific loader code SRCS=3D autoload.c \ @@ -22,8 +24,11 @@ main.c \ self_reloc.c \ smbios.c \ - vers.c + vers.c \ + ${ZFS_C} =20 +ZFS_C =3D ${.CURDIR}/../../zfs/zfs.c + .PATH: ${.CURDIR}/arch/${MACHINE} # For smbios.c .PATH: ${.CURDIR}/../../i386/libi386 @@ -36,6 +41,8 @@ CFLAGS+=3D -I${.CURDIR}/../../../contrib/dev/acpica/include CFLAGS+=3D -I${.CURDIR}/../../.. CFLAGS+=3D -I${.CURDIR}/../../i386/libi386 +CFLAGS+=3D -I${.CURDIR}/../../zfs +CFLAGS+=3D -I${.CURDIR}/../../../cddl/boot/zfs CFLAGS+=3D -DNO_PCI -DEFI =20 # make buildenv doesn't set DESTDIR, this means LIBSTAND @@ -68,7 +75,7 @@ CFLAGS+=3D -DEFI_STAGING_SIZE=3D${EFI_STAGING_SIZE} .endif =20 -# Always add MI sources=20 +# Always add MI sources .PATH: ${.CURDIR}/../../common .include "${.CURDIR}/../../common/Makefile.inc" CFLAGS+=3D -I${.CURDIR}/../../common Index: sys/boot/efi/loader/conf.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/loader/conf.c (revision 283525) +++ sys/boot/efi/loader/conf.c (working copy) @@ -31,14 +31,17 @@ #include <bootstrap.h> #include <efi.h> #include <efilib.h> +#include "../zfs/libzfs.h" =20 struct devsw *devsw[] =3D { &efipart_dev, &efinet_dev, + &zfs_dev, NULL }; =20 struct fs_ops *file_system[] =3D { + &zfs_fsops, &dosfs_fsops, &ufs_fsops, &cd9660_fsops, Index: sys/boot/efi/loader/devicename.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/loader/devicename.c (revision 283525) +++ sys/boot/efi/loader/devicename.c (working copy) @@ -32,6 +32,7 @@ #include <string.h> #include <sys/disklabel.h> #include "bootstrap.h" +#include "libzfs.h" =20 #include <efi.h> #include <efilib.h> @@ -38,7 +39,7 @@ =20 static int efi_parsedev(struct devdesc **, const char *, const char **);= =20 -/*=20 +/* * Point (dev) at an allocated device specifier for the device matching = the * path in (devspec). If it contains an explicit device specification, * use that. If not, use the default device. @@ -48,7 +49,6 @@ { struct devdesc **dev =3D (struct devdesc **)vdev; int rv; - /* * If it looks like this is just a path and no device, then * use the current device instead. @@ -61,7 +61,8 @@ } =20 /* Parse the device name off the beginning of the devspec. */ - return (efi_parsedev(dev, devspec, path)); + const int out =3D efi_parsedev(dev, devspec, path); + return out; } =20 /* @@ -87,8 +88,9 @@ int i, err; =20 /* minimum length check */ - if (strlen(devspec) < 2) + if (strlen(devspec) < 2) { return (EINVAL); + } =20 /* look for a device that matches */ for (i =3D 0; devsw[i] !=3D NULL; i++) { @@ -96,27 +98,39 @@ if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) break; } - if (devsw[i] =3D=3D NULL) + if (devsw[i] =3D=3D NULL) { return (ENOENT); + } + np =3D devspec + strlen(dv->dv_name); =20 - idev =3D malloc(sizeof(struct devdesc)); - if (idev =3D=3D NULL) - return (ENOMEM); + if (DEVT_ZFS =3D=3D dv->dv_type) { + idev =3D malloc(sizeof(struct zfs_devdesc)); + int out =3D zfs_parsedev((struct zfs_devdesc*)idev, np, = path); + if (0 =3D=3D out) { + *dev =3D idev; + cp =3D strchr(np + 1, ':'); + } else { + free(idev); + return out; + } + } else { + idev =3D malloc(sizeof(struct devdesc)); + if (idev =3D=3D NULL) + return (ENOMEM); =20 - idev->d_dev =3D dv; - idev->d_type =3D dv->dv_type; - idev->d_unit =3D -1; - + idev->d_dev =3D dv; + idev->d_type =3D dv->dv_type; + idev->d_unit =3D -1; + if (*np !=3D '\0' && *np !=3D ':') { + idev->d_unit =3D strtol(np, &cp, 0); + if (cp =3D=3D np) { + idev->d_unit =3D -1; + free(idev); + return (EUNIT); + } + } + } err =3D 0; - np =3D devspec + strlen(dv->dv_name); - if (*np !=3D '\0' && *np !=3D ':') { - idev->d_unit =3D strtol(np, &cp, 0); - if (cp =3D=3D np) { - idev->d_unit =3D -1; - free(idev); - return (EUNIT); - } - } if (*cp !=3D '\0' && *cp !=3D ':') { free(idev); return (EINVAL); @@ -138,10 +152,11 @@ static char buf[32]; /* XXX device length constant? */ =20 switch(dev->d_type) { + case DEVT_ZFS: + return zfs_fmtdev(dev); case DEVT_NONE: strcpy(buf, "(no device)"); break; - default: sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); break; Index: sys/boot/efi/loader/main.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/efi/loader/main.c (revision 283525) +++ sys/boot/efi/loader/main.c (working copy) @@ -39,6 +39,7 @@ #include <smbios.h> =20 #include "loader_efi.h" +#include "libzfs.h" =20 extern char bootprog_name[]; extern char bootprog_rev[]; @@ -45,8 +46,9 @@ extern char bootprog_date[]; extern char bootprog_maker[]; =20 -struct devdesc currdev; /* our current device */ -struct arch_switch archsw; /* MI/MD interface boundary */ +/* our current device */ +/* MI/MD interface boundary */ +struct arch_switch archsw; =20 EFI_GUID acpi =3D ACPI_TABLE_GUID; EFI_GUID acpi20 =3D ACPI_20_TABLE_GUID; @@ -61,6 +63,70 @@ EFI_GUID debugimg =3D DEBUG_IMAGE_INFO_TABLE_GUID; EFI_GUID fdtdtb =3D FDT_TABLE_GUID; =20 +static void efi_zfs_probe(void); + +static void +print_str16(const CHAR16* const str) +{ + for(int i; str[i]; i++) + { + printf("%c", str[i]); + } +} + +/* +static int +str16cmp(const CHAR16 const *a, + const char* const b) +{ + for(int i =3D 0; a[i] || b[i]; i++) + { + const CHAR16 achr =3D a[i]; + const CHAR16 bchr =3D b[i]; + if (achr < bchr) + { + return -1; + } else if (achr > bchr) + { + return 1; + } + } + return 0; +} + +// Split an arg of the form "argname=3Dargval", replacing the '=3D' with= a \0 +static CHAR16* +split_arg(CHAR16 *const str) +{ + for (int i =3D 0; str[i]; i++) + { + if ('=3D' =3D=3D str[i]) + { + str[i] =3D 0; + return str + i + 1; + } + } + return NULL; +} + +static void +handle_arg(CHAR16 *const arg) +{ + const CHAR16* const argval =3D split_arg(arg); + const CHAR16* const argname =3D arg; + + if (NULL !=3D argval) + { + printf("Unrecognized argument \""); + print_arg(argname); + printf("\n"); + } else { + printf("Unrecognized argument \""); + print_arg(argname); + printf("\n"); + } +} +*/ EFI_STATUS main(int argc, CHAR16 *argv[]) { @@ -69,7 +135,15 @@ EFI_GUID *guid; int i; =20 - /* + archsw.arch_autoload =3D efi_autoload; + archsw.arch_getdev =3D efi_getdev; + archsw.arch_copyin =3D efi_copyin; + archsw.arch_copyout =3D efi_copyout; + archsw.arch_readin =3D efi_readin; + // Note this needs to be set before ZFS init + archsw.arch_zfs_probe =3D efi_zfs_probe; + + /* * XXX Chicken-and-egg problem; we want to have console output * early, but some console attributes may depend on reading from * eg. the boot device, which we can't do yet. We can use @@ -85,13 +159,22 @@ /* * March through the device switch probing for things. */ - for (i =3D 0; devsw[i] !=3D NULL; i++) - if (devsw[i]->dv_init !=3D NULL) + for (i =3D 0; devsw[i] !=3D NULL; i++) { + if (devsw[i]->dv_init !=3D NULL) { + printf("Initializing %s\n", devsw[i]->dv_name); (devsw[i]->dv_init)(); - + } + } /* Get our loaded image protocol interface structure. */ BS->HandleProtocol(IH, &imgid, (VOID**)&img); =20 + printf("Command line arguments:"); + for(i =3D 0; i < argc; i++) { + printf(" "); + print_str16(argv[i]); + } + printf("\n"); + printf("Image base: 0x%lx\n", (u_long)img->ImageBase); printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); @@ -105,8 +188,13 @@ printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); =20 - efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit); - currdev.d_type =3D currdev.d_dev->dv_type; + // Handle command-line arguments + /* + for(i =3D 1; i < argc; i++) + { + handle_arg(argv[i]); + } + */ =20 /* * Disable the watchdog timer. By default the boot manager sets @@ -119,19 +207,39 @@ */ BS->SetWatchdogTimer(0, 0, 0, NULL); =20 - env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev), - efi_setcurrdev, env_nounset); - env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset, - env_nounset); + struct devsw *dev; + int unit; + uint64_t pool_guid; + efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid); + switch (dev->dv_type) { + case DEVT_ZFS: { + struct zfs_devdesc currdev; + currdev.d_dev =3D dev; + currdev.d_unit =3D unit; + currdev.d_type =3D currdev.d_dev->dv_type; + currdev.d_opendata =3D NULL; + currdev.pool_guid =3D pool_guid; + currdev.root_guid =3D 0; + env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),= + efi_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev),= env_noset, + env_nounset); + } break; + default: { + struct devdesc currdev; + currdev.d_dev =3D dev; + currdev.d_unit =3D unit; + currdev.d_opendata =3D NULL; + currdev.d_type =3D currdev.d_dev->dv_type; + env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),= + efi_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev),= env_noset, + env_nounset); + } break; + } =20 setenv("LINES", "24", 1); /* optional */ =20 - archsw.arch_autoload =3D efi_autoload; - archsw.arch_getdev =3D efi_getdev; - archsw.arch_copyin =3D efi_copyin; - archsw.arch_copyout =3D efi_copyout; - archsw.arch_readin =3D efi_readin; - for (i =3D 0; i < ST->NumberOfTableEntries; i++) { guid =3D &ST->ConfigurationTable[i].VendorGuid; if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) { @@ -350,7 +458,6 @@ return (CMD_OK); } =20 - COMMAND_SET(nvram, "nvram", "get or set NVRAM variables", command_nvram)= ; =20 static int @@ -402,6 +509,27 @@ return (CMD_OK); } =20 +COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset", + command_lszfs); + +static int +command_lszfs(int argc, char *argv[]) +{ + int err; + + if (argc !=3D 2) { + command_errmsg =3D "wrong number of arguments"; + return (CMD_ERROR); + } + + err =3D zfs_list(argv[1]); + if (err !=3D 0) { + command_errmsg =3D strerror(err); + return (CMD_ERROR); + } + return (CMD_OK); +} + #ifdef LOADER_FDT_SUPPORT extern int command_fdt_internal(int argc, char *argv[]); =20 @@ -420,3 +548,23 @@ =20 COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt); #endif + +static void +efi_zfs_probe(void) +{ + EFI_BLOCK_IO *blkio; + EFI_HANDLE h; + EFI_STATUS status; + u_int unit =3D 0; + char devname[32]; + uint64_t pool_guid; + + for (int i =3D 0, h =3D efi_find_handle(&efipart_dev, 0); + h !=3D NULL; h =3D efi_find_handle(&efipart_dev, ++i)) { + snprintf(devname, sizeof devname, "%s%d:", + efipart_dev.dv_name, i); + if(0 =3D=3D zfs_probe_dev(devname, &pool_guid)) { + efi_handle_update_dev(h, &zfs_dev, unit++, pool_= guid); + } + } +} Index: sys/boot/zfs/zfs.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/zfs/zfs.c (revision 283525) +++ sys/boot/zfs/zfs.c (working copy) @@ -140,7 +140,7 @@ n =3D size; if (fp->f_seekp + n > sb.st_size) n =3D sb.st_size - fp->f_seekp; -=09 + rc =3D dnode_read(spa, &fp->f_dnode, fp->f_seekp, start, n); if (rc) return (rc); @@ -493,7 +493,7 @@ } } close(pa.fd); - return (0); + return (ret); } =20 /* --------------040508010102090007040903-- --9mXtQcxIOTeBwJJoa4u3PEkLG2JCiT7t8 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBAgAGBQJVdh5gAAoJEEGB2s+NNG0FiowQAL/TyR5NDvsJyybuIMCPigzD 2eSU5raV1osBX4v7bCTBl3bcXlbmKD4qKnsdSJ3l7Uq2Dcx5N0NuhrvDwexomT2G II3uQGpiTILin6/KGuGj+TySed59QEiTEe0Ue/GMi3hIjDZ16EoHamgTU5fdraG6 92zW/wfPCQS/hmruhnw6cUnHR0p4LwCERm0GnfHhoTYnLEVmiv9PLVoyWBoViRel R4A0WIIUJGDteonwCGo0u19fqnPvOuUs2Pfw9+T+Ds6QHE6QP6gOGHbRlkJKxYD6 Ci1iRZXGiCgs7YAgyv8k1uf9JELR4IOgsde39U0nY6h6WHAtPxGbXlrMH5rLlpQ8 5+vbXK9ndBf4a/YphrjfPWAr4vX/KJbC7UXIA88vgszPe6KPl1TBD7Z3GuGpotGK snS5yvFquWyXJkXq1V23da/aaaqLquILuZKeUqqcdRs80hkvRVCk2OZPuJYxMsQ/ IZG9AqYTjKzz+wN8J+IcRGFOtxmp+4TZFsFv8eBvY8FOuUHkCCwwpszFpTOW6qRc /cpfHODnMcpqjP7dBktShVgjP5/EZ4Yh/fg4vwVGWQeJC7MQgMXA/sTqf3V0+sde /5sgATJX4QE1fvu3ORD3oJTW730GVpPHd2YeUi9juYcoZ0dU3X1sxG6Y6jypgBJX m53qFGGi1Bj8PzLWlbq7 =YoaN -----END PGP SIGNATURE----- --9mXtQcxIOTeBwJJoa4u3PEkLG2JCiT7t8--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?55761E58.6040704>