Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 4 Apr 2014 00:16:47 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r264095 - in head/sys/boot: amd64 amd64/efi efi/include i386/efi
Message-ID:  <201404040016.s340GlJn072315@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Fri Apr  4 00:16:46 2014
New Revision: 264095
URL: http://svnweb.freebsd.org/changeset/base/264095

Log:
  Support UEFI booting on amd64 via loader.efi
  
  This is largely the work from the projects/uefi branch, with some
  additional refinements.  This is derived from (and replaces) the
  original i386 efi implementation; i386 support will be restored later.
  
  Specific revisions of note from projects/uefi:
  
  r247380:
  
    Adjust our load device when we boot from CD under UEFI.
  
    The process for booting from a CD under UEFI involves adding a FAT
    filesystem containing your loader code as an El Torito boot image.
    When UEFI detects this, it provides a block IO instance that points at
    the FAT filesystem as a child of the device that represents the CD
    itself. The problem being that the CD device is flagged as a "raw
    device" while the boot image is flagged as a "logical partition". The
    existing EFI partition code only looks for logical partitions and so
    the CD filesystem was rendered invisible.
  
    To fix this, check the type of each block IO device. If it's found to
    be a CD, and thus an El Torito boot image, look up its parent device
    and add that instead so that the loader will then load the kernel from
    the CD filesystem.  This is done by using the handle for the boot
    filesystem as an alias.
  
    Something similar to this will be required for booting from other
    media as well as the loader will live in the EFI system partition, not
    on the partition containing the kernel.
  
  r246231:
  
    Add necessary code to hand off from loader to an amd64 kernel.
  
  r246335:
  
    Grab the EFI memory map and store it as module metadata on the kernel.
  
    This is the same approach used to provide the BIOS SMAP to the kernel.
  
  r246336:
  
    Pass the ACPI table metadata via hints so the kernel ACPI code can
    find them.
  
  r246608:
  
    Rework copy routines to ensure we always use memory allocated via EFI.
  
    The previous code assumed it could copy wherever it liked. This is not
    the case. The approach taken by this code is pretty ham-fisted in that
    it simply allocates a large (32MB) buffer area and stages into that,
    then copies the whole area into place when it's time to execute. A more
    elegant solution could be used but this works for now.
  
  r247214:
  
    Fix a number of problems preventing proper handover to the kernel.
  
    There were two issues at play here. Firstly, there was nothing
    preventing UEFI from placing the loader code above 1GB in RAM. This
    meant that when we switched in the page tables the kernel expects to
    be running on, we are suddenly unmapped and things no longer work. We
    solve this by making our trampoline code not dependent on being at any
    given position and simply copying it to a "safe" location before
    calling it.
  
    Secondly, UEFI could allocate our stack wherever it wants. As it
    happened on my PC, that was right where I was copying the kernel to.
    This did not cause happiness. The solution to this was to also switch
    to a temporary stack in a safe location before performing the final
    copy of the loaded kernel.
  
  r246231:
  
    Add necessary code to hand off from loader to an amd64 kernel.
  
  r246335:
  
    Grab the EFI memory map and store it as module metadata on the kernel.
  
    This is the same approach used to provide the BIOS SMAP to the kernel.
  
  r246336:
  
    Pass the ACPI table metadata via hints so the kernel ACPI code can
    find them.
  
  r246608:
  
    Rework copy routines to ensure we always use memory allocated via EFI.
  
    The previous code assumed it could copy wherever it liked. This is not
    the case. The approach taken by this code is pretty ham-fisted in that
    it simply allocates a large (32MB) buffer area and stages into that,
    then copies the whole area into place when it's time to execute. A more
    elegant solution could be used but this works for now.
  
  r247214:
  
    Fix a number of problems preventing proper handover to the kernel.
  
    There were two issues at play here. Firstly, there was nothing
    preventing UEFI from placing the loader code above 1GB in RAM. This
    meant that when we switched in the page tables the kernel expects to
    be running on, we are suddenly unmapped and things no longer work. We
    solve this by making our trampoline code not dependent on being at any
    given position and simply copying it to a "safe" location before
    calling it.
  
    Secondly, UEFI could allocate our stack wherever it wants. As it
    happened on my PC, that was right where I was copying the kernel to.
    This did not cause happiness. The solution to this was to also switch
    to a temporary stack in a safe location before performing the final
    copy of the loaded kernel.
  
  r247216:
  
    Use the UEFI Graphics Output Protocol to get the parameters of the
    framebuffer.
  
  Sponsored by:	The FreeBSD Foundation

Added:
  head/sys/boot/amd64/
  head/sys/boot/amd64/Makefile   (contents, props changed)
  head/sys/boot/amd64/Makefile.inc   (contents, props changed)
  head/sys/boot/amd64/efi/
  head/sys/boot/amd64/efi/Makefile
     - copied, changed from r264093, head/sys/boot/i386/efi/Makefile
  head/sys/boot/amd64/efi/amd64_tramp.S   (contents, props changed)
  head/sys/boot/amd64/efi/autoload.c
     - copied, changed from r264093, head/sys/boot/i386/efi/autoload.c
  head/sys/boot/amd64/efi/bootinfo.c   (contents, props changed)
  head/sys/boot/amd64/efi/conf.c
     - copied, changed from r264093, head/sys/boot/i386/efi/conf.c
  head/sys/boot/amd64/efi/copy.c   (contents, props changed)
  head/sys/boot/amd64/efi/devicename.c
     - copied, changed from r264093, head/sys/boot/i386/efi/devicename.c
  head/sys/boot/amd64/efi/elf64_freebsd.c   (contents, props changed)
  head/sys/boot/amd64/efi/framebuffer.c   (contents, props changed)
  head/sys/boot/amd64/efi/framebuffer.h   (contents, props changed)
  head/sys/boot/amd64/efi/ldscript.amd64
     - copied, changed from r264093, head/sys/boot/i386/efi/ldscript.amd64
  head/sys/boot/amd64/efi/main.c
     - copied, changed from r264093, head/sys/boot/i386/efi/main.c
  head/sys/boot/amd64/efi/reloc.c
     - copied unchanged from r264093, head/sys/boot/i386/efi/reloc.c
  head/sys/boot/amd64/efi/start.S   (contents, props changed)
  head/sys/boot/amd64/efi/version
     - copied unchanged from r264093, head/sys/boot/i386/efi/version
  head/sys/boot/amd64/efi/x86_efi.h   (contents, props changed)
  head/sys/boot/efi/include/efigop.h   (contents, props changed)
Deleted:
  head/sys/boot/i386/efi/Makefile
  head/sys/boot/i386/efi/autoload.c
  head/sys/boot/i386/efi/conf.c
  head/sys/boot/i386/efi/devicename.c
  head/sys/boot/i386/efi/ldscript.amd64
  head/sys/boot/i386/efi/main.c
  head/sys/boot/i386/efi/reloc.c
  head/sys/boot/i386/efi/version
Modified:
  head/sys/boot/efi/include/efi.h

Added: head/sys/boot/amd64/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/boot/amd64/Makefile	Fri Apr  4 00:16:46 2014	(r264095)
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+SUBDIR=		efi
+
+.include <bsd.subdir.mk>

Added: head/sys/boot/amd64/Makefile.inc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/boot/amd64/Makefile.inc	Fri Apr  4 00:16:46 2014	(r264095)
@@ -0,0 +1,11 @@
+# Common defines for all of /sys/boot/amd64/
+#
+# $FreeBSD$
+
+BINDIR?=	/boot
+
+CFLAGS+=	-ffreestanding
+CFLAGS+=	-mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
+LDFLAGS+=	-nostdlib
+
+.include "../Makefile.inc"

Copied and modified: head/sys/boot/amd64/efi/Makefile (from r264093, head/sys/boot/i386/efi/Makefile)
==============================================================================
--- head/sys/boot/i386/efi/Makefile	Thu Apr  3 23:22:04 2014	(r264093, copy source)
+++ head/sys/boot/amd64/efi/Makefile	Fri Apr  4 00:16:46 2014	(r264095)
@@ -1,7 +1,6 @@
 # $FreeBSD$
 
 NO_MAN=
-BUILDING_EFI=
 
 .include <bsd.own.mk>
 MK_SSP=		no
@@ -13,30 +12,30 @@ INTERNALPROG=
 SRCS=	autoload.c \
 	bootinfo.c \
 	conf.c \
+	copy.c \
 	devicename.c \
-	efimd.c \
-	elf32_freebsd.c \
-	exec.c \
-	i386_copy.c \
+	elf64_freebsd.c \
+	framebuffer.c \
 	main.c \
 	reloc.c \
 	vers.c
-SRCS+=	start.S
+SRCS+=	amd64_tramp.S \
+	start.S
 
+CFLAGS+=	-fPIC
+CFLAGS+=	-I.
 CFLAGS+=	-I${.CURDIR}/../../efi/include
-CFLAGS+=	-I${.CURDIR}/../../efi/include/i386
+CFLAGS+=	-I${.CURDIR}/../../efi/include/${MACHINE_CPUARCH}
+CFLAGS+=	-I${.CURDIR}/../../../contrib/dev/acpica/include
+CFLAGS+=	-I${.CURDIR}/../../..
 
 .if ${MK_FORTH} != "no"
 BOOT_FORTH=	yes
 CFLAGS+=	-DBOOT_FORTH
 CFLAGS+=	-I${.CURDIR}/../../ficl
-CFLAGS+=	-I${.CURDIR}/../../ficl/i386
-.if ${MACHINE_CPUARCH} == "amd64"
-LIBFICL=	${.OBJDIR}/../../ficl32/libficl.a
-.else
+CFLAGS+=	-I${.CURDIR}/../../ficl/${MACHINE_CPUARCH}
 LIBFICL=	${.OBJDIR}/../../ficl/libficl.a
 .endif
-.endif
 
 # Include bcache code.
 HAVE_BCACHE=    yes
@@ -49,14 +48,14 @@ CFLAGS+=	-I${.CURDIR}/../../common
 FILES=	loader.efi
 FILESMODE_loader.efi=	${BINMODE}
 
-LDSCRIPT=	${.CURDIR}/ldscript.i386
-LDFLAGS=	-Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared
+LDSCRIPT=	${.CURDIR}/ldscript.${MACHINE_CPUARCH}
+LDFLAGS=	-Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared -Wl,-znocombreloc
 
 ${PROG}:	${LDSCRIPT}
 
 CLEANFILES=	vers.c loader.efi
 
-NEWVERSWHAT=	"EFI loader" x86
+NEWVERSWHAT=	"EFI loader" ${MACHINE_CPUARCH}
 
 vers.c:	${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
 	sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
@@ -64,28 +63,36 @@ vers.c:	${.CURDIR}/../../common/newvers.
 OBJCOPY?=	objcopy
 OBJDUMP?=	objdump
 
+.if ${MACHINE_CPUARCH} == "amd64"
+EFI_TARGET=	efi-app-x86_64
+.else
+EFI_TARGET=	efi-app-ia32
+.endif
+
 loader.efi: loader.sym
 	if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \
 		${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
 		exit 1; \
 	fi
-	${OBJCOPY} -j .data -j .dynamic -j .dynstr -j .dynsym -j .hash \
-	    -j .rel.dyn -j .reloc -j .sdata -j .text -j set_Xcommand_set \
-	    --target=efi-app-ia32 ${.ALLSRC} ${.TARGET}
+	${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 \
+		--target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
 
 LIBEFI=		${.OBJDIR}/../../efi/libefi/libefi.a
-LIBSTAND=	${.OBJDIR}/../../libstand32/libstand.a
-CFLAGS+=	-I${.CURDIR}/../libi386
-CFLAGS+=	-I${.CURDIR}/../btx/lib
+CFLAGS+=	-I${.CURDIR}/../../common
 
 DPADD=		${LIBFICL} ${LIBEFI} ${LIBSTAND}
 LDADD=		${LIBFICL} ${LIBEFI} ${LIBSTAND}
 
 .include <bsd.prog.mk>
 
-.if ${MACHINE_CPUARCH} == "amd64"
-CFLAGS+=        -I.
-beforedepend ${OBJS}: machine
+beforedepend ${OBJS}: machine x86
+
+CLEANFILES+=   machine x86
+
 machine:
-	ln -sf ${.CURDIR}/../../../i386/include machine
-.endif
+	ln -sf ${.CURDIR}/../../../amd64/include machine
+
+x86:
+	ln -sf ${.CURDIR}/../../../x86/include x86

Added: head/sys/boot/amd64/efi/amd64_tramp.S
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/boot/amd64/efi/amd64_tramp.S	Fri Apr  4 00:16:46 2014	(r264095)
@@ -0,0 +1,64 @@
+/*-
+ * 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$
+ */
+
+#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

Copied and modified: head/sys/boot/amd64/efi/autoload.c (from r264093, head/sys/boot/i386/efi/autoload.c)
==============================================================================
--- head/sys/boot/i386/efi/autoload.c	Thu Apr  3 23:22:04 2014	(r264093, copy source)
+++ head/sys/boot/amd64/efi/autoload.c	Fri Apr  4 00:16:46 2014	(r264095)
@@ -28,7 +28,7 @@
 __FBSDID("$FreeBSD$");
 
 int
-i386_autoload(void)
+x86_efi_autoload(void)
 {
 
 	return (0);

Added: head/sys/boot/amd64/efi/bootinfo.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/boot/amd64/efi/bootinfo.c	Fri Apr  4 00:16:46 2014	(r264095)
@@ -0,0 +1,360 @@
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith@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$");
+
+#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/metadata.h>
+#include <machine/psl.h>
+#include <machine/specialreg.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+#include "framebuffer.h"
+#include "x86_efi.h"
+
+UINTN x86_efi_mapkey;
+
+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;
+	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;
+	}
+
+	/* 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 (x86_efi_copyin(ep->ev_name, addr, len) != len)
+			break;
+		addr += len;
+		if (x86_efi_copyin("=", addr, 1) != 1)
+			break;
+		addr++;
+		if (ep->ev_value != NULL) {
+			len = strlen(ep->ev_value);
+			if (x86_efi_copyin(ep->ev_value, addr, len) != len)
+				break;
+			addr += len;
+		}
+		if (x86_efi_copyin("", addr, 1) != 1)
+			break;
+		last = ++addr;
+	}
+
+	if (x86_efi_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)							\
+		x86_efi_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)							\
+		x86_efi_copyin(s, a, strlen(s) + 1);		\
+	a += roundup(strlen(s) + 1, sizeof(uint64_t));		\
+}
+
+#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)							\
+		x86_efi_copyin(&s, a, sizeof(s));		\
+	a += roundup(sizeof(s), sizeof(uint64_t));		\
+}
+
+#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)							\
+		x86_efi_copyin(mm->md_data, a, mm->md_size);	\
+	a += roundup(mm->md_size, sizeof(uint64_t));		\
+}
+
+#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 mmsz, pages, sz;
+	UINT32 mmver;
+	struct efi_map_header *efihdr;
+	struct efi_fb efifb;
+
+	if (efi_find_framebuffer(&efifb) == 0)
+		file_addmetadata(kfp, MODINFOMD_EFI_FB, sizeof(efifb), &efifb);
+
+	efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
+
+	/*
+	 * 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, &x86_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() returned 0x%lx\n", __func__,
+		    (long)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, &x86_efi_mapkey, &mmsz, &mmver);
+	if (EFI_ERROR(status)) {
+		printf("%s: GetMemoryMap() returned 0x%lx\n", __func__,
+		    (long)status);
+		return (EINVAL);
+	}
+
+	efihdr->memory_size = sz;
+	efihdr->descriptor_size = mmsz;
+	efihdr->descriptor_version = mmver;
+
+	file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz, efihdr);
+
+	return (0);
+}
+
+/*
+ * 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");
+	x86_efi_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(x86_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);
+}

Copied and modified: head/sys/boot/amd64/efi/conf.c (from r264093, head/sys/boot/i386/efi/conf.c)
==============================================================================
--- head/sys/boot/i386/efi/conf.c	Thu Apr  3 23:22:04 2014	(r264093, copy source)
+++ head/sys/boot/amd64/efi/conf.c	Fri Apr  4 00:16:46 2014	(r264095)
@@ -52,20 +52,12 @@ struct netif_driver *netif_drivers[] = {
 	NULL
 };
 
-#ifdef notyet
 extern struct file_format amd64_elf;
 extern struct file_format amd64_elf_obj;
-#endif
-extern struct file_format i386_elf;
-extern struct file_format i386_elf_obj;
 
 struct file_format *file_formats[] = {
-#ifdef notyet
 	&amd64_elf,
 	&amd64_elf_obj,
-#endif
-	&i386_elf,
-	&i386_elf_obj,
 	NULL
 };
 

Added: head/sys/boot/amd64/efi/copy.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/boot/amd64/efi/copy.c	Fri Apr  4 00:16:46 2014	(r264095)
@@ -0,0 +1,102 @@
+/*-
+ * 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$");
+
+#include <sys/param.h>
+
+#include <stand.h>
+#include <bootstrap.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#define	STAGE_PAGES	8192	/* 32MB */
+
+EFI_PHYSICAL_ADDRESS	staging;
+int			stage_offset_set = 0;
+ssize_t			stage_offset;
+
+int
+x86_efi_copy_init(void)
+{
+	EFI_STATUS	status;
+
+	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+	    STAGE_PAGES, &staging);
+	if (EFI_ERROR(status)) {
+		printf("failed to allocate staging area: %d\n",
+		    status & EFI_ERROR_MASK);
+		return (status);
+	}
+
+	return (0);
+}
+
+ssize_t
+x86_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;
+	}
+
+	bcopy(src, (void *)(dest + stage_offset), len);
+	return (len);
+}
+
+ssize_t
+x86_efi_copyout(const vm_offset_t src, void *dest, const size_t len)
+{
+
+	bcopy((void *)(src + stage_offset), dest, len);
+	return (len);
+}
+
+
+ssize_t
+x86_efi_readin(const int fd, vm_offset_t dest, const size_t len)
+{
+
+	return (read(fd, (void *)(dest + stage_offset), len));
+}
+
+void
+x86_efi_copy_finish(void)
+{
+	uint64_t	*src, *dst, *last;
+
+	src = (uint64_t *)staging;
+	dst = (uint64_t *)(staging - stage_offset);
+	last = (uint64_t *)(staging + STAGE_PAGES * EFI_PAGE_SIZE);
+
+	while (src < last)
+		*dst++ = *src++;
+}

Copied and modified: head/sys/boot/amd64/efi/devicename.c (from r264093, head/sys/boot/i386/efi/devicename.c)
==============================================================================
--- head/sys/boot/i386/efi/devicename.c	Thu Apr  3 23:22:04 2014	(r264093, copy source)
+++ head/sys/boot/amd64/efi/devicename.c	Fri Apr  4 00:16:46 2014	(r264095)
@@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
 #include <efi.h>
 #include <efilib.h>
 
-static int i386_parsedev(struct devdesc **, const char *, const char **);
+static int x86_efi_parsedev(struct devdesc **, const char *, const char **);
 
 /* 
  * Point (dev) at an allocated device specifier for the device matching the
@@ -44,7 +44,7 @@ static int i386_parsedev(struct devdesc 
  * use that.  If not, use the default device.
  */
 int
-i386_getdev(void **vdev, const char *devspec, const char **path)
+x86_efi_getdev(void **vdev, const char *devspec, const char **path)
 {
 	struct devdesc **dev = (struct devdesc **)vdev;
 	int rv;
@@ -54,14 +54,14 @@ i386_getdev(void **vdev, const char *dev
 	 * use the current device instead.
 	 */
 	if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) {
-		rv = i386_parsedev(dev, getenv("currdev"), NULL);
+		rv = x86_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 (i386_parsedev(dev, devspec, path));
+	return (x86_efi_parsedev(dev, devspec, path));
 }
 
 /*
@@ -78,7 +78,7 @@ i386_getdev(void **vdev, const char *dev
  * fs<unit>:
  */
 static int
-i386_parsedev(struct devdesc **dev, const char *devspec, const char **path)
+x86_efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
 {
 	struct devdesc *idev;
 	struct devsw *dv;
@@ -132,7 +132,7 @@ i386_parsedev(struct devdesc **dev, cons
 }
 
 char *
-i386_fmtdev(void *vdev)
+x86_efi_fmtdev(void *vdev)
 {
 	struct devdesc *dev = (struct devdesc *)vdev;
 	static char buf[32];	/* XXX device length constant? */
@@ -154,12 +154,12 @@ i386_fmtdev(void *vdev)
  * Set currdev to suit the value being supplied in (value)
  */
 int
-i386_setcurrdev(struct env_var *ev, int flags, const void *value)
+x86_efi_setcurrdev(struct env_var *ev, int flags, const void *value)
 {
 	struct devdesc *ncurr;
 	int rv;
 
-	rv = i386_parsedev(&ncurr, value, NULL);
+	rv = x86_efi_parsedev(&ncurr, value, NULL);
 	if (rv != 0)
 		return(rv);
 

Added: head/sys/boot/amd64/efi/elf64_freebsd.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/boot/amd64/efi/elf64_freebsd.c	Fri Apr  4 00:16:46 2014	(r264095)
@@ -0,0 +1,189 @@
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith@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$");
+
+#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
+#include "actypes.h"
+#include "actbl.h"
+
+#include "x86_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);
+
+struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
+struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
+
+#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;
+	EFI_STATUS		status;
+
+	rsdp = efi_get_table(&acpi20_guid);
+	if (rsdp == NULL) {
+		rsdp = efi_get_table(&acpi_guid);
+	}
+	if (rsdp != NULL) {
+		sprintf(buf, "0x%016llx", 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", 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);
+
+	status = BS->ExitBootServices(IH, x86_efi_mapkey);
+	if (EFI_ERROR(status)) {
+		printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
+		    (long)status);
+		return (EINVAL);
+	}
+
+	dev_cleanup();
+
+	trampoline(trampstack, x86_efi_copy_finish, kernend, modulep, PT4,
+	    ehdr->e_entry);
+
+	panic("exec returned");
+}
+
+static int
+elf64_obj_exec(struct preloaded_file *fp)
+{
+	return (EFTYPE);
+}

Added: head/sys/boot/amd64/efi/framebuffer.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/boot/amd64/efi/framebuffer.c	Fri Apr  4 00:16:46 2014	(r264095)
@@ -0,0 +1,85 @@
+/*-
+ * 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

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404040016.s340GlJn072315>