[Midnightbsd-cvs] src [10208] trunk/sys/boot/efi/boot1: add boot1
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sat Jun 2 08:43:49 EDT 2018
Revision: 10208
http://svnweb.midnightbsd.org/src/?rev=10208
Author: laffer1
Date: 2018-06-02 08:43:49 -0400 (Sat, 02 Jun 2018)
Log Message:
-----------
add boot1
Added Paths:
-----------
trunk/sys/boot/efi/boot1/
trunk/sys/boot/efi/boot1/Makefile
trunk/sys/boot/efi/boot1/Makefile.fat
trunk/sys/boot/efi/boot1/boot1.c
trunk/sys/boot/efi/boot1/boot_module.h
trunk/sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
trunk/sys/boot/efi/boot1/generate-fat.sh
trunk/sys/boot/efi/boot1/ufs_module.c
trunk/sys/boot/efi/boot1/zfs_module.c
Added: trunk/sys/boot/efi/boot1/Makefile
===================================================================
--- trunk/sys/boot/efi/boot1/Makefile (rev 0)
+++ trunk/sys/boot/efi/boot1/Makefile 2018-06-02 12:43:49 UTC (rev 10208)
@@ -0,0 +1,119 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/boot/efi/boot1/Makefile 319025 2017-05-28 01:14:59Z ngie $
+
+MAN=
+
+.include <bsd.own.mk>
+
+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 reloc.c start.S ufs_module.c
+.if ${MK_ZFS} != "no"
+SRCS+= zfs_module.c
+.endif
+
+CFLAGS+= -fPIC
+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} == "amd64" || ${MACHINE_CPUARCH} == "i386"
+LDFLAGS+= -Wl,-znocombreloc
+.endif
+
+#
+# Add libstand for required string and memory functions for all platforms.
+#
+DPADD+= ${LIBSTAND}
+LDADD+= -lstand
+
+DPADD+= ${LDSCRIPT}
+
+NM?= nm
+OBJCOPY?= objcopy
+
+.if ${MACHINE_CPUARCH} == "amd64"
+EFI_TARGET= efi-app-x86_64
+.elif ${MACHINE_CPUARCH} == "i386"
+EFI_TARGET= efi-app-ia32
+.endif
+
+boot1.efi: ${PROG}
+ if ${NM} ${.ALLSRC} | grep ' U '; then \
+ echo "Undefined symbols in ${.ALLSRC}"; \
+ exit 1; \
+ fi
+ ${OBJCOPY} -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.efifat: boot1.efi
+ echo ${.OBJDIR}
+ uudecode ${.CURDIR}/fat-${MACHINE}.tmpl.bz2.uu
+ mv fat-${MACHINE}.tmpl.bz2 ${.TARGET}.bz2
+ bzip2 -f -d ${.TARGET}.bz2
+ ${DD} if=${.ALLSRC} of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc
+
+CLEANFILES= boot1.efi boot1.efifat
+
+.include <bsd.prog.mk>
+
+.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
+beforedepend ${OBJS}: machine x86
+
+CLEANFILES+= machine x86
+
+machine:
+ ln -sf ${.CURDIR}/../../../amd64/include machine
+
+x86:
+ ln -sf ${.CURDIR}/../../../x86/include x86
+.endif
Property changes on: trunk/sys/boot/efi/boot1/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/boot/efi/boot1/Makefile.fat
===================================================================
--- trunk/sys/boot/efi/boot1/Makefile.fat (rev 0)
+++ trunk/sys/boot/efi/boot1/Makefile.fat 2018-06-02 12:43:49 UTC (rev 10208)
@@ -0,0 +1,4 @@
+# $MidnightBSD$
+# This file autogenerated by generate-fat.sh - DO NOT EDIT
+# $FreeBSD: stable/10/sys/boot/efi/boot1/Makefile.fat 293297 2016-01-07 02:22:45Z emaste $
+BOOT1_OFFSET=0x2d
Property changes on: trunk/sys/boot/efi/boot1/Makefile.fat
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/boot/efi/boot1/boot1.c
===================================================================
--- trunk/sys/boot/efi/boot1/boot1.c (rev 0)
+++ trunk/sys/boot/efi/boot1/boot1.c 2018-06-02 12:43:49 UTC (rev 10208)
@@ -0,0 +1,728 @@
+/* $MidnightBSD$ */
+/*-
+ * 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 reserved.
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/boot1/boot1.c 318626 2017-05-22 06:29:20Z ngie $");
+
+#include <sys/param.h>
+#include <machine/elf.h>
+#include <machine/stdarg.h>
+#include <stand.h>
+
+#include <efi.h>
+#include <eficonsctl.h>
+
+#include "boot_module.h"
+#include "paths.h"
+
+static const boot_module_t *boot_modules[] =
+{
+#ifdef EFI_ZFS_BOOT
+ &zfs_module,
+#endif
+#ifdef EFI_UFS_BOOT
+ &ufs_module
+#endif
+};
+
+#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*))
+/* The initial number of handles used to query EFI for partitions. */
+#define NUM_HANDLES_INIT 24
+
+EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
+
+EFI_SYSTEM_TABLE *systab;
+EFI_BOOT_SERVICES *bs;
+static EFI_HANDLE *image;
+
+static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
+static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
+static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
+static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
+
+/*
+ * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
+ * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
+ * EFI methods.
+ */
+void *
+Malloc(size_t len, const char *file __unused, int line __unused)
+{
+ void *out;
+
+ if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
+ return (out);
+
+ return (NULL);
+}
+
+void
+Free(void *buf, const char *file __unused, int line __unused)
+{
+ (void)bs->FreePool(buf);
+}
+
+/*
+ * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
+ * FALSE otherwise.
+ */
+static BOOLEAN
+nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
+{
+ int len;
+
+ if (imgpath == NULL || imgpath->Type != devpath->Type ||
+ imgpath->SubType != devpath->SubType)
+ return (FALSE);
+
+ len = DevicePathNodeLength(imgpath);
+ if (len != DevicePathNodeLength(devpath))
+ return (FALSE);
+
+ return (memcmp(imgpath, devpath, (size_t)len) == 0);
+}
+
+/*
+ * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
+ * in imgpath and devpath match up to their respect occurances of a media
+ * node, FALSE otherwise.
+ */
+static BOOLEAN
+device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
+{
+
+ if (imgpath == NULL)
+ return (FALSE);
+
+ while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
+ if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
+ IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
+ return (TRUE);
+
+ if (!nodes_match(imgpath, devpath))
+ return (FALSE);
+
+ imgpath = NextDevicePathNode(imgpath);
+ devpath = NextDevicePathNode(devpath);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * devpath_last returns the last non-path end node in devpath.
+ */
+static EFI_DEVICE_PATH *
+devpath_last(EFI_DEVICE_PATH *devpath)
+{
+
+ while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+ devpath = NextDevicePathNode(devpath);
+
+ return (devpath);
+}
+
+/*
+ * devpath_node_str is a basic output method for a devpath node which
+ * only understands a subset of the available sub types.
+ *
+ * If we switch to UEFI 2.x then we should update it to use:
+ * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
+ */
+static int
+devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
+{
+
+ switch (devpath->Type) {
+ case MESSAGING_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case MSG_ATAPI_DP: {
+ ATAPI_DEVICE_PATH *atapi;
+
+ atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "ata(%s,%s,0x%x)",
+ (atapi->PrimarySecondary == 1) ? "Sec" : "Pri",
+ (atapi->SlaveMaster == 1) ? "Slave" : "Master",
+ atapi->Lun);
+ }
+ case MSG_USB_DP: {
+ USB_DEVICE_PATH *usb;
+
+ usb = (USB_DEVICE_PATH *)devpath;
+ return snprintf(buf, size, "usb(0x%02x,0x%02x)",
+ usb->ParentPortNumber, usb->InterfaceNumber);
+ }
+ case MSG_SCSI_DP: {
+ SCSI_DEVICE_PATH *scsi;
+
+ scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
+ scsi->Pun, scsi->Lun);
+ }
+ case MSG_SATA_DP: {
+ SATA_DEVICE_PATH *sata;
+
+ sata = (SATA_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
+ sata->HBAPortNumber, sata->PortMultiplierPortNumber,
+ sata->Lun);
+ }
+ default:
+ return snprintf(buf, size, "msg(0x%02x)",
+ devpath->SubType);
+ }
+ break;
+ case HARDWARE_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case HW_PCI_DP: {
+ PCI_DEVICE_PATH *pci;
+
+ pci = (PCI_DEVICE_PATH *)devpath;
+ return snprintf(buf, size, "pci(0x%02x,0x%02x)",
+ pci->Device, pci->Function);
+ }
+ default:
+ return snprintf(buf, size, "hw(0x%02x)",
+ devpath->SubType);
+ }
+ break;
+ case ACPI_DEVICE_PATH: {
+ ACPI_HID_DEVICE_PATH *acpi;
+
+ acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
+ if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+ switch (EISA_ID_TO_NUM(acpi->HID)) {
+ case 0x0a03:
+ return snprintf(buf, size, "pciroot(0x%x)",
+ acpi->UID);
+ case 0x0a08:
+ return snprintf(buf, size, "pcieroot(0x%x)",
+ acpi->UID);
+ case 0x0604:
+ return snprintf(buf, size, "floppy(0x%x)",
+ acpi->UID);
+ case 0x0301:
+ return snprintf(buf, size, "keyboard(0x%x)",
+ acpi->UID);
+ case 0x0501:
+ return snprintf(buf, size, "serial(0x%x)",
+ acpi->UID);
+ case 0x0401:
+ return snprintf(buf, size, "parallelport(0x%x)",
+ acpi->UID);
+ default:
+ return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
+ EISA_ID_TO_NUM(acpi->HID), acpi->UID);
+ }
+ }
+
+ return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
+ acpi->UID);
+ }
+ case MEDIA_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case MEDIA_CDROM_DP: {
+ CDROM_DEVICE_PATH *cdrom;
+
+ cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "cdrom(%x)",
+ cdrom->BootEntry);
+ }
+ case MEDIA_HARDDRIVE_DP: {
+ HARDDRIVE_DEVICE_PATH *hd;
+
+ hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "hd(%x)",
+ hd->PartitionNumber);
+ }
+ default:
+ return snprintf(buf, size, "media(0x%02x)",
+ devpath->SubType);
+ }
+ case BBS_DEVICE_PATH:
+ return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
+ case END_DEVICE_PATH_TYPE:
+ return (0);
+ }
+
+ return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
+ devpath->SubType);
+}
+
+/*
+ * devpath_strlcat appends a text description of devpath to buf but not more
+ * than size - 1 characters followed by NUL-terminator.
+ */
+int
+devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
+{
+ size_t len, used;
+ const char *sep;
+
+ sep = "";
+ used = 0;
+ while (!IsDevicePathEnd(devpath)) {
+ len = snprintf(buf, size - used, "%s", sep);
+ used += len;
+ if (used > size)
+ return (used);
+ buf += len;
+
+ len = devpath_node_str(buf, size - used, devpath);
+ used += len;
+ if (used > size)
+ return (used);
+ buf += len;
+ devpath = NextDevicePathNode(devpath);
+ sep = ":";
+ }
+
+ return (used);
+}
+
+/*
+ * devpath_str is convenience method which returns the text description of
+ * devpath using a static buffer, so it isn't thread safe!
+ */
+char *
+devpath_str(EFI_DEVICE_PATH *devpath)
+{
+ static char buf[256];
+
+ devpath_strlcat(buf, sizeof(buf), devpath);
+
+ return buf;
+}
+
+/*
+ * load_loader attempts to load the loader image data.
+ *
+ * It tries each module and its respective devices, identified by mod->probe,
+ * in order until a successful load occurs at which point it returns EFI_SUCCESS
+ * and EFI_NOT_FOUND otherwise.
+ *
+ * Only devices which have preferred matching the preferred parameter are tried.
+ */
+static EFI_STATUS
+load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
+ size_t *bufsize, BOOLEAN preferred)
+{
+ UINTN i;
+ dev_info_t *dev;
+ const boot_module_t *mod;
+
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
+ mod = boot_modules[i];
+ for (dev = mod->devices(); dev != NULL; dev = dev->next) {
+ if (dev->preferred != preferred)
+ continue;
+
+ if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
+ EFI_SUCCESS) {
+ *devinfop = dev;
+ *modp = mod;
+ return (EFI_SUCCESS);
+ }
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+/*
+ * try_boot only returns if it fails to load the loader. If it succeeds
+ * it simply boots, otherwise it returns the status of last EFI call.
+ */
+static EFI_STATUS
+try_boot()
+{
+ size_t bufsize, loadersize, cmdsize;
+ void *buf, *loaderbuf;
+ char *cmd;
+ dev_info_t *dev;
+ const boot_module_t *mod;
+ EFI_HANDLE loaderhandle;
+ EFI_LOADED_IMAGE *loaded_image;
+ EFI_STATUS status;
+
+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
+ if (status != EFI_SUCCESS) {
+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
+ FALSE);
+ if (status != EFI_SUCCESS) {
+ printf("Failed to load '%s'\n", PATH_LOADER_EFI);
+ return (status);
+ }
+ }
+
+ /*
+ * Read in and parse the command line from /boot.config or /boot/config,
+ * if present. We'll pass it the next stage via a simple ASCII
+ * string. loader.efi has a hack for ASCII strings, so we'll use that to
+ * keep the size down here. We only try to read the alternate file if
+ * we get EFI_NOT_FOUND because all other errors mean that the boot_module
+ * had troubles with the filesystem. We could return early, but we'll let
+ * loading the actual kernel sort all that out. Since these files are
+ * optional, we don't report errors in trying to read them.
+ */
+ cmd = NULL;
+ cmdsize = 0;
+ status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
+ if (status == EFI_NOT_FOUND)
+ status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
+ if (status == EFI_SUCCESS) {
+ cmdsize = bufsize + 1;
+ cmd = malloc(cmdsize);
+ if (cmd == NULL)
+ goto errout;
+ memcpy(cmd, buf, bufsize);
+ cmd[bufsize] = '\0';
+ free(buf);
+ buf = NULL;
+ }
+
+ if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath),
+ loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
+ printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
+ mod->name, bufsize, EFI_ERROR_CODE(status));
+ goto errout;
+ }
+
+ if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
+ (VOID**)&loaded_image)) != EFI_SUCCESS) {
+ printf("Failed to query LoadedImage provided by %s (%lu)\n",
+ mod->name, EFI_ERROR_CODE(status));
+ goto errout;
+ }
+
+ if (cmd != NULL)
+ printf(" command args: %s\n", cmd);
+
+ loaded_image->DeviceHandle = dev->devhandle;
+ loaded_image->LoadOptionsSize = cmdsize;
+ loaded_image->LoadOptions = cmd;
+
+ DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".\n");
+
+ if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
+ EFI_SUCCESS) {
+ printf("Failed to start image provided by %s (%lu)\n",
+ mod->name, EFI_ERROR_CODE(status));
+ loaded_image->LoadOptionsSize = 0;
+ loaded_image->LoadOptions = NULL;
+ }
+
+errout:
+ if (cmd != NULL)
+ free(cmd);
+ if (buf != NULL)
+ free(buf);
+ if (loaderbuf != NULL)
+ free(loaderbuf);
+
+ return (status);
+}
+
+/*
+ * probe_handle determines if the passed handle represents a logical partition
+ * if it does it uses each module in order to probe it and if successful it
+ * returns EFI_SUCCESS.
+ */
+static EFI_STATUS
+probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
+{
+ dev_info_t *devinfo;
+ EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath;
+ EFI_STATUS status;
+ UINTN i;
+
+ /* Figure out if we're dealing with an actual partition. */
+ status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ DPRINTF("probing: %s\n", devpath_str(devpath));
+
+ status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ if (!blkio->Media->LogicalPartition)
+ return (EFI_UNSUPPORTED);
+
+ *preferred = device_paths_match(imgpath, devpath);
+
+ /* Run through each module, see if it can load this partition */
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
+
+ if ((status = bs->AllocatePool(EfiLoaderData,
+ sizeof(*devinfo), (void **)&devinfo)) !=
+ EFI_SUCCESS) {
+ DPRINTF("\nFailed to allocate devinfo (%lu)\n",
+ EFI_ERROR_CODE(status));
+ continue;
+ }
+ devinfo->dev = blkio;
+ devinfo->devpath = devpath;
+ devinfo->devhandle = h;
+ devinfo->devdata = NULL;
+ devinfo->preferred = *preferred;
+ devinfo->next = NULL;
+
+ status = boot_modules[i]->probe(devinfo);
+ if (status == EFI_SUCCESS)
+ return (EFI_SUCCESS);
+ (void)bs->FreePool(devinfo);
+ }
+
+ return (EFI_UNSUPPORTED);
+}
+
+/*
+ * probe_handle_status calls probe_handle and outputs the returned status
+ * of the call.
+ */
+static void
+probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
+{
+ EFI_STATUS status;
+ BOOLEAN preferred;
+
+ status = probe_handle(h, imgpath, &preferred);
+
+ DPRINTF("probe: ");
+ switch (status) {
+ case EFI_UNSUPPORTED:
+ printf(".");
+ DPRINTF(" not supported\n");
+ break;
+ case EFI_SUCCESS:
+ if (preferred) {
+ printf("%c", '*');
+ DPRINTF(" supported (preferred)\n");
+ } else {
+ printf("%c", '+');
+ DPRINTF(" supported\n");
+ }
+ break;
+ default:
+ printf("x");
+ DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
+ break;
+ }
+ DSTALL(500000);
+}
+
+EFI_STATUS
+efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
+{
+ EFI_HANDLE *handles;
+ EFI_LOADED_IMAGE *img;
+ EFI_DEVICE_PATH *imgpath;
+ EFI_STATUS status;
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
+ SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
+ UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
+
+ /* Basic initialization*/
+ systab = Xsystab;
+ image = Ximage;
+ bs = Xsystab->BootServices;
+
+ /* Set up the console, so printf works. */
+ status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
+ (VOID **)&ConsoleControl);
+ if (status == EFI_SUCCESS)
+ (void)ConsoleControl->SetMode(ConsoleControl,
+ EfiConsoleControlScreenText);
+ /*
+ * Reset the console and find the best text mode.
+ */
+ conout = systab->ConOut;
+ conout->Reset(conout, TRUE);
+ max_dim = best_mode = 0;
+ for (i = 0; ; i++) {
+ status = conout->QueryMode(conout, i, &cols, &rows);
+ if (EFI_ERROR(status))
+ break;
+ if (cols * rows > max_dim) {
+ max_dim = cols * rows;
+ best_mode = i;
+ }
+ }
+ if (max_dim > 0)
+ conout->SetMode(conout, best_mode);
+ conout->EnableCursor(conout, TRUE);
+ conout->ClearScreen(conout);
+
+ printf("\n>> MidnightBSD EFI boot block\n");
+ printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
+ printf(" Initializing modules:");
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
+
+ printf(" %s", boot_modules[i]->name);
+ if (boot_modules[i]->init != NULL)
+ boot_modules[i]->init();
+ }
+ putchar('\n');
+
+ /* Get all the device handles */
+ hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
+ if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
+ != EFI_SUCCESS)
+ panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
+ EFI_ERROR_CODE(status));
+
+ status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
+ &hsize, handles);
+ switch (status) {
+ case EFI_SUCCESS:
+ break;
+ case EFI_BUFFER_TOO_SMALL:
+ (void)bs->FreePool(handles);
+ if ((status = bs->AllocatePool(EfiLoaderData, hsize,
+ (void **)&handles)) != EFI_SUCCESS) {
+ panic("Failed to allocate %zu handles (%lu)", hsize /
+ sizeof(*handles), EFI_ERROR_CODE(status));
+ }
+ status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
+ NULL, &hsize, handles);
+ if (status != EFI_SUCCESS)
+ panic("Failed to get device handles (%lu)\n",
+ EFI_ERROR_CODE(status));
+ break;
+ default:
+ panic("Failed to get device handles (%lu)",
+ EFI_ERROR_CODE(status));
+ }
+
+ /* Scan all partitions, probing with all modules. */
+ nhandles = hsize / sizeof(*handles);
+ printf(" Probing %zu block devices...", nhandles);
+ DPRINTF("\n");
+
+ /* Determine the devpath of our image so we can prefer it. */
+ status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
+ imgpath = NULL;
+ if (status == EFI_SUCCESS) {
+ status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
+ (void **)&imgpath);
+ if (status != EFI_SUCCESS)
+ DPRINTF("Failed to get image DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
+ }
+
+ for (i = 0; i < nhandles; i++)
+ probe_handle_status(handles[i], imgpath);
+ printf(" done\n");
+
+ /* Status summary. */
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] != NULL) {
+ printf(" ");
+ boot_modules[i]->status();
+ }
+ }
+
+ try_boot();
+
+ /* If we get here, we're out of luck... */
+ panic("No bootable partitions found!");
+}
+
+/*
+ * add_device adds a device to the passed devinfo list.
+ */
+void
+add_device(dev_info_t **devinfop, dev_info_t *devinfo)
+{
+ dev_info_t *dev;
+
+ if (*devinfop == NULL) {
+ *devinfop = devinfo;
+ return;
+ }
+
+ for (dev = *devinfop; dev->next != NULL; dev = dev->next)
+ ;
+
+ dev->next = devinfo;
+}
+
+void
+panic(const char *fmt, ...)
+{
+ va_list ap;
+
+ printf("panic: ");
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ printf("\n");
+
+ while (1) {}
+}
+
+void
+putchar(int c)
+{
+ CHAR16 buf[2];
+
+ if (c == '\n') {
+ buf[0] = '\r';
+ buf[1] = 0;
+ systab->ConOut->OutputString(systab->ConOut, buf);
+ }
+ buf[0] = c;
+ buf[1] = 0;
+ systab->ConOut->OutputString(systab->ConOut, buf);
+}
Property changes on: trunk/sys/boot/efi/boot1/boot1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/boot/efi/boot1/boot_module.h
===================================================================
--- trunk/sys/boot/efi/boot1/boot_module.h (rev 0)
+++ trunk/sys/boot/efi/boot1/boot_module.h 2018-06-02 12:43:49 UTC (rev 10208)
@@ -0,0 +1,116 @@
+/* $MidnightBSD$ */
+/*-
+ * 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: stable/10/sys/boot/efi/boot1/boot_module.h 318626 2017-05-22 06:29:20Z ngie $
+ */
+
+#ifndef _BOOT_MODULE_H_
+#define _BOOT_MODULE_H_
+
+#include <stdbool.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <eficonsctl.h>
+
+#ifdef EFI_DEBUG
+#define DPRINTF(fmt, args...) printf(fmt, ##args)
+#define DSTALL(d) bs->Stall(d)
+#else
+#define DPRINTF(fmt, ...) {}
+#define DSTALL(d) {}
+#endif
+
+/* EFI device info */
+typedef struct dev_info
+{
+ EFI_BLOCK_IO *dev;
+ EFI_DEVICE_PATH *devpath;
+ EFI_HANDLE *devhandle;
+ void *devdata;
+ BOOLEAN preferred;
+ 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)(void);
+
+ /*
+ * 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 the specified file.
+ *
+ * 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 *filepath, dev_info_t *devinfo,
+ void **buf, size_t *bufsize);
+
+ /* status outputs information about the probed devices. */
+ void (*status)(void);
+
+ /* valid devices as found by probe. */
+ dev_info_t *(*devices)(void);
+} 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 int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
+
+extern EFI_SYSTEM_TABLE *systab;
+extern EFI_BOOT_SERVICES *bs;
+
+extern int devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath);
+extern char *devpath_str(EFI_DEVICE_PATH *devpath);
+#endif
Property changes on: trunk/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 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
===================================================================
--- trunk/sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu (rev 0)
+++ trunk/sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu 2018-06-02 12:43:49 UTC (rev 10208)
@@ -0,0 +1,26 @@
+FAT template boot filesystem created by generate-fat.sh
+DO NOT EDIT
+$FreeBSD: stable/10/sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu 294725 2016-01-25 13:27:49Z smh $
+begin 644 fat-amd64.tmpl.bz2
+M0EIH.3%!62936;D*A>0`&T#_____ZZKJ[_^N_^O^Z_Z[OJ_NJ^JK^KZNKNNJ
+MZ^KNZOJ^P`+\&$`!D#0T:`80&@T#`@`-`:9`:`P"`R::```:8)II@@,FC(-&
+M$`!D,(:9`E5%&3_]*J?ZHC(--&@::#3)HQ#0`&C330,"9,F$::9!D#`F30#3
+M3)H9-&1DTR`R:,3"`&0-#1H!A`:#0,"``T!ID!H#`(#)IH``!I at FFF"`R:,@
+MT80`&0PAID!5)$)Y0 at R&HQ#3U-I--, at -&0R-&@T-`&FF at 9-!IIIH-&1ILHTT
+M&ADQ#-$\B;1-/2-H93$\4\34Q9ZDM*M:U49"2K6F0C'21$(GD$1$085)7RB(
+M00A7Q'^3"!"&CM$T+&UM5A49]7/"3^:EK7GMDVS9MRWK=+E>.(OG-?ZZMDA:
+MR74C/HR\T0"$,Y+,YBA.JO&6C*K-DV26*@S24I%*E-2I4J5*JH43)*%"A0H4
+M*5-"E)2E2I4J5+!RPP]&&&&&&,P(9X]&&&&&&.IMKISQPX<.'#AP at 0A"$(0A
+M"$(0A"(MX]&&&&&&&$(0A"$(0(0A"$(?ME2N'#APX<.'"+EZ,,,,,,,($(0A
+M"$0>NEGIM!8-(Y6FM$:.>9*3D219:RJKD^H2><E'K)-B^-<-VW[]G'7J_835
+MV`;*SC5&G@`GJ:N1`"ME+C<;GOI5H@!F'<0==<-#$2A&BJ%];5)UFHN9,G4?
+M]G6ARV-EJBOU_NY'021>1%9\LD8<E236-:]ILVV?0M6\<%=N2Y;G.DQ&<9G;
+MYJUNKRLLL]6X.TJQ;DFP1"P)D;"2W:]/XKP9*EC5W57(SUF^DRDD9N1\+:MN
+MLGV-ZX"Y<5R'+7S`832.Y=383)I.'I9>O.X4EIVM=.HDTT1'B:J=8;[A9NLU
+M"OX%C.X>0U/WZ^E74T&IHJ3EG))(^U[S\6_?HX;B.,Y*]7SGN at PV*_(O+^9#
+M+^Q,N_S1'42+=METV+CK9;+US'.8#H,%B,9Y*RD-/)TYXB8XQHI(RLF')')<
+MI>OZ<QW[FL!T6"X+#8C:LZZ5O?(VDD<W&Y\YA<5&NDFDA at -2Z#HNDWC!83#;
+MMB/W8SIL=EC%D8\FXDOI':7&/BN`UTRVDB;11`(0E`!CSIY+M)?HOW^+N2*<
+'*$A<A4+R````
+`
+end
Property changes on: trunk/sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/boot/efi/boot1/generate-fat.sh
===================================================================
--- trunk/sys/boot/efi/boot1/generate-fat.sh (rev 0)
+++ trunk/sys/boot/efi/boot1/generate-fat.sh 2018-06-02 12:43:49 UTC (rev 10208)
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# This script generates the dummy FAT filesystem used for the EFI boot
+# blocks. It uses newfs_msdos to generate a template filesystem with the
+# relevant interesting files. These are then found by grep, and the offsets
+# written to a Makefile snippet.
+#
+# Because it requires root, and because it is overkill, we do not
+# do this as part of the normal build. If makefs(8) grows workable FAT
+# support, this should be revisited.
+
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/boot/efi/boot1/generate-fat.sh 303297 2016-07-25 14:36:55Z emaste $
+
+FAT_SIZE=1600 #Size in 512-byte blocks of the produced image
+
+BOOT1_SIZE=128k
+
+#
+# Known filenames
+# amd64: BOOTx64.efi
+# arm64: BOOTaa64.efi
+#
+if [ -z "$1" ]; then
+ echo "Usage: $0 filename"
+ exit 1
+fi
+
+FILENAME=$1
+
+# Generate 800K FAT image
+OUTPUT_FILE=fat.tmpl
+
+dd if=/dev/zero of=$OUTPUT_FILE bs=512 count=$FAT_SIZE
+DEVICE=`mdconfig -a -f $OUTPUT_FILE`
+newfs_msdos -F 12 -L EFI $DEVICE
+mkdir stub
+mount -t msdosfs /dev/$DEVICE stub
+
+# Create and bless a directory for the boot loader
+mkdir -p stub/efi/boot
+
+# Make a dummy file for boot1
+echo 'Boot1 START' | dd of=stub/efi/boot/$FILENAME cbs=$BOOT1_SIZE count=1 conv=block
+# Provide a fallback startup.nsh
+echo $FILENAME > stub/efi/boot/startup.nsh
+
+umount stub
+mdconfig -d -u $DEVICE
+rmdir stub
+
+# Locate the offset of the fake file
+BOOT1_OFFSET=$(hd $OUTPUT_FILE | grep 'Boot1 START' | cut -f 1 -d ' ')
+
+# Convert to number of blocks
+BOOT1_OFFSET=$(echo 0x$BOOT1_OFFSET | awk '{printf("%x\n",$1/512);}')
+
+echo '# This file autogenerated by generate-fat.sh - DO NOT EDIT' > Makefile.fat
+echo '# $FreeBSD: stable/10/sys/boot/efi/boot1/generate-fat.sh 303297 2016-07-25 14:36:55Z emaste $' >> Makefile.fat
+echo "BOOT1_OFFSET=0x$BOOT1_OFFSET" >> Makefile.fat
+
+bzip2 $OUTPUT_FILE
+echo 'FAT template boot filesystem created by generate-fat.sh' > $OUTPUT_FILE.bz2.uu
+echo 'DO NOT EDIT' >> $OUTPUT_FILE.bz2.uu
+echo '$FreeBSD: stable/10/sys/boot/efi/boot1/generate-fat.sh 303297 2016-07-25 14:36:55Z emaste $' >> $OUTPUT_FILE.bz2.uu
+
+uuencode $OUTPUT_FILE.bz2 $OUTPUT_FILE.bz2 >> $OUTPUT_FILE.bz2.uu
+rm $OUTPUT_FILE.bz2
+
Property changes on: trunk/sys/boot/efi/boot1/generate-fat.sh
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/boot/efi/boot1/ufs_module.c
===================================================================
--- trunk/sys/boot/efi/boot1/ufs_module.c (rev 0)
+++ trunk/sys/boot/efi/boot1/ufs_module.c 2018-06-02 12:43:49 UTC (rev 10208)
@@ -0,0 +1,181 @@
+/* $MidnightBSD$ */
+/*-
+ * 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, 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: stable/10/sys/boot/efi/boot1/ufs_module.c 295550 2016-02-11 22:33:47Z smh $
+ */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <efi.h>
+
+#include "boot_module.h"
+
+static dev_info_t *devinfo;
+static dev_info_t *devices;
+
+static int
+dskread(void *buf, u_int64_t lba, int nblk)
+{
+ int size;
+ EFI_STATUS status;
+
+ lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE);
+ size = nblk * DEV_BSIZE;
+
+ status = devinfo->dev->ReadBlocks(devinfo->dev,
+ devinfo->dev->Media->MediaId, lba, size, buf);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("dskread: failed dev: %p, id: %u, lba: %lu, size: %d, "
+ "status: %lu\n", devinfo->dev,
+ devinfo->dev->Media->MediaId, lba, size,
+ EFI_ERROR_CODE(status));
+ return (-1);
+ }
+
+ return (0);
+}
+
+#include "ufsread.c"
+
+static struct dmadat __dmadat;
+
+static int
+init_dev(dev_info_t* dev)
+{
+
+ devinfo = dev;
+ dmadat = &__dmadat;
+
+ return fsread(0, NULL, 0);
+}
+
+static EFI_STATUS
+probe(dev_info_t* dev)
+{
+
+ if (init_dev(dev) < 0)
+ return (EFI_UNSUPPORTED);
+
+ add_device(&devices, dev);
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS
+load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize)
+{
+ ufs_ino_t ino;
+ EFI_STATUS status;
+ size_t size;
+ ssize_t read;
+ void *buf;
+
+ DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath));
+
+ if (init_dev(dev) < 0) {
+ DPRINTF("Failed to init device\n");
+ return (EFI_UNSUPPORTED);
+ }
+
+ if ((ino = lookup(filepath)) == 0) {
+ DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath);
+ return (EFI_NOT_FOUND);
+ }
+
+ if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) {
+ printf("Failed to read size of '%s' ino: %d\n", filepath, ino);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) !=
+ EFI_SUCCESS) {
+ printf("Failed to allocate read buffer %zu for '%s' (%lu)\n",
+ size, filepath, EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ read = fsread(ino, buf, size);
+ if ((size_t)read != size) {
+ printf("Failed to read '%s' (%zd != %zu)\n", filepath, read,
+ size);
+ (void)bs->FreePool(buf);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ DPRINTF("Load complete\n");
+
+ *bufp = buf;
+ *bufsize = size;
+
+ return (EFI_SUCCESS);
+}
+
+static void
+status()
+{
+ int i;
+ dev_info_t *dev;
+
+ for (dev = devices, i = 0; dev != NULL; dev = dev->next, i++)
+ ;
+
+ printf("%s found ", ufs_module.name);
+ switch (i) {
+ case 0:
+ printf("no partitions\n");
+ break;
+ case 1:
+ printf("%d partition\n", i);
+ break;
+ default:
+ printf("%d partitions\n", i);
+ }
+}
+
+static dev_info_t *
+_devices()
+{
+
+ return (devices);
+}
+
+const boot_module_t ufs_module =
+{
+ .name = "UFS",
+ .probe = probe,
+ .load = load,
+ .status = status,
+ .devices = _devices
+};
Property changes on: trunk/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 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/boot/efi/boot1/zfs_module.c
===================================================================
--- trunk/sys/boot/efi/boot1/zfs_module.c (rev 0)
+++ trunk/sys/boot/efi/boot1/zfs_module.c 2018-06-02 12:43:49 UTC (rev 10208)
@@ -0,0 +1,197 @@
+/* $MidnightBSD$ */
+/*-
+ * 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: stable/10/sys/boot/efi/boot1/zfs_module.c 321660 2017-07-28 18:35:29Z dim $
+ */
+#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"
+
+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: %zu, size: %zu,"
+ " status: %lu\n", devinfo->dev,
+ 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
+load(const char *filepath, dev_info_t *devinfo, 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;
+
+ DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name,
+ devpath_str(devinfo->devpath));
+
+ if ((err = zfs_spa_init(spa)) != 0) {
+ DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err);
+ return (EFI_NOT_FOUND);
+ }
+
+ if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) {
+ DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
+ return (EFI_NOT_FOUND);
+ }
+
+ if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) {
+ if (err == ENOENT) {
+ DPRINTF("Failed to find '%s' on pool '%s' (%d)\n",
+ filepath, spa->spa_name, err);
+ return (EFI_NOT_FOUND);
+ }
+ printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath,
+ spa->spa_name, err);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
+ printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath,
+ 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 %jd for pool '%s' for '%s' "
+ "(%lu)\n", (intmax_t)st.st_size, spa->spa_name, filepath, 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 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();
+}
+
+static dev_info_t *
+_devices()
+{
+
+ return (devices);
+}
+
+const boot_module_t zfs_module =
+{
+ .name = "ZFS",
+ .init = init,
+ .probe = probe,
+ .load = load,
+ .status = status,
+ .devices = _devices
+};
Property changes on: trunk/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 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
More information about the Midnightbsd-cvs
mailing list