From owner-freebsd-hackers@FreeBSD.ORG Sun May 10 18:04:47 2015 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id AB3DE920 for ; Sun, 10 May 2015 18:04:47 +0000 (UTC) Received: from mail.metricspace.net (mail.metricspace.net [IPv6:2001:470:1f11:617::103]) by mx1.freebsd.org (Postfix) with ESMTP id 4689A18D6 for ; Sun, 10 May 2015 18:04:47 +0000 (UTC) Received: from [IPv6:2001:470:1f11:617:5ef7:830:9e60:2038] (unknown [IPv6:2001:470:1f11:617:5ef7:830:9e60:2038]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) (Authenticated sender: eric) by mail.metricspace.net (Postfix) with ESMTPSA id 71E4E29AD2 for ; Sun, 10 May 2015 18:04:46 +0000 (UTC) Message-ID: <554F9DBB.6020202@metricspace.net> Date: Sun, 10 May 2015 14:04:43 -0400 From: Eric McCorkle User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 MIME-Version: 1.0 To: freebsd-hackers@freebsd.org Subject: Re: EFI boot loader regression? References: <553A8CE4.9030204@metricspace.net> In-Reply-To: <553A8CE4.9030204@metricspace.net> Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="BdNR2hc2JDrfgguIWCHHMsfb9beOihcgH" X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 10 May 2015 18:04:47 -0000 This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --BdNR2hc2JDrfgguIWCHHMsfb9beOihcgH Content-Type: multipart/mixed; boundary="------------040709080406050600000600" This is a multi-part message in MIME format. --------------040709080406050600000600 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable Sorry for the delay in posting this. Attached is my latest work on the boot block. It includes numerous debugging messages. You should be able to tell if it gets all the way through the first stage, or where it stops if it doesn't. For everyone else, these are the outstanding issues I still need to addre= ss: * I'm currently (ab)using the UEFI pool allocator as a malloc-like mechanism. * The partition scan completely ignores the GPT labels, and tries to probe every single partition for every single filesystem. * Need to work out argv-style options for the UEFI loader, and have the boot block construct and pass in an argv array. Any other comments are welcome. On 04/24/2015 02:35 PM, Eric McCorkle wrote: > What kind of laptop are you using, and did you update your BIOS in ther= e > anywhere? >=20 > I'm actively working on the UEFI boot block. I will post a patch with > extra debugging messages added, which will hopefully help track down th= e > problem. >=20 > On 04/24/2015 12:50 PM, Andrey Fesenko wrote: >> Hello, >> >> I'm use system with EFI boot loader on Lenovo X220. >> >> Old EFI loader work fine if BIOS set any boot priority UEFI or Legacy = first. >> >> Starting around December last year, system not boot if set UEFI boot f= irst. >> >> http://bsdnir.info/files/efi/ screenshots and working version boot loa= der >> >> For the cleanliness of experiment, as a new loader I downloaded and >> test FreeBSD-11.0-CURRENT-amd64-20150421-r281832-memstick.img >> _______________________________________________ >> freebsd-hackers@freebsd.org mailing list >> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers >> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.= org" >> > _______________________________________________ > 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 --------------040709080406050600000600 Content-Type: text/x-patch; name="zfsefi_curr.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="zfsefi_curr.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 281381) +++ sys/boot/efi/boot1/Makefile (working copy) @@ -13,7 +13,7 @@ INTERNALPROG=3D =20 # architecture-specific loader code -SRCS=3D boot1.c reloc.c start.S +SRCS=3D boot1.c 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_CPUARCH} 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_CPUARCH} 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 281381) +++ 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 -#include #include #include =20 @@ -28,6 +29,8 @@ #include #include =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 partitions= \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; @@ -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 + +#include +#include +#include + +#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 +#include + +#include +#include + +#include + +#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 +#include +#include + +#include +#include +#include + +#include + +#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 --------------040709080406050600000600-- --BdNR2hc2JDrfgguIWCHHMsfb9beOihcgH 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 iQIcBAEBAgAGBQJVT53DAAoJEEGB2s+NNG0FfAQP/1LiivskAgDIPNiXjq6ZhapJ FgPtFWzpkOHIe7WXfXgqwCwziFlvwmmyVTcX/JfbXtLO9UK/Y+aUEw0bnwbMEy2f bsWbsfauTL2X6Q7zeabTG/JV/G9tOe/IQKYYQFaYeMY7pweX0g9Dqv1eGWgOG6Is t+4xaSxv1I+L9HjcuRnoJ1sWnvTEx7oPi7Gwm0XtTmNeRB4tB7IJS4GFe4kQjR9t WinWfO+pQMxFJaTKYpG9GZ4x2Syt92xC+z4qVETKEydG54eoFfOu9GNmju6p1irX IcYxQBH6Fm5quR+CkrR66xVNVJfZjgSa11zU1HI0OgHFT9T+tsL1sDWnDPuIBgKH YjB/vsb1jnqIF+l31y9Y50rTWOelPugGQcpdXhHTbsxIZTgpPh+N1LegpcS40Ny9 Q52j39igaSR2Z9IjlLAMsNyk2BcS3Wfv/gMFeg/QB6w5N1r5ucMkQHLQn7FQ41n1 MDu2f+4aW4zx1NfY7U69VVmQHy0fcR61p0CnIIcx2FavRemjQquHvmC7TehBh5ab PHpg3qW1dt60vVEmW4O9wbGx1zMhkCvB+UTSQPjaYwkMS2Zul94Y+e1HVp6qUoou QJ61p+JbpYNfndJfm6NNtvvmhbZTjQCiQ8L3wyAhNXL9hxF51GXdV9Ocd911NsRU u+bqVCyj7xgCe+9nXuxk =ljNX -----END PGP SIGNATURE----- --BdNR2hc2JDrfgguIWCHHMsfb9beOihcgH--