[Midnightbsd-cvs] src [10206] trunk/sys/boot/efi/loader: add x86 efi loader

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat Jun 2 08:39:13 EDT 2018


Revision: 10206
          http://svnweb.midnightbsd.org/src/?rev=10206
Author:   laffer1
Date:     2018-06-02 08:39:13 -0400 (Sat, 02 Jun 2018)
Log Message:
-----------
add x86 efi loader

Added Paths:
-----------
    trunk/sys/boot/efi/loader/
    trunk/sys/boot/efi/loader/Makefile
    trunk/sys/boot/efi/loader/arch/
    trunk/sys/boot/efi/loader/arch/amd64/
    trunk/sys/boot/efi/loader/arch/amd64/Makefile.inc
    trunk/sys/boot/efi/loader/arch/amd64/amd64_tramp.S
    trunk/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
    trunk/sys/boot/efi/loader/arch/amd64/framebuffer.c
    trunk/sys/boot/efi/loader/arch/amd64/framebuffer.h
    trunk/sys/boot/efi/loader/arch/amd64/ldscript.amd64
    trunk/sys/boot/efi/loader/arch/amd64/reloc.c
    trunk/sys/boot/efi/loader/arch/amd64/start.S
    trunk/sys/boot/efi/loader/arch/i386/
    trunk/sys/boot/efi/loader/autoload.c
    trunk/sys/boot/efi/loader/bootinfo.c
    trunk/sys/boot/efi/loader/conf.c
    trunk/sys/boot/efi/loader/copy.c
    trunk/sys/boot/efi/loader/devicename.c
    trunk/sys/boot/efi/loader/loader_efi.h
    trunk/sys/boot/efi/loader/main.c
    trunk/sys/boot/efi/loader/version

Added: trunk/sys/boot/efi/loader/Makefile
===================================================================
--- trunk/sys/boot/efi/loader/Makefile	                        (rev 0)
+++ trunk/sys/boot/efi/loader/Makefile	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,133 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/boot/efi/loader/Makefile 304507 2016-08-19 23:31:56Z jhb $
+
+MAN=
+
+.include <bsd.own.mk>
+
+MK_SSP=		no
+
+PROG=		loader.sym
+INTERNALPROG=
+WARNS?=		3
+
+# architecture-specific loader code
+SRCS=	autoload.c \
+	bootinfo.c \
+	conf.c \
+	copy.c \
+	devicename.c \
+	main.c \
+	smbios.c \
+	vers.c
+
+.if ${MK_ZFS} != "no"
+SRCS+=		zfs.c
+.PATH:		${.CURDIR}/../../zfs
+
+# Disable warnings that are currently incompatible with the zfs boot code
+CWARNFLAGS.zfs.c+=	-Wno-sign-compare
+CWARNFLAGS.zfs.c+=	-Wno-array-bounds
+CWARNFLAGS.zfs.c+=	-Wno-missing-prototypes
+.endif
+
+.PATH: ${.CURDIR}/arch/${MACHINE}
+# For smbios.c
+.PATH: ${.CURDIR}/../../i386/libi386
+.include "${.CURDIR}/arch/${MACHINE}/Makefile.inc"
+
+CFLAGS+=	-fPIC
+CFLAGS+=	-I${.CURDIR}
+CFLAGS+=	-I${.CURDIR}/arch/${MACHINE}
+CFLAGS+=	-I${.CURDIR}/../include
+CFLAGS+=	-I${.CURDIR}/../include/${MACHINE}
+CFLAGS+=	-I${.CURDIR}/../../../contrib/dev/acpica/include
+CFLAGS+=	-I${.CURDIR}/../../..
+CFLAGS+=	-I${.CURDIR}/../../i386/libi386
+.if ${MK_ZFS} != "no"
+CFLAGS+=	-I${.CURDIR}/../../zfs
+CFLAGS+=	-I${.CURDIR}/../../../cddl/boot/zfs
+CFLAGS+=	-DEFI_ZFS_BOOT
+.endif
+CFLAGS+=	-DNO_PCI -DEFI
+
+.if !defined(BOOT_HIDE_SERIAL_NUMBERS)
+# Export serial numbers, UUID, and asset tag from loader.
+CFLAGS+= -DSMBIOS_SERIAL_NUMBERS
+.if defined(BOOT_LITTLE_ENDIAN_UUID)
+# Use little-endian UUID format as defined in SMBIOS 2.6.
+CFLAGS+= -DSMBIOS_LITTLE_ENDIAN_UUID
+.elif defined(BOOT_NETWORK_ENDIAN_UUID)
+# Use network-endian UUID format for backward compatibility.
+CFLAGS+= -DSMBIOS_NETWORK_ENDIAN_UUID
+.endif
+.endif
+
+.if ${MK_FORTH} != "no"
+BOOT_FORTH=	yes
+CFLAGS+=	-DBOOT_FORTH
+CFLAGS+=	-I${.CURDIR}/../../ficl
+CFLAGS+=	-I${.CURDIR}/../../ficl/${MACHINE}
+LIBFICL=	${.OBJDIR}/../../ficl/libficl.a
+.endif
+
+# Include bcache code.
+HAVE_BCACHE=    yes
+
+.if defined(EFI_STAGING_SIZE)
+CFLAGS+=	-DEFI_STAGING_SIZE=${EFI_STAGING_SIZE}
+.endif
+
+# Always add MI sources
+.PATH:		${.CURDIR}/../../common
+.include	"${.CURDIR}/../../common/Makefile.inc"
+CFLAGS+=	-I${.CURDIR}/../../common
+
+FILES=	loader.efi
+FILESMODE_loader.efi=	${BINMODE}
+
+LDSCRIPT=	${.CURDIR}/arch/${MACHINE}/ldscript.${MACHINE}
+LDFLAGS=	-Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared -Wl,-znocombreloc
+
+CLEANFILES=	vers.c loader.efi
+
+NEWVERSWHAT=	"EFI loader" ${MACHINE}
+
+vers.c:	${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../../efi/loader/version
+	sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
+
+NM?=		nm
+OBJCOPY?=	objcopy
+
+.if ${MACHINE_CPUARCH} == "amd64"
+EFI_TARGET=	efi-app-x86_64
+.elif ${MACHINE_CPUARCH} == "i386"
+EFI_TARGET=	efi-app-ia32
+.endif
+
+loader.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 -j set_Xcommand_set \
+		--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
+
+LIBEFI=		${.OBJDIR}/../libefi/libefi.a
+
+DPADD=		${LIBFICL} ${LIBEFI} ${LIBSTAND} ${LDSCRIPT}
+LDADD=		${LIBFICL} ${LIBEFI} ${LIBSTAND}
+
+.include <bsd.prog.mk>
+
+beforedepend ${OBJS}: machine x86
+
+CLEANFILES+=   machine x86
+
+machine:
+	ln -sf ${.CURDIR}/../../../amd64/include machine
+
+x86:
+	ln -sf ${.CURDIR}/../../../x86/include x86


Property changes on: trunk/sys/boot/efi/loader/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/loader/arch/amd64/Makefile.inc
===================================================================
--- trunk/sys/boot/efi/loader/arch/amd64/Makefile.inc	                        (rev 0)
+++ trunk/sys/boot/efi/loader/arch/amd64/Makefile.inc	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,12 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/boot/efi/loader/arch/amd64/Makefile.inc 293297 2016-01-07 02:22:45Z emaste $
+
+SRCS+=	amd64_tramp.S \
+	start.S \
+	framebuffer.c \
+	elf64_freebsd.c \
+	reloc.c
+
+.PATH:	${.CURDIR}/../../i386/libi386
+SRCS+=	nullconsole.c \
+	comconsole.c


Property changes on: trunk/sys/boot/efi/loader/arch/amd64/Makefile.inc
___________________________________________________________________
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/loader/arch/amd64/amd64_tramp.S
===================================================================
--- trunk/sys/boot/efi/loader/arch/amd64/amd64_tramp.S	                        (rev 0)
+++ trunk/sys/boot/efi/loader/arch/amd64/amd64_tramp.S	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,65 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Benno Rice under sponsorship from
+ * the FreeBSD Foundation.
+ * 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/loader/arch/amd64/amd64_tramp.S 293297 2016-01-07 02:22:45Z emaste $
+ */
+
+#include <machine/asmacros.h>
+
+	.text
+	.globl	amd64_tramp
+
+/*
+ * void amd64_tramp(uint64_t stack, void *copy_finish, uint64_t kernend,
+ *		    uint64_t modulep, uint64_t pagetable, uint64_t entry)
+ */
+amd64_tramp:
+	cli			/* Make sure we don't get interrupted. */
+	movq	%rdi,%rsp	/* Switch to our temporary stack. */
+
+	movq	%rdx,%r12	/* Stash the kernel values for later. */
+	movq	%rcx,%r13
+	movq	%r8,%r14
+	movq	%r9,%r15
+
+	callq	*%rsi		/* Call copy_finish so we're all ready to go. */
+
+	pushq	%r12		/* Push kernend. */
+	salq	$32,%r13	/* Shift modulep and push it. */
+	pushq	%r13
+	pushq	%r15		/* Push the entry address. */
+	movq	%r14,%cr3	/* Switch page tables. */
+	ret			/* "Return" to kernel entry. */
+
+	ALIGN_TEXT
+amd64_tramp_end:
+
+	.data
+	.globl	amd64_tramp_size
+amd64_tramp_size:
+	.long	amd64_tramp_end-amd64_tramp


Property changes on: trunk/sys/boot/efi/loader/arch/amd64/amd64_tramp.S
___________________________________________________________________
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/loader/arch/amd64/elf64_freebsd.c
===================================================================
--- trunk/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,190 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith at freebsd.org>
+ * Copyright (c) 2014 The FreeBSD Foundation
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c 294981 2016-01-28 12:11:42Z smh $");
+
+#define __ELF_WORD_SIZE 64
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/linker.h>
+#include <string.h>
+#include <machine/elf.h>
+#include <stand.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+
+#include "platform/acfreebsd.h"
+#include "acconfig.h"
+#define ACPI_SYSTEM_XFACE
+#define ACPI_USE_SYSTEM_INTTYPES
+#include "actypes.h"
+#include "actbl.h"
+
+#include "loader_efi.h"
+
+static EFI_GUID acpi_guid = ACPI_TABLE_GUID;
+static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID;
+
+extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp);
+
+static int	elf64_exec(struct preloaded_file *amp);
+static int	elf64_obj_exec(struct preloaded_file *amp);
+
+static struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
+static struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
+
+struct file_format *file_formats[] = {
+	&amd64_elf,
+	&amd64_elf_obj,
+	NULL
+};
+
+#define PG_V    0x001
+#define PG_RW   0x002
+#define PG_U    0x004
+#define PG_PS   0x080
+
+typedef u_int64_t p4_entry_t;
+typedef u_int64_t p3_entry_t;
+typedef u_int64_t p2_entry_t;
+static p4_entry_t *PT4;
+static p3_entry_t *PT3;
+static p2_entry_t *PT2;
+
+static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend,
+			  uint64_t modulep, p4_entry_t *pagetable,
+			  uint64_t entry);
+
+extern uintptr_t amd64_tramp;
+extern uint32_t amd64_tramp_size;
+
+/*
+ * There is an ELF kernel and one or more ELF modules loaded.
+ * We wish to start executing the kernel image, so make such
+ * preparations as are required, and do so.
+ */
+static int
+elf64_exec(struct preloaded_file *fp)
+{
+	struct file_metadata	*md;
+	Elf_Ehdr 		*ehdr;
+	vm_offset_t		modulep, kernend, trampcode, trampstack;
+	int			err, i;
+	ACPI_TABLE_RSDP		*rsdp;
+	char			buf[24];
+	int			revision;
+
+	rsdp = efi_get_table(&acpi20_guid);
+	if (rsdp == NULL) {
+		rsdp = efi_get_table(&acpi_guid);
+	}
+	if (rsdp != NULL) {
+		sprintf(buf, "0x%016llx", (unsigned long long)rsdp);
+		setenv("hint.acpi.0.rsdp", buf, 1);
+		revision = rsdp->Revision;
+		if (revision == 0)
+			revision = 1;
+		sprintf(buf, "%d", revision);
+		setenv("hint.acpi.0.revision", buf, 1);
+		strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
+		buf[sizeof(rsdp->OemId)] = '\0';
+		setenv("hint.acpi.0.oem", buf, 1);
+		sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress);
+		setenv("hint.acpi.0.rsdt", buf, 1);
+		if (revision >= 2) {
+			/* XXX extended checksum? */
+			sprintf(buf, "0x%016llx",
+			    (unsigned long long)rsdp->XsdtPhysicalAddress);
+			setenv("hint.acpi.0.xsdt", buf, 1);
+			sprintf(buf, "%d", rsdp->Length);
+			setenv("hint.acpi.0.xsdt_length", buf, 1);
+		}
+	}
+
+	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
+		return(EFTYPE);
+	ehdr = (Elf_Ehdr *)&(md->md_data);
+
+	trampcode = (vm_offset_t)0x0000000040000000;
+	err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1,
+	    (EFI_PHYSICAL_ADDRESS *)&trampcode);
+	bzero((void *)trampcode, EFI_PAGE_SIZE);
+	trampstack = trampcode + EFI_PAGE_SIZE - 8;
+	bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size);
+	trampoline = (void *)trampcode;
+
+	PT4 = (p4_entry_t *)0x0000000040000000;
+	err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3,
+	    (EFI_PHYSICAL_ADDRESS *)&PT4);
+	bzero(PT4, 3 * EFI_PAGE_SIZE);
+
+	PT3 = &PT4[512];
+	PT2 = &PT3[512];
+
+	/*
+	 * This is kinda brutal, but every single 1GB VM memory segment points
+	 * to the same first 1GB of physical memory.  But it is more than
+	 * adequate.
+	 */
+	for (i = 0; i < 512; i++) {
+		/* Each slot of the L4 pages points to the same L3 page. */
+		PT4[i] = (p4_entry_t)PT3;
+		PT4[i] |= PG_V | PG_RW | PG_U;
+
+		/* Each slot of the L3 pages points to the same L2 page. */
+		PT3[i] = (p3_entry_t)PT2;
+		PT3[i] |= PG_V | PG_RW | PG_U;
+
+		/* The L2 page slots are mapped with 2MB pages for 1GB. */
+		PT2[i] = i * (2 * 1024 * 1024);
+		PT2[i] |= PG_V | PG_RW | PG_PS | PG_U;
+	}
+
+	printf("Start @ 0x%lx ...\n", ehdr->e_entry);
+
+	err = bi_load(fp->f_args, &modulep, &kernend);
+	if (err != 0)
+		return(err);
+
+	dev_cleanup();
+
+	trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4,
+	    ehdr->e_entry);
+
+	panic("exec returned");
+}
+
+static int
+elf64_obj_exec(struct preloaded_file *fp)
+{
+	return (EFTYPE);
+}


Property changes on: trunk/sys/boot/efi/loader/arch/amd64/elf64_freebsd.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/loader/arch/amd64/framebuffer.c
===================================================================
--- trunk/sys/boot/efi/loader/arch/amd64/framebuffer.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/arch/amd64/framebuffer.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,567 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Benno Rice under sponsorship from
+ * the FreeBSD Foundation.
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/arch/amd64/framebuffer.c 297555 2016-04-04 12:21:04Z marius $");
+
+#include <bootstrap.h>
+#include <sys/endian.h>
+#include <stand.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <efiuga.h>
+#include <efipciio.h>
+#include <machine/metadata.h>
+
+#include "framebuffer.h"
+
+static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+static EFI_GUID pciio_guid = EFI_PCI_IO_PROTOCOL_GUID;
+static EFI_GUID uga_guid = EFI_UGA_DRAW_PROTOCOL_GUID;
+
+static u_int
+efifb_color_depth(struct efi_fb *efifb)
+{
+	uint32_t mask;
+	u_int depth;
+
+	mask = efifb->fb_mask_red | efifb->fb_mask_green |
+	    efifb->fb_mask_blue | efifb->fb_mask_reserved;
+	if (mask == 0)
+		return (0);
+	for (depth = 1; mask != 1; depth++)
+		mask >>= 1;
+	return (depth);
+}
+
+static int
+efifb_mask_from_pixfmt(struct efi_fb *efifb, EFI_GRAPHICS_PIXEL_FORMAT pixfmt,
+    EFI_PIXEL_BITMASK *pixinfo)
+{
+	int result;
+
+	result = 0;
+	switch (pixfmt) {
+	case PixelRedGreenBlueReserved8BitPerColor:
+		efifb->fb_mask_red = 0x000000ff;
+		efifb->fb_mask_green = 0x0000ff00;
+		efifb->fb_mask_blue = 0x00ff0000;
+		efifb->fb_mask_reserved = 0xff000000;
+		break;
+	case PixelBlueGreenRedReserved8BitPerColor:
+		efifb->fb_mask_red = 0x00ff0000;
+		efifb->fb_mask_green = 0x0000ff00;
+		efifb->fb_mask_blue = 0x000000ff;
+		efifb->fb_mask_reserved = 0xff000000;
+		break;
+	case PixelBitMask:
+		efifb->fb_mask_red = pixinfo->RedMask;
+		efifb->fb_mask_green = pixinfo->GreenMask;
+		efifb->fb_mask_blue = pixinfo->BlueMask;
+		efifb->fb_mask_reserved = pixinfo->ReservedMask;
+		break;
+	default:
+		result = 1;
+		break;
+	}
+	return (result);
+}
+
+static int
+efifb_from_gop(struct efi_fb *efifb, EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *mode,
+    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info)
+{
+	int result;
+
+	efifb->fb_addr = mode->FrameBufferBase;
+	efifb->fb_size = mode->FrameBufferSize;
+	efifb->fb_height = info->VerticalResolution;
+	efifb->fb_width = info->HorizontalResolution;
+	efifb->fb_stride = info->PixelsPerScanLine;
+	result = efifb_mask_from_pixfmt(efifb, info->PixelFormat,
+	    &info->PixelInformation);
+	return (result);
+}
+
+static ssize_t
+efifb_uga_find_pixel(EFI_UGA_DRAW_PROTOCOL *uga, u_int line,
+    EFI_PCI_IO_PROTOCOL *pciio, uint64_t addr, uint64_t size)
+{
+	EFI_UGA_PIXEL pix0, pix1;
+	uint8_t *data1, *data2;
+	size_t count, maxcount = 1024;
+	ssize_t ofs;
+	EFI_STATUS status;
+	u_int idx;
+
+	status = uga->Blt(uga, &pix0, EfiUgaVideoToBltBuffer,
+	    0, line, 0, 0, 1, 1, 0);
+	if (EFI_ERROR(status)) {
+		printf("UGA BLT operation failed (video->buffer)");
+		return (-1);
+	}
+	pix1.Red = ~pix0.Red;
+	pix1.Green = ~pix0.Green;
+	pix1.Blue = ~pix0.Blue;
+	pix1.Reserved = 0;
+
+	data1 = calloc(maxcount, 2);
+	if (data1 == NULL) {
+		printf("Unable to allocate memory");
+		return (-1);
+	}
+	data2 = data1 + maxcount;
+
+	ofs = 0;
+	while (size > 0) {
+		count = min(size, maxcount);
+
+		status = pciio->Mem.Read(pciio, EfiPciIoWidthUint32,
+		    EFI_PCI_IO_PASS_THROUGH_BAR, addr + ofs, count >> 2,
+		    data1);
+		if (EFI_ERROR(status)) {
+			printf("Error reading frame buffer (before)");
+			goto fail;
+		}
+		status = uga->Blt(uga, &pix1, EfiUgaBltBufferToVideo,
+		    0, 0, 0, line, 1, 1, 0);
+		if (EFI_ERROR(status)) {
+			printf("UGA BLT operation failed (modify)");
+			goto fail;
+		}
+		status = pciio->Mem.Read(pciio, EfiPciIoWidthUint32,
+		    EFI_PCI_IO_PASS_THROUGH_BAR, addr + ofs, count >> 2,
+		    data2);
+		if (EFI_ERROR(status)) {
+			printf("Error reading frame buffer (after)");
+			goto fail;
+		}
+		status = uga->Blt(uga, &pix0, EfiUgaBltBufferToVideo,
+		    0, 0, 0, line, 1, 1, 0);
+		if (EFI_ERROR(status)) {
+			printf("UGA BLT operation failed (restore)");
+			goto fail;
+		}
+		for (idx = 0; idx < count; idx++) {
+			if (data1[idx] != data2[idx]) {
+				free(data1);
+				return (ofs + (idx & ~3));
+			}
+		}
+		ofs += count;
+		size -= count;
+	}
+	printf("No change detected in frame buffer");
+
+ fail:
+	printf(" -- error %lu\n", EFI_ERROR_CODE(status));
+	free(data1);
+	return (-1);
+}
+
+static EFI_PCI_IO_PROTOCOL *
+efifb_uga_get_pciio(void)
+{
+	EFI_PCI_IO_PROTOCOL *pciio;
+	EFI_HANDLE *buf, *hp;
+	EFI_STATUS status;
+	UINTN bufsz;
+
+	/* Get all handles that support the UGA protocol. */
+	bufsz = 0;
+	status = BS->LocateHandle(ByProtocol, &uga_guid, NULL, &bufsz, NULL);
+	if (status != EFI_BUFFER_TOO_SMALL)
+		return (NULL);
+	buf = malloc(bufsz);
+	status = BS->LocateHandle(ByProtocol, &uga_guid, NULL, &bufsz, buf);
+	if (status != EFI_SUCCESS) {
+		free(buf);
+		return (NULL);
+	}
+	bufsz /= sizeof(EFI_HANDLE);
+
+	/* Get the PCI I/O interface of the first handle that supports it. */
+	pciio = NULL;
+	for (hp = buf; hp < buf + bufsz; hp++) {
+		status = BS->HandleProtocol(*hp, &pciio_guid, (void **)&pciio);
+		if (status == EFI_SUCCESS) {
+			free(buf);
+			return (pciio);
+		}
+	}
+	free(buf);
+	return (NULL);
+}
+
+static EFI_STATUS
+efifb_uga_locate_framebuffer(EFI_PCI_IO_PROTOCOL *pciio, uint64_t *addrp,
+    uint64_t *sizep)
+{
+	uint8_t *resattr;
+	uint64_t addr, size;
+	EFI_STATUS status;
+	u_int bar;
+
+	if (pciio == NULL)
+		return (EFI_DEVICE_ERROR);
+
+	/* Attempt to get the frame buffer address (imprecise). */
+	*addrp = 0;
+	*sizep = 0;
+	for (bar = 0; bar < 6; bar++) {
+		status = pciio->GetBarAttributes(pciio, bar, NULL,
+		    (void **)&resattr);
+		if (status != EFI_SUCCESS)
+			continue;
+		/* XXX magic offsets and constants. */
+		if (resattr[0] == 0x87 && resattr[3] == 0) {
+			/* 32-bit address space descriptor (MEMIO) */
+			addr = le32dec(resattr + 10);
+			size = le32dec(resattr + 22);
+		} else if (resattr[0] == 0x8a && resattr[3] == 0) {
+			/* 64-bit address space descriptor (MEMIO) */
+			addr = le64dec(resattr + 14);
+			size = le64dec(resattr + 38);
+		} else {
+			addr = 0;
+			size = 0;
+		}
+		BS->FreePool(resattr);
+		if (addr == 0 || size == 0)
+			continue;
+
+		/* We assume the largest BAR is the frame buffer. */
+		if (size > *sizep) {
+			*addrp = addr;
+			*sizep = size;
+		}
+	}
+	return ((*addrp == 0 || *sizep == 0) ? EFI_DEVICE_ERROR : 0);
+}
+
+static int
+efifb_from_uga(struct efi_fb *efifb, EFI_UGA_DRAW_PROTOCOL *uga)
+{
+	EFI_PCI_IO_PROTOCOL *pciio;
+	char *ev, *p;
+	EFI_STATUS status;
+	ssize_t offset;
+	uint64_t fbaddr;
+	uint32_t horiz, vert, stride;
+	uint32_t np, depth, refresh;
+
+	status = uga->GetMode(uga, &horiz, &vert, &depth, &refresh);
+	if (EFI_ERROR(status))
+		return (1);
+	efifb->fb_height = vert;
+	efifb->fb_width = horiz;
+	/* Paranoia... */
+	if (efifb->fb_height == 0 || efifb->fb_width == 0)
+		return (1);
+
+	/* The color masks are fixed AFAICT. */
+	efifb_mask_from_pixfmt(efifb, PixelBlueGreenRedReserved8BitPerColor,
+	    NULL);
+
+	/* pciio can be NULL on return! */
+	pciio = efifb_uga_get_pciio();
+
+	/* Try to find the frame buffer. */
+	status = efifb_uga_locate_framebuffer(pciio, &efifb->fb_addr,
+	    &efifb->fb_size);
+	if (EFI_ERROR(status)) {
+		efifb->fb_addr = 0;
+		efifb->fb_size = 0;
+	}
+
+	/*
+	 * There's no reliable way to detect the frame buffer or the
+	 * offset within the frame buffer of the visible region, nor
+	 * the stride. Our only option is to look at the system and
+	 * fill in the blanks based on that. Luckily, UGA was mostly
+	 * only used on Apple hardware.
+	 */
+	offset = -1;
+	ev = getenv("smbios.system.maker");
+	if (ev != NULL && !strcmp(ev, "Apple Inc.")) {
+		ev = getenv("smbios.system.product");
+		if (ev != NULL && !strcmp(ev, "iMac7,1")) {
+			/* These are the expected values we should have. */
+			horiz = 1680;
+			vert = 1050;
+			fbaddr = 0xc0000000;
+			/* These are the missing bits. */
+			offset = 0x10000;
+			stride = 1728;
+		} else if (ev != NULL && !strcmp(ev, "MacBook3,1")) {
+			/* These are the expected values we should have. */
+			horiz = 1280;
+			vert = 800;
+			fbaddr = 0xc0000000;
+			/* These are the missing bits. */
+			offset = 0x0;
+			stride = 2048;
+		}
+	}
+
+	/*
+	 * If this is hardware we know, make sure that it looks familiar
+	 * before we accept our hardcoded values.
+	 */
+	if (offset >= 0 && efifb->fb_width == horiz &&
+	    efifb->fb_height == vert && efifb->fb_addr == fbaddr) {
+		efifb->fb_addr += offset;
+		efifb->fb_size -= offset;
+		efifb->fb_stride = stride;
+		return (0);
+	} else if (offset >= 0) {
+		printf("Hardware make/model known, but graphics not "
+		    "as expected.\n");
+		printf("Console may not work!\n");
+	}
+
+	/*
+	 * The stride is equal or larger to the width. Often it's the
+	 * next larger power of two. We'll start with that...
+	 */
+	efifb->fb_stride = efifb->fb_width;
+	do {
+		np = efifb->fb_stride & (efifb->fb_stride - 1);
+		if (np) {
+			efifb->fb_stride |= (np - 1);
+			efifb->fb_stride++;
+		}
+	} while (np);
+
+	ev = getenv("hw.efifb.address");
+	if (ev == NULL) {
+		if (efifb->fb_addr == 0) {
+			printf("Please set hw.efifb.address and "
+			    "hw.efifb.stride.\n");
+			return (1);
+		}
+
+		/*
+		 * The visible part of the frame buffer may not start at
+		 * offset 0, so try to detect it. Note that we may not
+		 * always be able to read from the frame buffer, which
+		 * means that we may not be able to detect anything. In
+		 * that case, we would take a long time scanning for a
+		 * pixel change in the frame buffer, which would have it
+		 * appear that we're hanging, so we limit the scan to
+		 * 1/256th of the frame buffer. This number is mostly
+		 * based on PR 202730 and the fact that on a MacBoook,
+		 * where we can't read from the frame buffer the offset
+		 * of the visible region is 0. In short: we want to scan
+		 * enough to handle all adapters that have an offset
+		 * larger than 0 and we want to scan as little as we can
+		 * to not appear to hang when we can't read from the
+		 * frame buffer.
+		 */
+		offset = efifb_uga_find_pixel(uga, 0, pciio, efifb->fb_addr,
+		    efifb->fb_size >> 8);
+		if (offset == -1) {
+			printf("Unable to reliably detect frame buffer.\n");
+		} else if (offset > 0) {
+			efifb->fb_addr += offset;
+			efifb->fb_size -= offset;
+		}
+	} else {
+		offset = 0;
+		efifb->fb_size = efifb->fb_height * efifb->fb_stride * 4;
+		efifb->fb_addr = strtoul(ev, &p, 0);
+		if (*p != '\0')
+			return (1);
+	}
+
+	ev = getenv("hw.efifb.stride");
+	if (ev == NULL) {
+		if (pciio != NULL && offset != -1) {
+			/* Determine the stride. */
+			offset = efifb_uga_find_pixel(uga, 1, pciio,
+			    efifb->fb_addr, horiz * 8);
+			if (offset != -1)
+				efifb->fb_stride = offset >> 2;
+		} else {
+			printf("Unable to reliably detect the stride.\n");
+		}
+	} else {
+		efifb->fb_stride = strtoul(ev, &p, 0);
+		if (*p != '\0')
+			return (1);
+	}
+
+	/*
+	 * We finalized on the stride, so recalculate the size of the
+	 * frame buffer.
+	 */
+	efifb->fb_size = efifb->fb_height * efifb->fb_stride * 4;
+	return (0);
+}
+
+int
+efi_find_framebuffer(struct efi_fb *efifb)
+{
+	EFI_GRAPHICS_OUTPUT *gop;
+	EFI_UGA_DRAW_PROTOCOL *uga;
+	EFI_STATUS status;
+
+	status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop);
+	if (status == EFI_SUCCESS)
+		return (efifb_from_gop(efifb, gop->Mode, gop->Mode->Info));
+
+	status = BS->LocateProtocol(&uga_guid, NULL, (VOID **)&uga);
+	if (status == EFI_SUCCESS)
+		return (efifb_from_uga(efifb, uga));
+
+	return (1);
+}
+
+static void
+print_efifb(int mode, struct efi_fb *efifb, int verbose)
+{
+	u_int depth;
+
+	if (mode >= 0)
+		printf("mode %d: ", mode);
+	depth = efifb_color_depth(efifb);
+	printf("%ux%ux%u, stride=%u", efifb->fb_width, efifb->fb_height,
+	    depth, efifb->fb_stride);
+	if (verbose) {
+		printf("\n    frame buffer: address=%jx, size=%jx",
+		    (uintmax_t)efifb->fb_addr, (uintmax_t)efifb->fb_size);
+		printf("\n    color mask: R=%08x, G=%08x, B=%08x\n",
+		    efifb->fb_mask_red, efifb->fb_mask_green,
+		    efifb->fb_mask_blue);
+	}
+}
+
+COMMAND_SET(gop, "gop", "graphics output protocol", command_gop);
+
+static int
+command_gop(int argc, char *argv[])
+{
+	struct efi_fb efifb;
+	EFI_GRAPHICS_OUTPUT *gop;
+	EFI_STATUS status;
+	u_int mode;
+
+	status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop);
+	if (EFI_ERROR(status)) {
+		sprintf(command_errbuf, "%s: Graphics Output Protocol not "
+		    "present (error=%lu)", argv[0], EFI_ERROR_CODE(status));
+		return (CMD_ERROR);
+	}
+
+	if (argc < 2)
+		goto usage;
+
+	if (!strcmp(argv[1], "set")) {
+		char *cp;
+
+		if (argc != 3)
+			goto usage;
+		mode = strtol(argv[2], &cp, 0);
+		if (cp[0] != '\0') {
+			sprintf(command_errbuf, "mode is an integer");
+			return (CMD_ERROR);
+		}
+		status = gop->SetMode(gop, mode);
+		if (EFI_ERROR(status)) {
+			sprintf(command_errbuf, "%s: Unable to set mode to "
+			    "%u (error=%lu)", argv[0], mode,
+			    EFI_ERROR_CODE(status));
+			return (CMD_ERROR);
+		}
+	} else if (!strcmp(argv[1], "get")) {
+		if (argc != 2)
+			goto usage;
+		efifb_from_gop(&efifb, gop->Mode, gop->Mode->Info);
+		print_efifb(gop->Mode->Mode, &efifb, 1);
+		printf("\n");
+	} else if (!strcmp(argv[1], "list")) {
+		EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
+		UINTN infosz;
+
+		if (argc != 2)
+			goto usage;
+		pager_open();
+		for (mode = 0; mode < gop->Mode->MaxMode; mode++) {
+			status = gop->QueryMode(gop, mode, &infosz, &info);
+			if (EFI_ERROR(status))
+				continue;
+			efifb_from_gop(&efifb, gop->Mode, info);
+			print_efifb(mode, &efifb, 0);
+			if (pager_output("\n"))
+				break;
+		}
+		pager_close();
+	}
+	return (CMD_OK);
+
+ usage:
+	sprintf(command_errbuf, "usage: %s [list | get | set <mode>]",
+	    argv[0]);
+	return (CMD_ERROR);
+}
+
+COMMAND_SET(uga, "uga", "universal graphics adapter", command_uga);
+
+static int
+command_uga(int argc, char *argv[])
+{
+	struct efi_fb efifb;
+	EFI_UGA_DRAW_PROTOCOL *uga;
+	EFI_STATUS status;
+
+	status = BS->LocateProtocol(&uga_guid, NULL, (VOID **)&uga);
+	if (EFI_ERROR(status)) {
+		sprintf(command_errbuf, "%s: UGA Protocol not present "
+		    "(error=%lu)", argv[0], EFI_ERROR_CODE(status));
+		return (CMD_ERROR);
+	}
+
+	if (argc != 1)
+		goto usage;
+
+	if (efifb_from_uga(&efifb, uga) != CMD_OK) {
+		sprintf(command_errbuf, "%s: Unable to get UGA information",
+		    argv[0]);
+		return (CMD_ERROR);
+	}
+
+	print_efifb(-1, &efifb, 1);
+	printf("\n");
+	return (CMD_OK);
+
+ usage:
+	sprintf(command_errbuf, "usage: %s", argv[0]);
+	return (CMD_ERROR);
+}


Property changes on: trunk/sys/boot/efi/loader/arch/amd64/framebuffer.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/loader/arch/amd64/framebuffer.h
===================================================================
--- trunk/sys/boot/efi/loader/arch/amd64/framebuffer.h	                        (rev 0)
+++ trunk/sys/boot/efi/loader/arch/amd64/framebuffer.h	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Benno Rice under sponsorship from
+ * the FreeBSD Foundation.
+ * 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/loader/arch/amd64/framebuffer.h 293297 2016-01-07 02:22:45Z emaste $
+ */
+
+#ifndef	_EFIFB_H_
+#define	_EFIFB_H_
+
+int	efi_find_framebuffer(struct efi_fb *efifb);
+
+#endif /* _EFIFB_H_ */


Property changes on: trunk/sys/boot/efi/loader/arch/amd64/framebuffer.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/loader/arch/amd64/ldscript.amd64
===================================================================
--- trunk/sys/boot/efi/loader/arch/amd64/ldscript.amd64	                        (rev 0)
+++ trunk/sys/boot/efi/loader/arch/amd64/ldscript.amd64	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,68 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/boot/efi/loader/arch/amd64/ldscript.amd64 293297 2016-01-07 02:22:45Z emaste $ */
+OUTPUT_FORMAT("elf64-x86-64-freebsd", "elf64-x86-64-freebsd", "elf64-x86-64-freebsd")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0;
+  ImageBase = .;
+  .hash : { *(.hash) }  /* this MUST come first! */
+  . = ALIGN(4096);
+  .eh_frame :
+  {
+    *(.eh_frame)
+  }
+  . = ALIGN(4096);
+  .text		: {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em. */
+    *(.gnu.warning)
+    *(.plt)
+  } =0x00300000010070000002000001000400
+  . = ALIGN(4096);
+  .data		: {
+    *(.rodata .rodata.* .gnu.linkonce.r.*)
+    *(.rodata1)
+    *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+    *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
+    *(.opd)
+    *(.data .data.* .gnu.linkonce.d.*)
+    *(.data1)
+    *(.plabel)
+    *(.dynbss)
+    *(.bss .bss.* .gnu.linkonce.b.*)
+    *(COMMON)
+  }
+  . = ALIGN(4096);
+  set_Xcommand_set	: {
+    __start_set_Xcommand_set = .;
+    *(set_Xcommand_set)
+    __stop_set_Xcommand_set = .;
+  }
+  . = ALIGN(4096);
+  __gp = .;
+  .sdata	: {
+    *(.got.plt .got)
+    *(.sdata .sdata.* .gnu.linkonce.s.*)
+    *(dynsbss)
+    *(.sbss .sbss.* .gnu.linkonce.sb.*)
+    *(.scommon)
+  }
+  . = ALIGN(4096);
+  .dynamic	: { *(.dynamic) }
+  . = ALIGN(4096);
+  .rela.dyn	: {
+    *(.rela.data*)
+    *(.rela.got)
+    *(.rela.stab)
+    *(.relaset_*)
+  }
+  . = ALIGN(4096);
+  .reloc	: { *(.reloc) }
+  . = ALIGN(4096);
+  .dynsym	: { *(.dynsym) }
+  . = ALIGN(4096);
+  .dynstr	: { *(.dynstr) }
+}


Property changes on: trunk/sys/boot/efi/loader/arch/amd64/ldscript.amd64
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/boot/efi/loader/arch/amd64/reloc.c
===================================================================
--- trunk/sys/boot/efi/loader/arch/amd64/reloc.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/arch/amd64/reloc.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,111 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008-2010 Rui Paulo <rpaulo at FreeBSD.org>
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/arch/amd64/reloc.c 294981 2016-01-28 12:11:42Z smh $");
+
+#include <sys/types.h>
+#include <elf.h>
+#include <efi.h>
+#include <bootstrap.h>
+
+#ifdef __i386__
+#define ElfW_Rel	Elf32_Rel
+#define	ElfW_Dyn	Elf32_Dyn
+#define	ELFW_R_TYPE	ELF32_R_TYPE
+#elif __amd64__
+#define ElfW_Rel	Elf64_Rel
+#define	ElfW_Dyn	Elf64_Dyn
+#define	ELFW_R_TYPE	ELF64_R_TYPE
+#endif
+
+EFI_STATUS _reloc(unsigned long ImageBase, ElfW_Dyn *dynamic, EFI_HANDLE image_handle __unused,
+    EFI_SYSTEM_TABLE *system_table __unused);
+
+/*
+ * A simple relocator for IA32/AMD64 EFI binaries.
+ */
+EFI_STATUS
+_reloc(unsigned long ImageBase, ElfW_Dyn *dynamic, EFI_HANDLE image_handle __unused,
+    EFI_SYSTEM_TABLE *system_table __unused)
+{
+	unsigned long relsz, relent;
+	unsigned long *newaddr;
+	ElfW_Rel *rel;
+	ElfW_Dyn *dynp;
+
+	/*
+	 * Find the relocation address, its size and the relocation entry.
+	 */
+	relsz = 0;
+	relent = 0;
+	for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
+		switch (dynp->d_tag) {
+		case DT_REL:
+		case DT_RELA:
+			rel = (ElfW_Rel *) ((unsigned long) dynp->d_un.d_ptr +
+			    ImageBase);
+			break;
+		case DT_RELSZ:
+		case DT_RELASZ:
+			relsz = dynp->d_un.d_val;
+			break;
+		case DT_RELENT:
+		case DT_RELAENT:
+			relent = dynp->d_un.d_val;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Perform the actual relocation.
+	 * XXX: We are reusing code for the amd64 version of this, but
+	 * we must make sure the relocation types are the same.
+	 */
+	CTASSERT(R_386_NONE == R_X86_64_NONE);
+	CTASSERT(R_386_RELATIVE == R_X86_64_RELATIVE);
+	for (; relsz > 0; relsz -= relent) {
+		switch (ELFW_R_TYPE(rel->r_info)) {
+		case R_386_NONE:
+			/* No relocation needs be performed. */
+			break;
+		case R_386_RELATIVE:
+			/* Address relative to the base address. */
+			newaddr = (unsigned long *)(ImageBase + rel->r_offset);
+			*newaddr += ImageBase;
+			break;
+		default:
+			/* XXX: do we need other relocations ? */
+			break;
+		}
+		rel = (ElfW_Rel *)(void *) ((caddr_t) rel + relent);
+	}
+
+	return (EFI_SUCCESS);
+}


Property changes on: trunk/sys/boot/efi/loader/arch/amd64/reloc.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/loader/arch/amd64/start.S
===================================================================
--- trunk/sys/boot/efi/loader/arch/amd64/start.S	                        (rev 0)
+++ trunk/sys/boot/efi/loader/arch/amd64/start.S	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,77 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ *     Contributed by David Mosberger <davidm at hpl.hp.com>.
+ * Copyright (C) 2005 Intel Co.
+ *     Contributed by Fenghua Yu <fenghua.yu at intel.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hewlett-Packard Co. nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+/*
+ * crt0-efi-x86_64.S - x86_64 EFI startup code.
+ * $FreeBSD: stable/10/sys/boot/efi/loader/arch/amd64/start.S 293297 2016-01-07 02:22:45Z emaste $
+ */
+
+	.text
+	.align 4
+
+	.globl _start
+_start:
+	subq $8, %rsp
+	pushq %rcx
+	pushq %rdx
+
+0:
+	lea ImageBase(%rip), %rdi
+	lea _DYNAMIC(%rip), %rsi
+
+	popq %rcx
+	popq %rdx
+	pushq %rcx
+	pushq %rdx
+	call _reloc
+
+	popq %rdi
+	popq %rsi
+
+	call efi_main
+	addq $8, %rsp
+
+.exit:
+	ret
+
+	/*
+	 * hand-craft a dummy .reloc section so EFI knows it's a relocatable
+	 * executable:
+	 */
+
+	.data
+	.section .reloc, "a"
+	.long   0
+	.long   10
+	.word   0


Property changes on: trunk/sys/boot/efi/loader/arch/amd64/start.S
___________________________________________________________________
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/loader/autoload.c
===================================================================
--- trunk/sys/boot/efi/loader/autoload.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/autoload.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,38 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Rui Paulo <rpaulo at FreeBSD.org>
+ * 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/autoload.c 294981 2016-01-28 12:11:42Z smh $");
+
+#include "loader_efi.h"
+
+int
+efi_autoload(void)
+{
+
+	return (0);
+}


Property changes on: trunk/sys/boot/efi/loader/autoload.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/loader/bootinfo.c
===================================================================
--- trunk/sys/boot/efi/loader/bootinfo.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/bootinfo.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,396 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith at freebsd.org>
+ * Copyright (c) 2004, 2006 Marcel Moolenaar
+ * Copyright (c) 2014 The FreeBSD Foundation
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/bootinfo.c 294981 2016-01-28 12:11:42Z smh $");
+
+#include <stand.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <sys/linker.h>
+#include <sys/boot.h>
+#include <machine/cpufunc.h>
+#include <machine/elf.h>
+#include <machine/metadata.h>
+#include <machine/psl.h>
+#include <machine/specialreg.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+#include "framebuffer.h"
+#include "loader_efi.h"
+
+int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp);
+
+static const char howto_switches[] = "aCdrgDmphsv";
+static int howto_masks[] = {
+	RB_ASKNAME, RB_CDROM, RB_KDB, RB_DFLTROOT, RB_GDB, RB_MULTIPLE,
+	RB_MUTE, RB_PAUSE, RB_SERIAL, RB_SINGLE, RB_VERBOSE
+};
+
+static int
+bi_getboothowto(char *kargs)
+{
+	const char *sw;
+	char *opts;
+	char *console;
+	int howto, i;
+
+	howto = 0;
+
+	/* Get the boot options from the environment first. */
+	for (i = 0; howto_names[i].ev != NULL; i++) {
+		if (getenv(howto_names[i].ev) != NULL)
+			howto |= howto_names[i].mask;
+	}
+
+	console = getenv("console");
+	if (console != NULL) {
+		if (strcmp(console, "comconsole") == 0)
+			howto |= RB_SERIAL;
+		if (strcmp(console, "nullconsole") == 0)
+			howto |= RB_MUTE;
+	}
+
+	/* Parse kargs */
+	if (kargs == NULL)
+		return (howto);
+
+	opts = strchr(kargs, '-');
+	while (opts != NULL) {
+		while (*(++opts) != '\0') {
+			sw = strchr(howto_switches, *opts);
+			if (sw == NULL)
+				break;
+			howto |= howto_masks[sw - howto_switches];
+		}
+		opts = strchr(opts, '-');
+	}
+
+	return (howto);
+}
+
+/*
+ * Copy the environment into the load area starting at (addr).
+ * Each variable is formatted as <name>=<value>, with a single nul
+ * separating each variable, and a double nul terminating the environment.
+ */
+static vm_offset_t
+bi_copyenv(vm_offset_t start)
+{
+	struct env_var *ep;
+	vm_offset_t addr, last;
+	size_t len;
+
+	addr = last = start;
+
+	/* Traverse the environment. */
+	for (ep = environ; ep != NULL; ep = ep->ev_next) {
+		len = strlen(ep->ev_name);
+		if ((size_t)archsw.arch_copyin(ep->ev_name, addr, len) != len)
+			break;
+		addr += len;
+		if (archsw.arch_copyin("=", addr, 1) != 1)
+			break;
+		addr++;
+		if (ep->ev_value != NULL) {
+			len = strlen(ep->ev_value);
+			if ((size_t)archsw.arch_copyin(ep->ev_value, addr, len) != len)
+				break;
+			addr += len;
+		}
+		if (archsw.arch_copyin("", addr, 1) != 1)
+			break;
+		last = ++addr;
+	}
+
+	if (archsw.arch_copyin("", last++, 1) != 1)
+		last = start;
+	return(last);
+}
+
+/*
+ * Copy module-related data into the load area, where it can be
+ * used as a directory for loaded modules.
+ *
+ * Module data is presented in a self-describing format.  Each datum
+ * is preceded by a 32-bit identifier and a 32-bit size field.
+ *
+ * Currently, the following data are saved:
+ *
+ * MOD_NAME	(variable)		module name (string)
+ * MOD_TYPE	(variable)		module type (string)
+ * MOD_ARGS	(variable)		module parameters (string)
+ * MOD_ADDR	sizeof(vm_offset_t)	module load address
+ * MOD_SIZE	sizeof(size_t)		module size
+ * MOD_METADATA	(variable)		type-specific metadata
+ */
+#define	COPY32(v, a, c) {					\
+	uint32_t x = (v);					\
+	if (c)							\
+		archsw.arch_copyin(&x, a, sizeof(x));		\
+	a += sizeof(x);						\
+}
+
+#define	MOD_STR(t, a, s, c) {					\
+	COPY32(t, a, c);					\
+	COPY32(strlen(s) + 1, a, c);				\
+	if (c)							\
+		archsw.arch_copyin(s, a, strlen(s) + 1);	\
+	a += roundup(strlen(s) + 1, sizeof(u_long));		\
+}
+
+#define	MOD_NAME(a, s, c)	MOD_STR(MODINFO_NAME, a, s, c)
+#define	MOD_TYPE(a, s, c)	MOD_STR(MODINFO_TYPE, a, s, c)
+#define	MOD_ARGS(a, s, c)	MOD_STR(MODINFO_ARGS, a, s, c)
+
+#define	MOD_VAR(t, a, s, c) {					\
+	COPY32(t, a, c);					\
+	COPY32(sizeof(s), a, c);				\
+	if (c)							\
+		archsw.arch_copyin(&s, a, sizeof(s));		\
+	a += roundup(sizeof(s), sizeof(u_long));		\
+}
+
+#define	MOD_ADDR(a, s, c)	MOD_VAR(MODINFO_ADDR, a, s, c)
+#define	MOD_SIZE(a, s, c)	MOD_VAR(MODINFO_SIZE, a, s, c)
+
+#define	MOD_METADATA(a, mm, c) {				\
+	COPY32(MODINFO_METADATA | mm->md_type, a, c);		\
+	COPY32(mm->md_size, a, c);				\
+	if (c)							\
+		archsw.arch_copyin(mm->md_data, a, mm->md_size);	\
+	a += roundup(mm->md_size, sizeof(u_long));		\
+}
+
+#define	MOD_END(a, c) {						\
+	COPY32(MODINFO_END, a, c);				\
+	COPY32(0, a, c);					\
+}
+
+static vm_offset_t
+bi_copymodules(vm_offset_t addr)
+{
+	struct preloaded_file *fp;
+	struct file_metadata *md;
+	int c;
+	uint64_t v;
+
+	c = addr != 0;
+	/* Start with the first module on the list, should be the kernel. */
+	for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
+		MOD_NAME(addr, fp->f_name, c); /* This must come first. */
+		MOD_TYPE(addr, fp->f_type, c);
+		if (fp->f_args)
+			MOD_ARGS(addr, fp->f_args, c);
+		v = fp->f_addr;
+		MOD_ADDR(addr, v, c);
+		v = fp->f_size;
+		MOD_SIZE(addr, v, c);
+		for (md = fp->f_metadata; md != NULL; md = md->md_next)
+			if (!(md->md_type & MODINFOMD_NOCOPY))
+				MOD_METADATA(addr, md, c);
+	}
+	MOD_END(addr, c);
+	return(addr);
+}
+
+static int
+bi_load_efi_data(struct preloaded_file *kfp)
+{
+	EFI_MEMORY_DESCRIPTOR *mm;
+	EFI_PHYSICAL_ADDRESS addr;
+	EFI_STATUS status;
+	size_t efisz;
+	UINTN efi_mapkey;
+	UINTN mmsz, pages, retry, sz;
+	UINT32 mmver;
+	struct efi_map_header *efihdr;
+	struct efi_fb efifb;
+
+	if (efi_find_framebuffer(&efifb) == 0) {
+		printf("EFI framebuffer information:\n");
+		printf("addr, size     0x%lx, 0x%lx\n", efifb.fb_addr,
+		    efifb.fb_size);
+		printf("dimensions     %d x %d\n", efifb.fb_width,
+		    efifb.fb_height);
+		printf("stride         %d\n", efifb.fb_stride);
+		printf("masks          0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+		    efifb.fb_mask_red, efifb.fb_mask_green, efifb.fb_mask_blue,
+		    efifb.fb_mask_reserved);
+
+		file_addmetadata(kfp, MODINFOMD_EFI_FB, sizeof(efifb), &efifb);
+	}
+
+	efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
+
+	/*
+	 * It is possible that the first call to ExitBootServices may change
+	 * the map key. Fetch a new map key and retry ExitBootServices in that
+	 * case.
+	 */
+	for (retry = 2; retry > 0; retry--) {
+		/*
+		 * Allocate enough pages to hold the bootinfo block and the
+		 * memory map EFI will return to us. The memory map has an
+		 * unknown size, so we have to determine that first. Note that
+		 * the AllocatePages call can itself modify the memory map, so
+		 * we have to take that into account as well. The changes to
+		 * the memory map are caused by splitting a range of free
+		 * memory into two (AFAICT), so that one is marked as being
+		 * loader data.
+		 */
+		sz = 0;
+		BS->GetMemoryMap(&sz, NULL, &efi_mapkey, &mmsz, &mmver);
+		sz += mmsz;
+		sz = (sz + 0xf) & ~0xf;
+		pages = EFI_SIZE_TO_PAGES(sz + efisz);
+		status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+		     pages, &addr);
+		if (EFI_ERROR(status)) {
+			printf("%s: AllocatePages error %lu\n", __func__,
+			    EFI_ERROR_CODE(status));
+			return (ENOMEM);
+		}
+
+		/*
+		 * Read the memory map and stash it after bootinfo. Align the
+		 * memory map on a 16-byte boundary (the bootinfo block is page
+		 * aligned).
+		 */
+		efihdr = (struct efi_map_header *)addr;
+		mm = (void *)((uint8_t *)efihdr + efisz);
+		sz = (EFI_PAGE_SIZE * pages) - efisz;
+
+		status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver);
+		if (EFI_ERROR(status)) {
+			printf("%s: GetMemoryMap error %lu\n", __func__,
+			    EFI_ERROR_CODE(status));
+			return (EINVAL);
+		}
+		status = BS->ExitBootServices(IH, efi_mapkey);
+		if (EFI_ERROR(status) == 0) {
+			efihdr->memory_size = sz;
+			efihdr->descriptor_size = mmsz;
+			efihdr->descriptor_version = mmver;
+			file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz,
+			    efihdr);
+			return (0);
+		}
+		BS->FreePages(addr, pages);
+	}
+	printf("ExitBootServices error %lu\n", EFI_ERROR_CODE(status));
+	return (EINVAL);
+}
+
+/*
+ * Load the information expected by an amd64 kernel.
+ *
+ * - The 'boothowto' argument is constructed.
+ * - The 'bootdev' argument is constructed.
+ * - The 'bootinfo' struct is constructed, and copied into the kernel space.
+ * - The kernel environment is copied into kernel space.
+ * - Module metadata are formatted and placed in kernel space.
+ */
+int
+bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
+{
+	struct preloaded_file *xp, *kfp;
+	struct devdesc *rootdev;
+	struct file_metadata *md;
+	vm_offset_t addr;
+	uint64_t kernend;
+	uint64_t envp;
+	vm_offset_t size;
+	char *rootdevname;
+	int howto;
+
+	howto = bi_getboothowto(args);
+
+	/*
+	 * Allow the environment variable 'rootdev' to override the supplied
+	 * device. This should perhaps go to MI code and/or have $rootdev
+	 * tested/set by MI code before launching the kernel.
+	 */
+	rootdevname = getenv("rootdev");
+	archsw.arch_getdev((void**)(&rootdev), rootdevname, NULL);
+	if (rootdev == NULL) {
+		printf("Can't determine root device.\n");
+		return(EINVAL);
+	}
+
+	/* Try reading the /etc/fstab file to select the root device */
+	getrootmount(efi_fmtdev((void *)rootdev));
+
+	addr = 0;
+	for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+		if (addr < (xp->f_addr + xp->f_size))
+			addr = xp->f_addr + xp->f_size;
+	}
+
+	/* Pad to a page boundary. */
+	addr = roundup(addr, PAGE_SIZE);
+
+	/* Copy our environment. */
+	envp = addr;
+	addr = bi_copyenv(addr);
+
+	/* Pad to a page boundary. */
+	addr = roundup(addr, PAGE_SIZE);
+
+	kfp = file_findfile(NULL, "elf kernel");
+	if (kfp == NULL)
+		kfp = file_findfile(NULL, "elf64 kernel");
+	if (kfp == NULL)
+		panic("can't find kernel file");
+	kernend = 0;	/* fill it in later */
+	file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
+	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
+	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
+
+	bi_load_efi_data(kfp);
+
+	/* Figure out the size and location of the metadata. */
+	*modulep = addr;
+	size = bi_copymodules(0);
+	kernend = roundup(addr + size, PAGE_SIZE);
+	*kernendp = kernend;
+
+	/* patch MODINFOMD_KERNEND */
+	md = file_findmetadata(kfp, MODINFOMD_KERNEND);
+	bcopy(&kernend, md->md_data, sizeof kernend);
+
+	/* Copy module list and metadata. */
+	(void)bi_copymodules(addr);
+
+	return (0);
+}


Property changes on: trunk/sys/boot/efi/loader/bootinfo.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/loader/conf.c
===================================================================
--- trunk/sys/boot/efi/loader/conf.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/conf.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,75 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Marcel Moolenaar
+ * 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/conf.c 294999 2016-01-28 17:24:40Z smh $");
+
+#include <stand.h>
+#include <bootstrap.h>
+#include <efi.h>
+#include <efilib.h>
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
+
+struct devsw *devsw[] = {
+	&efipart_dev,
+	&efinet_dev,
+#ifdef EFI_ZFS_BOOT
+	&zfs_dev,
+#endif
+	NULL
+};
+
+struct fs_ops *file_system[] = {
+#ifdef EFI_ZFS_BOOT
+	&zfs_fsops,
+#endif
+	&dosfs_fsops,
+	&ufs_fsops,
+	&cd9660_fsops,
+	&nfs_fsops,
+	&gzipfs_fsops,
+	&bzipfs_fsops,
+	NULL
+};
+
+struct netif_driver *netif_drivers[] = {
+	&efinetif,
+	NULL
+};
+
+extern struct console efi_console;
+extern struct console comconsole;
+extern struct console nullconsole;
+
+struct console *consoles[] = {
+	&efi_console,
+	&comconsole,
+	&nullconsole,
+	NULL
+};


Property changes on: trunk/sys/boot/efi/loader/conf.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/loader/copy.c
===================================================================
--- trunk/sys/boot/efi/loader/copy.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/copy.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,270 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Benno Rice under sponsorship from
+ * the FreeBSD Foundation.
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/copy.c 316273 2017-03-30 12:51:44Z dexuan $");
+
+#include <sys/param.h>
+
+#include <stand.h>
+#include <bootstrap.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "loader_efi.h"
+
+#if defined(__i386__) || defined(__amd64__)
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+
+/*
+ * The code is excerpted from sys/x86/x86/identcpu.c: identify_cpu(),
+ * identify_hypervisor(), and dev/hyperv/vmbus/hyperv.c: hyperv_identify().
+ */
+#define CPUID_LEAF_HV_MAXLEAF		0x40000000
+#define CPUID_LEAF_HV_INTERFACE		0x40000001
+#define CPUID_LEAF_HV_FEATURES		0x40000003
+#define CPUID_LEAF_HV_LIMITS		0x40000005
+#define CPUID_HV_IFACE_HYPERV		0x31237648	/* HV#1 */
+#define CPUID_HV_MSR_TIME_REFCNT	0x0002	/* MSR_HV_TIME_REF_COUNT */
+#define CPUID_HV_MSR_HYPERCALL		0x0020
+
+static int
+running_on_hyperv(void)
+{
+	char hv_vendor[16];
+	uint32_t regs[4];
+
+	do_cpuid(1, regs);
+	if ((regs[2] & CPUID2_HV) == 0)
+		return (0);
+
+	do_cpuid(CPUID_LEAF_HV_MAXLEAF, regs);
+	if (regs[0] < CPUID_LEAF_HV_LIMITS)
+		return (0);
+
+	((uint32_t *)&hv_vendor)[0] = regs[1];
+	((uint32_t *)&hv_vendor)[1] = regs[2];
+	((uint32_t *)&hv_vendor)[2] = regs[3];
+	hv_vendor[12] = '\0';
+	if (strcmp(hv_vendor, "Microsoft Hv") != 0)
+		return (0);
+
+	do_cpuid(CPUID_LEAF_HV_INTERFACE, regs);
+	if (regs[0] != CPUID_HV_IFACE_HYPERV)
+		return (0);
+
+	do_cpuid(CPUID_LEAF_HV_FEATURES, regs);
+	if ((regs[0] & CPUID_HV_MSR_HYPERCALL) == 0)
+		return (0);
+	if ((regs[0] & CPUID_HV_MSR_TIME_REFCNT) == 0)
+		return (0);
+
+	return (1);
+}
+
+#define KERNEL_PHYSICAL_BASE (2*1024*1024)
+
+static void
+efi_verify_staging_size(unsigned long *nr_pages)
+{
+	UINTN sz;
+	EFI_MEMORY_DESCRIPTOR *map, *p;
+	EFI_PHYSICAL_ADDRESS start, end;
+	UINTN key, dsz;
+	UINT32 dver;
+	EFI_STATUS status;
+	int i, ndesc;
+	unsigned long available_pages = 0;
+
+	sz = 0;
+	status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
+	if (status != EFI_BUFFER_TOO_SMALL) {
+		printf("Can't determine memory map size\n");
+		return;
+	}
+
+	map = malloc(sz);
+	status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
+	if (EFI_ERROR(status)) {
+		printf("Can't read memory map\n");
+		goto out;
+	}
+
+	ndesc = sz / dsz;
+	for (i = 0, p = map; i < ndesc;
+	     i++, p = NextMemoryDescriptor(p, dsz)) {
+		start = p->PhysicalStart;
+		end = start + p->NumberOfPages * EFI_PAGE_SIZE;
+
+		if (KERNEL_PHYSICAL_BASE < start ||
+		    KERNEL_PHYSICAL_BASE >= end)
+			continue;
+
+		available_pages = p->NumberOfPages -
+			((KERNEL_PHYSICAL_BASE - start) >> EFI_PAGE_SHIFT);
+		break;
+	}
+
+	if (available_pages == 0) {
+		printf("Can't find valid memory map for staging area!\n");
+		goto out;
+	}
+
+	i++;
+	p = NextMemoryDescriptor(p, dsz);
+
+	for ( ; i < ndesc;
+	     i++, p = NextMemoryDescriptor(p, dsz)) {
+		if (p->Type != EfiConventionalMemory &&
+		    p->Type != EfiLoaderData)
+			break;
+
+		if (p->PhysicalStart != end)
+			break;
+
+		end = p->PhysicalStart + p->NumberOfPages * EFI_PAGE_SIZE;
+
+		available_pages += p->NumberOfPages;
+	}
+
+	if (*nr_pages > available_pages) {
+		printf("Staging area's size is reduced: %ld -> %ld!\n",
+		    *nr_pages, available_pages);
+		*nr_pages = available_pages;
+	}
+out:
+	free(map);
+}
+#endif /* __i386__ || __amd64__ */
+
+#ifndef EFI_STAGING_SIZE
+#define	EFI_STAGING_SIZE	48
+#endif
+
+EFI_PHYSICAL_ADDRESS	staging, staging_end;
+int			stage_offset_set = 0;
+ssize_t			stage_offset;
+
+int
+efi_copy_init(void)
+{
+	EFI_STATUS	status;
+
+	unsigned long nr_pages;
+
+	nr_pages = EFI_SIZE_TO_PAGES((EFI_STAGING_SIZE) * 1024 * 1024);
+
+#if defined(__i386__) || defined(__amd64__)
+	/*
+	 * We'll decrease nr_pages, if it's too big. Currently we only
+	 * apply this to FreeBSD VM running on Hyper-V. Why? Please see
+	 * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=211746#c28
+	 */
+	if (running_on_hyperv())
+		efi_verify_staging_size(&nr_pages);
+
+	/*
+	 * The staging area must reside in the the first 1GB physical
+	 * memory: see elf64_exec() in
+	 * boot/efi/loader/arch/amd64/elf64_freebsd.c.
+	 */
+	staging = 1024*1024*1024;
+	status = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+	    nr_pages, &staging);
+#else
+	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+	    nr_pages, &staging);
+#endif
+	if (EFI_ERROR(status)) {
+		printf("failed to allocate staging area: %lu\n",
+		    EFI_ERROR_CODE(status));
+		return (status);
+	}
+	staging_end = staging + nr_pages * EFI_PAGE_SIZE;
+
+	return (0);
+}
+
+ssize_t
+efi_copyin(const void *src, vm_offset_t dest, const size_t len)
+{
+
+	if (!stage_offset_set) {
+		stage_offset = (vm_offset_t)staging - dest;
+		stage_offset_set = 1;
+	}
+
+	/* XXX: Callers do not check for failure. */
+	if (dest + stage_offset + len > staging_end) {
+		errno = ENOMEM;
+		return (-1);
+	}
+	bcopy(src, (void *)(dest + stage_offset), len);
+	return (len);
+}
+
+ssize_t
+efi_copyout(const vm_offset_t src, void *dest, const size_t len)
+{
+
+	/* XXX: Callers do not check for failure. */
+	if (src + stage_offset + len > staging_end) {
+		errno = ENOMEM;
+		return (-1);
+	}
+	bcopy((void *)(src + stage_offset), dest, len);
+	return (len);
+}
+
+
+ssize_t
+efi_readin(const int fd, vm_offset_t dest, const size_t len)
+{
+
+	if (dest + stage_offset + len > staging_end) {
+		errno = ENOMEM;
+		return (-1);
+	}
+	return (read(fd, (void *)(dest + stage_offset), len));
+}
+
+void
+efi_copy_finish(void)
+{
+	uint64_t	*src, *dst, *last;
+
+	src = (uint64_t *)staging;
+	dst = (uint64_t *)(staging - stage_offset);
+	last = (uint64_t *)staging_end;
+
+	while (src < last)
+		*dst++ = *src++;
+}


Property changes on: trunk/sys/boot/efi/loader/copy.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/loader/devicename.c
===================================================================
--- trunk/sys/boot/efi/loader/devicename.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/devicename.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,199 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith at freebsd.org>
+ * Copyright (c) 2006 Marcel Moolenaar
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/devicename.c 297555 2016-04-04 12:21:04Z marius $");
+
+#include <stand.h>
+#include <string.h>
+#include <sys/disklabel.h>
+#include <sys/param.h>
+#include <bootstrap.h>
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "loader_efi.h"
+
+static int efi_parsedev(struct devdesc **, const char *, const char **);
+
+/*
+ * Point (dev) at an allocated device specifier for the device matching the
+ * path in (devspec). If it contains an explicit device specification,
+ * use that.  If not, use the default device.
+ */
+int
+efi_getdev(void **vdev, const char *devspec, const char **path)
+{
+	struct devdesc **dev = (struct devdesc **)vdev;
+	int rv;
+
+	/*
+	 * If it looks like this is just a path and no device, then
+	 * use the current device instead.
+	 */
+	if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) {
+		rv = efi_parsedev(dev, getenv("currdev"), NULL);
+		if (rv == 0 && path != NULL)
+			*path = devspec;
+		return (rv);
+	}
+
+	/* Parse the device name off the beginning of the devspec. */
+	return (efi_parsedev(dev, devspec, path));
+}
+
+/*
+ * Point (dev) at an allocated device specifier matching the string version
+ * at the beginning of (devspec).  Return a pointer to the remaining
+ * text in (path).
+ *
+ * In all cases, the beginning of (devspec) is compared to the names
+ * of known devices in the device switch, and then any following text
+ * is parsed according to the rules applied to the device type.
+ *
+ * For disk-type devices, the syntax is:
+ *
+ * fs<unit>:
+ */
+static int
+efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
+{
+	struct devdesc *idev;
+	struct devsw *dv;
+	char *cp;
+	const char *np;
+	int i;
+
+	/* minimum length check */
+	if (strlen(devspec) < 2)
+		return (EINVAL);
+
+	/* look for a device that matches */
+	for (i = 0; devsw[i] != NULL; i++) {
+		dv = devsw[i];
+		if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name)))
+			break;
+	}
+	if (devsw[i] == NULL)
+		return (ENOENT);
+
+	np = devspec + strlen(dv->dv_name);
+
+#ifdef EFI_ZFS_BOOT
+	if (dv->dv_type == DEVT_ZFS) {
+		int err;
+
+		idev = malloc(sizeof(struct zfs_devdesc));
+		if (idev == NULL)
+			return (ENOMEM);
+
+		err = zfs_parsedev((struct zfs_devdesc*)idev, np, path);
+		if (err != 0) {
+			free(idev);
+			return (err);
+		}
+		*dev = idev;
+		cp = strchr(np + 1, ':');
+	} else
+#endif
+	{
+		idev = malloc(sizeof(struct devdesc));
+		if (idev == NULL)
+			return (ENOMEM);
+
+		idev->d_dev = dv;
+		idev->d_type = dv->dv_type;
+		idev->d_unit = -1;
+		if (*np != '\0' && *np != ':') {
+			idev->d_unit = strtol(np, &cp, 0);
+			if (cp == np) {
+				idev->d_unit = -1;
+				free(idev);
+				return (EUNIT);
+			}
+		}
+	}
+
+	if (*cp != '\0' && *cp != ':') {
+		free(idev);
+		return (EINVAL);
+	}
+
+	if (path != NULL)
+		*path = (*cp == 0) ? cp : cp + 1;
+	if (dev != NULL)
+		*dev = idev;
+	else
+		free(idev);
+	return (0);
+}
+
+char *
+efi_fmtdev(void *vdev)
+{
+	struct devdesc *dev = (struct devdesc *)vdev;
+	static char buf[SPECNAMELEN + 1];
+
+	switch(dev->d_type) {
+#ifdef EFI_ZFS_BOOT
+	case DEVT_ZFS:
+		return (zfs_fmtdev(dev));
+#endif
+	case DEVT_NONE:
+		strcpy(buf, "(no device)");
+		break;
+
+	default:
+		sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
+		break;
+	}
+
+	return (buf);
+}
+
+/*
+ * Set currdev to suit the value being supplied in (value)
+ */
+int
+efi_setcurrdev(struct env_var *ev, int flags, const void *value)
+{
+	struct devdesc *ncurr;
+	int rv;
+
+	rv = efi_parsedev(&ncurr, value, NULL);
+	if (rv != 0)
+		return (rv);
+
+	free(ncurr);
+	env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+	return (0);
+}


Property changes on: trunk/sys/boot/efi/loader/devicename.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/loader/loader_efi.h
===================================================================
--- trunk/sys/boot/efi/loader/loader_efi.h	                        (rev 0)
+++ trunk/sys/boot/efi/loader/loader_efi.h	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Benno Rice under sponsorship from
+ * the FreeBSD Foundation.
+ * 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/loader/loader_efi.h 294981 2016-01-28 12:11:42Z smh $
+ */
+
+#ifndef	_LOADER_EFI_COPY_H_
+#define	_LOADER_EFI_COPY_H_
+
+#include <stand.h>
+
+int	efi_autoload(void);
+
+int	efi_getdev(void **vdev, const char *devspec, const char **path);
+char	*efi_fmtdev(void *vdev);
+int	efi_setcurrdev(struct env_var *ev, int flags, const void *value);
+
+int	efi_copy_init(void);
+
+ssize_t	efi_copyin(const void *src, vm_offset_t dest, const size_t len);
+ssize_t	efi_copyout(const vm_offset_t src, void *dest, const size_t len);
+ssize_t	efi_readin(const int fd, vm_offset_t dest, const size_t len);
+void * efi_translate(vm_offset_t ptr);
+
+void	efi_copy_finish(void);
+
+#endif	/* _LOADER_EFI_COPY_H_ */


Property changes on: trunk/sys/boot/efi/loader/loader_efi.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/loader/main.c
===================================================================
--- trunk/sys/boot/efi/loader/main.c	                        (rev 0)
+++ trunk/sys/boot/efi/loader/main.c	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,732 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008-2010 Rui Paulo
+ * Copyright (c) 2006 Marcel Moolenaar
+ * 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/main.c 295551 2016-02-11 23:43:27Z imp $");
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <sys/boot.h>
+#include <stand.h>
+#include <string.h>
+#include <setjmp.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include <bootstrap.h>
+#include <smbios.h>
+
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
+
+#include "loader_efi.h"
+
+extern char bootprog_name[];
+extern char bootprog_rev[];
+extern char bootprog_date[];
+extern char bootprog_maker[];
+
+struct arch_switch archsw;	/* MI/MD interface boundary */
+
+EFI_GUID acpi = ACPI_TABLE_GUID;
+EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
+EFI_GUID devid = DEVICE_PATH_PROTOCOL;
+EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
+EFI_GUID mps = MPS_TABLE_GUID;
+EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
+EFI_GUID smbios = SMBIOS_TABLE_GUID;
+EFI_GUID dxe = DXE_SERVICES_TABLE_GUID;
+EFI_GUID hoblist = HOB_LIST_TABLE_GUID;
+EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
+EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
+EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
+
+#ifdef EFI_ZFS_BOOT
+static void efi_zfs_probe(void);
+#endif
+
+/*
+ * Need this because EFI uses UTF-16 unicode string constants, but we
+ * use UTF-8. We can't use printf due to the possiblity of \0 and we
+ * don't support support wide characters either.
+ */
+static void
+print_str16(const CHAR16 *str)
+{
+	int i;
+
+	for (i = 0; str[i]; i++)
+		printf("%c", (char)str[i]);
+}
+
+static void
+cp16to8(const CHAR16 *src, char *dst, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len && src[i]; i++)
+		dst[i] = (char)src[i];
+}
+
+static int
+has_keyboard(void)
+{
+	EFI_STATUS status;
+	EFI_DEVICE_PATH *path;
+	EFI_HANDLE *hin, *hin_end, *walker;
+	UINTN sz;
+	int retval = 0;
+	
+	/*
+	 * Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and
+	 * do the typical dance to get the right sized buffer.
+	 */
+	sz = 0;
+	hin = NULL;
+	status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz, 0);
+	if (status == EFI_BUFFER_TOO_SMALL) {
+		hin = (EFI_HANDLE *)malloc(sz);
+		status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz,
+		    hin);
+		if (EFI_ERROR(status))
+			free(hin);
+	}
+	if (EFI_ERROR(status))
+		return retval;
+
+	/*
+	 * Look at each of the handles. If it supports the device path protocol,
+	 * use it to get the device path for this handle. Then see if that
+	 * device path matches either the USB device path for keyboards or the
+	 * legacy device path for keyboards.
+	 */
+	hin_end = &hin[sz / sizeof(*hin)];
+	for (walker = hin; walker < hin_end; walker++) {
+		status = BS->HandleProtocol(*walker, &devid, (VOID **)&path);
+		if (EFI_ERROR(status))
+			continue;
+
+		while (!IsDevicePathEnd(path)) {
+			/*
+			 * Check for the ACPI keyboard node. All PNP3xx nodes
+			 * are keyboards of different flavors. Note: It is
+			 * unclear of there's always a keyboard node when
+			 * there's a keyboard controller, or if there's only one
+			 * when a keyboard is detected at boot.
+			 */
+			if (DevicePathType(path) == ACPI_DEVICE_PATH &&
+			    (DevicePathSubType(path) == ACPI_DP ||
+				DevicePathSubType(path) == ACPI_EXTENDED_DP)) {
+				ACPI_HID_DEVICE_PATH  *acpi;
+
+				acpi = (ACPI_HID_DEVICE_PATH *)(void *)path;
+				if ((EISA_ID_TO_NUM(acpi->HID) & 0xff00) == 0x300 &&
+				    (acpi->HID & 0xffff) == PNP_EISA_ID_CONST) {
+					retval = 1;
+					goto out;
+				}
+			/*
+			 * Check for USB keyboard node, if present. Unlike a
+			 * PS/2 keyboard, these definitely only appear when
+			 * connected to the system.
+			 */
+			} else if (DevicePathType(path) == MESSAGING_DEVICE_PATH &&
+			    DevicePathSubType(path) == MSG_USB_CLASS_DP) {
+				USB_CLASS_DEVICE_PATH *usb;
+			       
+				usb = (USB_CLASS_DEVICE_PATH *)(void *)path;
+				if (usb->DeviceClass == 3 && /* HID */
+				    usb->DeviceSubClass == 1 && /* Boot devices */
+				    usb->DeviceProtocol == 1) { /* Boot keyboards */
+					retval = 1;
+					goto out;
+				}
+			}
+			path = NextDevicePathNode(path);
+		}
+	}
+out:
+	free(hin);
+	return retval;
+}
+
+EFI_STATUS
+main(int argc, CHAR16 *argv[])
+{
+	char var[128];
+	EFI_LOADED_IMAGE *img;
+	EFI_GUID *guid;
+	int i, j, vargood, unit, howto;
+	struct devsw *dev;
+	uint64_t pool_guid;
+	UINTN k;
+	int has_kbd;
+
+	archsw.arch_autoload = efi_autoload;
+	archsw.arch_getdev = efi_getdev;
+	archsw.arch_copyin = efi_copyin;
+	archsw.arch_copyout = efi_copyout;
+	archsw.arch_readin = efi_readin;
+#ifdef EFI_ZFS_BOOT
+	/* Note this needs to be set before ZFS init. */
+	archsw.arch_zfs_probe = efi_zfs_probe;
+#endif
+
+	has_kbd = has_keyboard();
+
+	/*
+	 * XXX Chicken-and-egg problem; we want to have console output
+	 * early, but some console attributes may depend on reading from
+	 * eg. the boot device, which we can't do yet.  We can use
+	 * printf() etc. once this is done.
+	 */
+	cons_probe();
+
+	/*
+	 * Parse the args to set the console settings, etc
+	 * boot1.efi passes these in, if it can read /boot.config or /boot/config
+	 * or iPXE may be setup to pass these in.
+	 *
+	 * Loop through the args, and for each one that contains an '=' that is
+	 * not the first character, add it to the environment.  This allows
+	 * loader and kernel env vars to be passed on the command line.  Convert
+	 * args from UCS-2 to ASCII (16 to 8 bit) as they are copied.
+	 */
+	howto = 0;
+	for (i = 1; i < argc; i++) {
+		if (argv[i][0] == '-') {
+			for (j = 1; argv[i][j] != 0; j++) {
+				int ch;
+
+				ch = argv[i][j];
+				switch (ch) {
+				case 'a':
+					howto |= RB_ASKNAME;
+					break;
+				case 'd':
+					howto |= RB_KDB;
+					break;
+				case 'D':
+					howto |= RB_MULTIPLE;
+					break;
+				case 'h':
+					howto |= RB_SERIAL;
+					break;
+				case 'm':
+					howto |= RB_MUTE;
+					break;
+				case 'p':
+					howto |= RB_PAUSE;
+					break;
+				case 'P':
+					if (!has_kbd)
+						howto |= RB_SERIAL | RB_MULTIPLE;
+					break;
+				case 'r':
+					howto |= RB_DFLTROOT;
+					break;
+				case 's':
+					howto |= RB_SINGLE;
+					break;
+				case 'S':
+					if (argv[i][j + 1] == 0) {
+						if (i + 1 == argc) {
+							setenv("comconsole_speed", "115200", 1);
+						} else {
+							cp16to8(&argv[i + 1][0], var,
+							    sizeof(var));
+							setenv("comconsole_speedspeed", var, 1);
+						}
+						i++;
+						break;
+					} else {
+						cp16to8(&argv[i][j + 1], var,
+						    sizeof(var));
+						setenv("comconsole_speed", var, 1);
+						break;
+					}
+				case 'v':
+					howto |= RB_VERBOSE;
+					break;
+				}
+			}
+		} else {
+			vargood = 0;
+			for (j = 0; argv[i][j] != 0; j++) {
+				if (j == sizeof(var)) {
+					vargood = 0;
+					break;
+				}
+				if (j > 0 && argv[i][j] == '=')
+					vargood = 1;
+				var[j] = (char)argv[i][j];
+			}
+			if (vargood) {
+				var[j] = 0;
+				putenv(var);
+			}
+		}
+	}
+	for (i = 0; howto_names[i].ev != NULL; i++)
+		if (howto & howto_names[i].mask)
+			setenv(howto_names[i].ev, "YES", 1);
+	if (howto & RB_MULTIPLE) {
+		if (howto & RB_SERIAL)
+			setenv("console", "comconsole efi" , 1);
+		else
+			setenv("console", "efi comconsole" , 1);
+	} else if (howto & RB_SERIAL) {
+		setenv("console", "comconsole" , 1);
+	}
+
+	if (efi_copy_init()) {
+		printf("failed to allocate staging area\n");
+		return (EFI_BUFFER_TOO_SMALL);
+	}
+
+	/*
+	 * March through the device switch probing for things.
+	 */
+	for (i = 0; devsw[i] != NULL; i++)
+		if (devsw[i]->dv_init != NULL)
+			(devsw[i]->dv_init)();
+
+	/* Get our loaded image protocol interface structure. */
+	BS->HandleProtocol(IH, &imgid, (VOID**)&img);
+
+	printf("Command line arguments:");
+	for (i = 0; i < argc; i++) {
+		printf(" ");
+		print_str16(argv[i]);
+	}
+	printf("\n");
+
+	printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
+	printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
+	    ST->Hdr.Revision & 0xffff);
+	printf("EFI Firmware: ");
+	/* printf doesn't understand EFI Unicode */
+	ST->ConOut->OutputString(ST->ConOut, ST->FirmwareVendor);
+	printf(" (rev %d.%02d)\n", ST->FirmwareRevision >> 16,
+	    ST->FirmwareRevision & 0xffff);
+
+	printf("\n");
+	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
+	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
+
+	/*
+	 * Disable the watchdog timer. By default the boot manager sets
+	 * the timer to 5 minutes before invoking a boot option. If we
+	 * want to return to the boot manager, we have to disable the
+	 * watchdog timer and since we're an interactive program, we don't
+	 * want to wait until the user types "quit". The timer may have
+	 * fired by then. We don't care if this fails. It does not prevent
+	 * normal functioning in any way...
+	 */
+	BS->SetWatchdogTimer(0, 0, 0, NULL);
+
+	if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid) != 0)
+		return (EFI_NOT_FOUND);
+
+	switch (dev->dv_type) {
+#ifdef EFI_ZFS_BOOT
+	case DEVT_ZFS: {
+		struct zfs_devdesc currdev;
+
+		currdev.d_dev = dev;
+		currdev.d_unit = unit;
+		currdev.d_type = currdev.d_dev->dv_type;
+		currdev.d_opendata = NULL;
+		currdev.pool_guid = pool_guid;
+		currdev.root_guid = 0;
+		env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
+			   efi_setcurrdev, env_nounset);
+		env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
+			   env_nounset);
+		init_zfs_bootenv(zfs_fmtdev(&currdev));
+		break;
+	}
+#endif
+	default: {
+		struct devdesc currdev;
+
+		currdev.d_dev = dev;
+		currdev.d_unit = unit;
+		currdev.d_opendata = NULL;
+		currdev.d_type = currdev.d_dev->dv_type;
+		env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
+			   efi_setcurrdev, env_nounset);
+		env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
+			   env_nounset);
+		break;
+	}
+	}
+
+	setenv("LINES", "24", 1);	/* optional */
+
+	for (k = 0; k < ST->NumberOfTableEntries; k++) {
+		guid = &ST->ConfigurationTable[k].VendorGuid;
+		if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
+			smbios_detect(ST->ConfigurationTable[k].VendorTable);
+			break;
+		}
+	}
+
+	interact();			/* doesn't return */
+
+	return (EFI_SUCCESS);		/* keep compiler happy */
+}
+
+COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
+
+static int
+command_reboot(int argc, char *argv[])
+{
+	int i;
+
+	for (i = 0; devsw[i] != NULL; ++i)
+		if (devsw[i]->dv_cleanup != NULL)
+			(devsw[i]->dv_cleanup)();
+
+	RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 23,
+	    (CHAR16 *)"Reboot from the loader");
+
+	/* NOTREACHED */
+	return (CMD_ERROR);
+}
+
+COMMAND_SET(quit, "quit", "exit the loader", command_quit);
+
+static int
+command_quit(int argc, char *argv[])
+{
+	exit(0);
+	return (CMD_OK);
+}
+
+COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
+
+static int
+command_memmap(int argc, char *argv[])
+{
+	UINTN sz;
+	EFI_MEMORY_DESCRIPTOR *map, *p;
+	UINTN key, dsz;
+	UINT32 dver;
+	EFI_STATUS status;
+	int i, ndesc;
+	static char *types[] = {
+	    "Reserved",
+	    "LoaderCode",
+	    "LoaderData",
+	    "BootServicesCode",
+	    "BootServicesData",
+	    "RuntimeServicesCode",
+	    "RuntimeServicesData",
+	    "ConventionalMemory",
+	    "UnusableMemory",
+	    "ACPIReclaimMemory",
+	    "ACPIMemoryNVS",
+	    "MemoryMappedIO",
+	    "MemoryMappedIOPortSpace",
+	    "PalCode"
+	};
+
+	sz = 0;
+	status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
+	if (status != EFI_BUFFER_TOO_SMALL) {
+		printf("Can't determine memory map size\n");
+		return (CMD_ERROR);
+	}
+	map = malloc(sz);
+	status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
+	if (EFI_ERROR(status)) {
+		printf("Can't read memory map\n");
+		return (CMD_ERROR);
+	}
+
+	ndesc = sz / dsz;
+	printf("%23s %12s %12s %8s %4s\n",
+	    "Type", "Physical", "Virtual", "#Pages", "Attr");
+
+	for (i = 0, p = map; i < ndesc;
+	     i++, p = NextMemoryDescriptor(p, dsz)) {
+		printf("%23s %012jx %012jx %08jx ", types[p->Type],
+		   (uintmax_t)p->PhysicalStart, (uintmax_t)p->VirtualStart,
+		   (uintmax_t)p->NumberOfPages);
+		if (p->Attribute & EFI_MEMORY_UC)
+			printf("UC ");
+		if (p->Attribute & EFI_MEMORY_WC)
+			printf("WC ");
+		if (p->Attribute & EFI_MEMORY_WT)
+			printf("WT ");
+		if (p->Attribute & EFI_MEMORY_WB)
+			printf("WB ");
+		if (p->Attribute & EFI_MEMORY_UCE)
+			printf("UCE ");
+		if (p->Attribute & EFI_MEMORY_WP)
+			printf("WP ");
+		if (p->Attribute & EFI_MEMORY_RP)
+			printf("RP ");
+		if (p->Attribute & EFI_MEMORY_XP)
+			printf("XP ");
+		printf("\n");
+	}
+
+	return (CMD_OK);
+}
+
+COMMAND_SET(configuration, "configuration", "print configuration tables",
+    command_configuration);
+
+static const char *
+guid_to_string(EFI_GUID *guid)
+{
+	static char buf[40];
+
+	sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+	    guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
+	    guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
+	    guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+	return (buf);
+}
+
+static int
+command_configuration(int argc, char *argv[])
+{
+	UINTN i;
+
+	printf("NumberOfTableEntries=%lu\n",
+		(unsigned long)ST->NumberOfTableEntries);
+	for (i = 0; i < ST->NumberOfTableEntries; i++) {
+		EFI_GUID *guid;
+
+		printf("  ");
+		guid = &ST->ConfigurationTable[i].VendorGuid;
+		if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
+			printf("MPS Table");
+		else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
+			printf("ACPI Table");
+		else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
+			printf("ACPI 2.0 Table");
+		else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
+			printf("SMBIOS Table");
+		else if (!memcmp(guid, &dxe, sizeof(EFI_GUID)))
+			printf("DXE Table");
+		else if (!memcmp(guid, &hoblist, sizeof(EFI_GUID)))
+			printf("HOB List Table");
+		else if (!memcmp(guid, &memtype, sizeof(EFI_GUID)))
+			printf("Memory Type Information Table");
+		else if (!memcmp(guid, &debugimg, sizeof(EFI_GUID)))
+			printf("Debug Image Info Table");
+		else
+			printf("Unknown Table (%s)", guid_to_string(guid));
+		printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
+	}
+
+	return (CMD_OK);
+}
+
+
+COMMAND_SET(mode, "mode", "change or display text modes", command_mode);
+
+static int
+command_mode(int argc, char *argv[])
+{
+	UINTN cols, rows;
+	unsigned int mode;
+	int i;
+	char *cp;
+	char rowenv[8];
+	EFI_STATUS status;
+	SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
+	extern void HO(void);
+
+	conout = ST->ConOut;
+
+	if (argc > 1) {
+		mode = strtol(argv[1], &cp, 0);
+		if (cp[0] != '\0') {
+			printf("Invalid mode\n");
+			return (CMD_ERROR);
+		}
+		status = conout->QueryMode(conout, mode, &cols, &rows);
+		if (EFI_ERROR(status)) {
+			printf("invalid mode %d\n", mode);
+			return (CMD_ERROR);
+		}
+		status = conout->SetMode(conout, mode);
+		if (EFI_ERROR(status)) {
+			printf("couldn't set mode %d\n", mode);
+			return (CMD_ERROR);
+		}
+		sprintf(rowenv, "%u", (unsigned)rows);
+		setenv("LINES", rowenv, 1);
+		HO();		/* set cursor */
+		return (CMD_OK);
+	}
+
+	printf("Current mode: %d\n", conout->Mode->Mode);
+	for (i = 0; i <= conout->Mode->MaxMode; i++) {
+		status = conout->QueryMode(conout, i, &cols, &rows);
+		if (EFI_ERROR(status))
+			continue;
+		printf("Mode %d: %u columns, %u rows\n", i, (unsigned)cols,
+		    (unsigned)rows);
+	}
+
+	if (i != 0)
+		printf("Choose the mode with \"col <mode number>\"\n");
+
+	return (CMD_OK);
+}
+
+
+COMMAND_SET(nvram, "nvram", "get or set NVRAM variables", command_nvram);
+
+static int
+command_nvram(int argc, char *argv[])
+{
+	CHAR16 var[128];
+	CHAR16 *data;
+	EFI_STATUS status;
+	EFI_GUID varguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
+	UINTN varsz, datasz, i;
+	SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
+
+	conout = ST->ConOut;
+
+	/* Initiate the search */
+	status = RS->GetNextVariableName(&varsz, NULL, NULL);
+
+	for (; status != EFI_NOT_FOUND; ) {
+		status = RS->GetNextVariableName(&varsz, var, &varguid);
+		//if (EFI_ERROR(status))
+			//break;
+
+		conout->OutputString(conout, var);
+		printf("=");
+		datasz = 0;
+		status = RS->GetVariable(var, &varguid, NULL, &datasz, NULL);
+		/* XXX: check status */
+		data = malloc(datasz);
+		status = RS->GetVariable(var, &varguid, NULL, &datasz, data);
+		if (EFI_ERROR(status))
+			printf("<error retrieving variable>");
+		else {
+			for (i = 0; i < datasz; i++) {
+				if (isalnum(data[i]) || isspace(data[i]))
+					printf("%c", data[i]);
+				else
+					printf("\\x%02x", data[i]);
+			}
+		}
+		/* XXX */
+		pager_output("\n");
+		free(data);
+	}
+
+	return (CMD_OK);
+}
+
+#ifdef EFI_ZFS_BOOT
+COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
+    command_lszfs);
+
+static int
+command_lszfs(int argc, char *argv[])
+{
+	int err;
+
+	if (argc != 2) {
+		command_errmsg = "wrong number of arguments";
+		return (CMD_ERROR);
+	}
+
+	err = zfs_list(argv[1]);
+	if (err != 0) {
+		command_errmsg = strerror(err);
+		return (CMD_ERROR);
+	}
+	return (CMD_OK);
+}
+
+COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments",
+	    command_reloadbe);
+
+static int
+command_reloadbe(int argc, char *argv[])
+{
+	int err;
+	char *root;
+
+	if (argc > 2) {
+		command_errmsg = "wrong number of arguments";
+		return (CMD_ERROR);
+	}
+
+	if (argc == 2) {
+		err = zfs_bootenv(argv[1]);
+	} else {
+		root = getenv("zfs_be_root");
+		if (root == NULL) {
+			return (CMD_OK);
+		}
+		err = zfs_bootenv(root);
+	}
+
+	if (err != 0) {
+		command_errmsg = strerror(err);
+		return (CMD_ERROR);
+	}
+
+	return (CMD_OK);
+}
+#endif
+
+#ifdef EFI_ZFS_BOOT
+static void
+efi_zfs_probe(void)
+{
+	EFI_HANDLE h;
+	u_int unit;
+	int i;
+	char dname[SPECNAMELEN + 1];
+	uint64_t guid;
+
+	unit = 0;
+	h = efi_find_handle(&efipart_dev, 0);
+	for (i = 0; h != NULL; h = efi_find_handle(&efipart_dev, ++i)) {
+		snprintf(dname, sizeof(dname), "%s%d:", efipart_dev.dv_name, i);
+		if (zfs_probe_dev(dname, &guid) == 0)
+			(void)efi_handle_update_dev(h, &zfs_dev, unit++, guid);
+	}
+}
+#endif


Property changes on: trunk/sys/boot/efi/loader/main.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/loader/version
===================================================================
--- trunk/sys/boot/efi/loader/version	                        (rev 0)
+++ trunk/sys/boot/efi/loader/version	2018-06-02 12:39:13 UTC (rev 10206)
@@ -0,0 +1,8 @@
+$MidnightBSD$
+$FreeBSD: stable/10/sys/boot/efi/loader/version 293297 2016-01-07 02:22:45Z emaste $
+
+NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE.  The format of this
+file is important.  Make sure the current version number is on line 6.
+
+1.1:	Keep in sync with i386 version.
+0.1:	Initial i386 version. Derived from ia64.


Property changes on: trunk/sys/boot/efi/loader/version
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property


More information about the Midnightbsd-cvs mailing list