[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