Index: head/sys/boot/efi/boot1/Makefile =================================================================== --- head/sys/boot/efi/boot1/Makefile (revision 294264) +++ head/sys/boot/efi/boot1/Makefile (revision 294265) @@ -1,132 +1,135 @@ # $FreeBSD$ MAN= .include MK_SSP= no PROG= boot1.sym INTERNALPROG= WARNS?= 6 .if ${MK_ZFS} != "no" # Disable warnings that are currently incompatible with the zfs boot code CWARNFLAGS.zfs_module.c += -Wno-array-bounds CWARNFLAGS.zfs_module.c += -Wno-cast-align CWARNFLAGS.zfs_module.c += -Wno-cast-qual CWARNFLAGS.zfs_module.c += -Wno-missing-prototypes CWARNFLAGS.zfs_module.c += -Wno-sign-compare CWARNFLAGS.zfs_module.c += -Wno-unused-parameter CWARNFLAGS.zfs_module.c += -Wno-unused-function .endif # architecture-specific loader code SRCS= boot1.c self_reloc.c start.S ufs_module.c .if ${MK_ZFS} != "no" SRCS+= zfs_module.c .endif CFLAGS+= -I. CFLAGS+= -I${.CURDIR}/../include CFLAGS+= -I${.CURDIR}/../include/${MACHINE} CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include CFLAGS+= -I${.CURDIR}/../../.. CFLAGS+= -DEFI_UFS_BOOT +.ifdef(EFI_DEBUG) +CFLAGS+= -DEFI_DEBUG +.endif .if ${MK_ZFS} != "no" CFLAGS+= -I${.CURDIR}/../../zfs/ CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs/ CFLAGS+= -DEFI_ZFS_BOOT .endif # Always add MI sources and REGULAR efi loader bits .PATH: ${.CURDIR}/../loader/arch/${MACHINE} .PATH: ${.CURDIR}/../loader .PATH: ${.CURDIR}/../../common CFLAGS+= -I${.CURDIR}/../../common FILES= boot1.efi boot1.efifat FILESMODE_boot1.efi= ${BINMODE} LDSCRIPT= ${.CURDIR}/../loader/arch/${MACHINE}/ldscript.${MACHINE} LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared .if ${MACHINE_CPUARCH} == "aarch64" CFLAGS+= -msoft-float -mgeneral-regs-only .endif .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" CFLAGS+= -fPIC LDFLAGS+= -Wl,-znocombreloc .endif # # Add libstand for the runtime functions used by the compiler - for example # __aeabi_* (arm) or __divdi3 (i386). # as well as required string and memory functions for all platforms. # DPADD+= ${LIBSTAND} LDADD+= -lstand DPADD+= ${LDSCRIPT} OBJCOPY?= objcopy OBJDUMP?= objdump .if ${MACHINE_CPUARCH} == "amd64" EFI_TARGET= efi-app-x86_64 .elif ${MACHINE_CPUARCH} == "i386" EFI_TARGET= efi-app-ia32 .else EFI_TARGET= binary .endif boot1.efi: ${PROG} if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ exit 1; \ fi ${OBJCOPY} -j .peheader -j .text -j .sdata -j .data \ -j .dynamic -j .dynsym -j .rel.dyn \ -j .rela.dyn -j .reloc -j .eh_frame \ --output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET} boot1.o: ${.CURDIR}/../../common/ufsread.c # The following inserts our objects into a template FAT file system # created by generate-fat.sh .include "${.CURDIR}/Makefile.fat" BOOT1_MAXSIZE?= 131072 boot1.efifat: boot1.efi @set -- `ls -l boot1.efi`; \ x=$$(($$5-${BOOT1_MAXSIZE})); \ if [ $$x -ge 0 ]; then \ echo "boot1 $$x bytes too large; regenerate FAT templates?" >&2 ;\ exit 1; \ fi echo ${.OBJDIR} uudecode ${.CURDIR}/fat-${MACHINE}.tmpl.bz2.uu mv fat-${MACHINE}.tmpl.bz2 ${.TARGET}.bz2 bzip2 -f -d ${.TARGET}.bz2 dd if=boot1.efi of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc CLEANFILES= boot1.efi boot1.efifat .include beforedepend ${OBJS}: machine CLEANFILES+= machine machine: ln -sf ${.CURDIR}/../../../${MACHINE}/include machine .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" beforedepend ${OBJS}: x86 CLEANFILES+= x86 x86: ln -sf ${.CURDIR}/../../../x86/include x86 .endif Index: head/sys/boot/efi/boot1/boot_module.h =================================================================== --- head/sys/boot/efi/boot1/boot_module.h (revision 294264) +++ head/sys/boot/efi/boot1/boot_module.h (revision 294265) @@ -1,113 +1,110 @@ /*- * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * $FreeBSD$ */ #ifndef _BOOT_MODULE_H_ #define _BOOT_MODULE_H_ #include #include #include #include #ifdef EFI_DEBUG -#define DPRINTF(fmt, args...) \ - do { \ - printf(fmt, ##args) \ - } while (0) +#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__) #else -#define DPRINTF(fmt, args...) {} +#define DPRINTF(fmt, ...) {} #endif /* EFI device info */ typedef struct dev_info { EFI_BLOCK_IO *dev; EFI_DEVICE_PATH *devpath; EFI_HANDLE *devhandle; void *devdata; struct dev_info *next; } 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 *name; /* init is the optional initialiser for the module. */ void (*init)(); /* * probe checks to see if the module can handle dev. * * Return codes: * EFI_SUCCESS = The module can handle the device. * EFI_NOT_FOUND = The module can not handle the device. * Other = The module encountered an error. */ EFI_STATUS (*probe)(dev_info_t* dev); /* * load should select the best out of a set of devices that probe * indicated were loadable and load it. * * Return codes: * EFI_SUCCESS = The module can handle the device. * EFI_NOT_FOUND = The module can not handle the device. * Other = The module encountered an error. */ EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo, void **buf, size_t *bufsize); /* status outputs information about the probed devices. */ void (*status)(); } boot_module_t; /* Standard boot modules. */ #ifdef EFI_UFS_BOOT extern const boot_module_t ufs_module; #endif #ifdef EFI_ZFS_BOOT extern const boot_module_t zfs_module; #endif /* Functions available to modules. */ extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo); 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); extern EFI_SYSTEM_TABLE *systab; extern EFI_BOOT_SERVICES *bs; #endif Index: head/sys/boot/efi/boot1/zfs_module.c =================================================================== --- head/sys/boot/efi/boot1/zfs_module.c (revision 294264) +++ head/sys/boot/efi/boot1/zfs_module.c (revision 294265) @@ -1,199 +1,199 @@ /*- * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include "boot_module.h" #include "libzfs.h" #include "zfsimpl.c" static dev_info_t *devices; static int vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) { dev_info_t *devinfo; off_t lba; EFI_STATUS status; devinfo = (dev_info_t *)priv; lba = off / devinfo->dev->Media->BlockSize; status = devinfo->dev->ReadBlocks(devinfo->dev, devinfo->dev->Media->MediaId, lba, bytes, buf); if (status != EFI_SUCCESS) { - DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %lu, size: %d," + DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %zu, size: %zu," " status: %lu\n", devinfo->dev, - devinfo->dev->Media->MediaId, lba, size, + devinfo->dev->Media->MediaId, lba, bytes, EFI_ERROR_CODE(status)); return (-1); } return (0); } static EFI_STATUS probe(dev_info_t *dev) { spa_t *spa; dev_info_t *tdev; EFI_STATUS status; /* ZFS consumes the dev on success so we need a copy. */ if ((status = bs->AllocatePool(EfiLoaderData, sizeof(*dev), (void**)&tdev)) != EFI_SUCCESS) { DPRINTF("Failed to allocate tdev (%lu)\n", EFI_ERROR_CODE(status)); return (status); } memcpy(tdev, dev, sizeof(*dev)); if (vdev_probe(vdev_read, tdev, &spa) != 0) { (void)bs->FreePool(tdev); return (EFI_UNSUPPORTED); } dev->devdata = spa; add_device(&devices, dev); return (EFI_SUCCESS); } static EFI_STATUS try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize) { spa_t *spa; struct zfsmount zfsmount; dnode_phys_t dn; struct stat st; int err; void *buf; EFI_STATUS status; spa = devinfo->devdata; if (zfs_spa_init(spa) != 0) { /* Init failed, don't report this loudly. */ return (EFI_NOT_FOUND); } if (zfs_mount(spa, 0, &zfsmount) != 0) { /* Mount failed, don't report this loudly. */ return (EFI_NOT_FOUND); } if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) { printf("Failed to lookup %s on pool %s (%d)\n", loader_path, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) { printf("Failed to lookup %s on pool %s (%d)\n", loader_path, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf)) != EFI_SUCCESS) { printf("Failed to allocate load buffer for pool %s (%lu)\n", spa->spa_name, EFI_ERROR_CODE(status)); return (EFI_INVALID_PARAMETER); } if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) { printf("Failed to read node from %s (%d)\n", spa->spa_name, err); (void)bs->FreePool(buf); return (EFI_INVALID_PARAMETER); } *bufsize = st.st_size; *bufp = buf; return (EFI_SUCCESS); } static EFI_STATUS load(const char *loader_path, dev_info_t **devinfop, void **bufp, size_t *bufsize) { dev_info_t *devinfo; EFI_STATUS status; for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) { status = try_load(devinfo, loader_path, bufp, bufsize); if (status == EFI_SUCCESS) { *devinfop = devinfo; return (EFI_SUCCESS); } else if (status != EFI_NOT_FOUND) { return (status); } } return (EFI_NOT_FOUND); } static void status() { spa_t *spa; spa = STAILQ_FIRST(&zfs_pools); if (spa == NULL) { printf("%s found no pools\n", zfs_module.name); return; } printf("%s found the following pools:", zfs_module.name); STAILQ_FOREACH(spa, &zfs_pools, spa_link) printf(" %s", spa->spa_name); printf("\n"); } static void init() { zfs_init(); } const boot_module_t zfs_module = { .name = "ZFS", .init = init, .probe = probe, .load = load, .status = status };