summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2014-09-04 21:01:10 +0000
committeremaste <emaste@FreeBSD.org>2014-09-04 21:01:10 +0000
commit261ad5a21cf8549e5837942a5890d7a3747adcb6 (patch)
treee211ff20c03fdf2844b8e3aa9063d03c400254b8 /sys/boot
parentae111330ce92f88fb725388657403bf2a6f3c464 (diff)
downloadFreeBSD-src-261ad5a21cf8549e5837942a5890d7a3747adcb6.zip
FreeBSD-src-261ad5a21cf8549e5837942a5890d7a3747adcb6.tar.gz
MFC UEFI loader
This MFC consists of the following SVN revisions: 258741 261568 261603 261668 263115 263117 263968 264078 264087 264088 264092 264095 264115 264132 264208 264261 264262 264263 264319 265028 265057 268974 Detailed commit messages: r258741: Note that libstand is 32-bit on amd64 and powerpc64 r261568: Build libstand as a 64-bit library on amd64 The 32-bit bootloaders now link against libstand.a in sys/boot/libstand32, so there is no need to force /usr/lib/libstand.a to be 32-bit. r261603: Don't force efi to a 32-bit build on amd64 r261668: Build libstand as a 64-bit library on ppc64 The 32-bit bootloaders now link against libstand.a in sys/boot/libstand32, so there is no need to force /usr/lib/libstand.a to be 32-bit. This is equivalent to r261568 for amd64. r263115: Add amd64 EFI headers r263117: Connect 64-bit boot ficl to the build It is not yet used, but this will ensure it doesn't get broken. r263968: Use EFI types for EFI values (silences warnings). EFI UINTN is actually a 64-bit type on 64-bit processors. r264078: Put each source file on a separate line This will simplify rebasing the amd64 UEFI patch set. r264087: Build boot/ficl as 64-bit library on amd64 The 32-bit bootloaders on amd64 now use the 32-bit version in ficl32, as is done with libstand32. The native 64-bit ficl will be used by the upcoming UEFI loader. r264088: Merge efilib changes from projects/uefi r247216: Add the ability for a device to have an "alias" handle. r247379: Fix network device registration. 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. r247381: Remove a scatalogical debug printf that crept in. r264092: Add -fPIC for amd64 r264095: 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. r264115: Fix printf format mismatches r264132: Connect sys/boot/amd64 to the build r264208: Do not build the amd64 UEFI loader with GCC The UEFI loader causes buildworld to fail when building with (in-tree) GCC, due to a typedef redefinition. As it happens the in-tree GCC cannot successfully build the UEFI loader anyhow, as it does not support __attribute__((ms_abi)). Thus, just avoid trying to build it with GCC, rather than disconnecting it from the build until the underlying issue is fixed. r264261: Correct a variable's type for 64-bit Ficl FICL_INT is long. r264262: Fix printf args for 64-bit archs r264263: Add explicit casts to quiet warnings in libefi r264319: Fix EFI loader object tree creation on 9.x build hosts Previously ${COMPILER_TYPE} was checked in sys/boot/amd64, and the efi subdirectory was skipped altogether for gcc (since GCC does not support a required attribute). However, during the early buildworld stages ${COMPILER_TYPE} is the existing system compiler (i.e., gcc on 9.x build hosts), not the compiler that will eventually be used. This caused "make obj" to skip the efi subdirectory. In later build stages ${COMPILER_TYPE} is "clang", and then the efi loader would attempt to build in the source directory. r265028 (dteske): Disable the beastie menu for EFI console ... which doesn't support ANSI codes (so things like `at-xy', `clear', and other commands don't work making it impossible to generate a living menu). r265057 (nwhitehorn): Turn off various fancy instruction sets... as well as deduplicate some options. This makes the EFI loader build work with CPUTYPE=native in make.conf on my Core i5. r268974 (sbruno): Supress clang warning for FreeBSD printf %b and %D formats Relnotes: Yes Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/Makefile5
-rw-r--r--sys/boot/Makefile.amd644
-rw-r--r--sys/boot/amd64/Makefile7
-rw-r--r--sys/boot/amd64/Makefile.inc12
-rw-r--r--sys/boot/amd64/efi/Makefile (renamed from sys/boot/i386/efi/Makefile)67
-rw-r--r--sys/boot/amd64/efi/amd64_tramp.S64
-rw-r--r--sys/boot/amd64/efi/autoload.c (renamed from sys/boot/i386/efi/autoload.c)2
-rw-r--r--sys/boot/amd64/efi/bootinfo.c360
-rw-r--r--sys/boot/amd64/efi/conf.c (renamed from sys/boot/i386/efi/conf.c)8
-rw-r--r--sys/boot/amd64/efi/copy.c102
-rw-r--r--sys/boot/amd64/efi/devicename.c (renamed from sys/boot/i386/efi/devicename.c)16
-rw-r--r--sys/boot/amd64/efi/elf64_freebsd.c190
-rw-r--r--sys/boot/amd64/efi/framebuffer.c85
-rw-r--r--sys/boot/amd64/efi/framebuffer.h36
-rw-r--r--sys/boot/amd64/efi/ldscript.amd64 (renamed from sys/boot/i386/efi/ldscript.amd64)24
-rw-r--r--sys/boot/amd64/efi/main.c (renamed from sys/boot/i386/efi/main.c)42
-rw-r--r--sys/boot/amd64/efi/reloc.c107
-rw-r--r--sys/boot/amd64/efi/start.S76
-rw-r--r--sys/boot/amd64/efi/version (renamed from sys/boot/i386/efi/version)0
-rw-r--r--sys/boot/amd64/efi/x86_efi.h49
-rw-r--r--sys/boot/efi/Makefile.inc9
-rw-r--r--sys/boot/efi/include/amd64/efibind.h267
-rw-r--r--sys/boot/efi/include/amd64/pe.h592
-rw-r--r--sys/boot/efi/include/efi.h1
-rw-r--r--sys/boot/efi/include/efigop.h122
-rw-r--r--sys/boot/efi/include/efilib.h2
-rw-r--r--sys/boot/efi/libefi/Makefile9
-rw-r--r--sys/boot/efi/libefi/efinet.c2
-rw-r--r--sys/boot/efi/libefi/efipart.c48
-rw-r--r--sys/boot/efi/libefi/handles.c10
-rw-r--r--sys/boot/ficl/Makefile23
-rw-r--r--sys/boot/ficl/tools.c22
-rw-r--r--sys/boot/ficl/words.c2
-rw-r--r--sys/boot/ficl32/Makefile (renamed from sys/boot/ficl64/Makefile)2
-rw-r--r--sys/boot/forth/beastie.4th5
-rw-r--r--sys/boot/forth/beastie.4th.84
-rw-r--r--sys/boot/forth/loader.conf.54
-rw-r--r--sys/boot/i386/libi386/Makefile3
-rw-r--r--sys/boot/i386/loader/Makefile4
39 files changed, 2274 insertions, 113 deletions
diff --git a/sys/boot/Makefile b/sys/boot/Makefile
index 06cffb1..0d6441d 100644
--- a/sys/boot/Makefile
+++ b/sys/boot/Makefile
@@ -9,9 +9,12 @@ SUBDIR+= ficl
.endif
# Pick the machine-dependent subdir based on the target architecture.
-ADIR= ${MACHINE:S/amd64/i386/:S/powerpc64/powerpc/}
+ADIR= ${MACHINE:S/powerpc64/powerpc/}
.if exists(${.CURDIR}/${ADIR}/.)
SUBDIR+= ${ADIR}
.endif
+.if ${MACHINE} == "amd64"
+SUBDIR+= i386
+.endif
.include <bsd.subdir.mk>
diff --git a/sys/boot/Makefile.amd64 b/sys/boot/Makefile.amd64
index 34ffb6c..2b85283 100644
--- a/sys/boot/Makefile.amd64
+++ b/sys/boot/Makefile.amd64
@@ -4,3 +4,7 @@ SUBDIR+= efi
SUBDIR+= libstand32
SUBDIR+= zfs
SUBDIR+= userboot
+
+.if ${MK_FORTH} != "no"
+SUBDIR+= ficl32
+.endif
diff --git a/sys/boot/amd64/Makefile b/sys/boot/amd64/Makefile
new file mode 100644
index 0000000..d0013fa
--- /dev/null
+++ b/sys/boot/amd64/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+SUBDIR= efi
+
+.include <bsd.subdir.mk>
diff --git a/sys/boot/amd64/Makefile.inc b/sys/boot/amd64/Makefile.inc
new file mode 100644
index 0000000..ee96a42
--- /dev/null
+++ b/sys/boot/amd64/Makefile.inc
@@ -0,0 +1,12 @@
+# Common defines for all of /sys/boot/amd64/
+#
+# $FreeBSD$
+
+BINDIR?= /boot
+
+# See conf/kern.mk for the correct set of these
+CFLAGS+= -ffreestanding
+CFLAGS+= -mno-mmx -mno-sse -mno-aes -mno-avx -msoft-float
+LDFLAGS+= -nostdlib
+
+.include "../Makefile.inc"
diff --git a/sys/boot/i386/efi/Makefile b/sys/boot/amd64/efi/Makefile
index 5a04466..8802605 100644
--- a/sys/boot/i386/efi/Makefile
+++ b/sys/boot/amd64/efi/Makefile
@@ -1,26 +1,43 @@
# $FreeBSD$
NO_MAN=
-BUILDING_EFI=
.include <bsd.own.mk>
+
+# In-tree GCC does not support __attribute__((ms_abi)).
+.if ${COMPILER_TYPE} != "gcc"
+
MK_SSP= no
PROG= loader.sym
INTERNALPROG=
# architecture-specific loader code
-SRCS= main.c exec.c conf.c vers.c reloc.c start.S elf32_freebsd.c
-SRCS+= i386_copy.c bootinfo.c autoload.c devicename.c efimd.c
-
+SRCS= autoload.c \
+ bootinfo.c \
+ conf.c \
+ copy.c \
+ devicename.c \
+ elf64_freebsd.c \
+ framebuffer.c \
+ main.c \
+ reloc.c \
+ vers.c
+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
+CFLAGS+= -I${.CURDIR}/../../ficl/${MACHINE_CPUARCH}
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
.endif
@@ -35,14 +52,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}
@@ -50,28 +67,38 @@ vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
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}
+.endif # ${COMPILER_TYPE} != "gcc"
+
.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
diff --git a/sys/boot/amd64/efi/amd64_tramp.S b/sys/boot/amd64/efi/amd64_tramp.S
new file mode 100644
index 0000000..c102d92
--- /dev/null
+++ b/sys/boot/amd64/efi/amd64_tramp.S
@@ -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
diff --git a/sys/boot/i386/efi/autoload.c b/sys/boot/amd64/efi/autoload.c
index 26370d6..efb32d4 100644
--- a/sys/boot/i386/efi/autoload.c
+++ b/sys/boot/amd64/efi/autoload.c
@@ -28,7 +28,7 @@
__FBSDID("$FreeBSD$");
int
-i386_autoload(void)
+x86_efi_autoload(void)
{
return (0);
diff --git a/sys/boot/amd64/efi/bootinfo.c b/sys/boot/amd64/efi/bootinfo.c
new file mode 100644
index 0000000..bf11f5b
--- /dev/null
+++ b/sys/boot/amd64/efi/bootinfo.c
@@ -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);
+}
diff --git a/sys/boot/i386/efi/conf.c b/sys/boot/amd64/efi/conf.c
index 13c2145..0e67b6b 100644
--- a/sys/boot/i386/efi/conf.c
+++ b/sys/boot/amd64/efi/conf.c
@@ -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
};
diff --git a/sys/boot/amd64/efi/copy.c b/sys/boot/amd64/efi/copy.c
new file mode 100644
index 0000000..c6cc349
--- /dev/null
+++ b/sys/boot/amd64/efi/copy.c
@@ -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: %lu\n",
+ (unsigned long)(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++;
+}
diff --git a/sys/boot/i386/efi/devicename.c b/sys/boot/amd64/efi/devicename.c
index c3d9062..aa43628 100644
--- a/sys/boot/i386/efi/devicename.c
+++ b/sys/boot/amd64/efi/devicename.c
@@ -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 **, const char *, const char **);
* 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 *devspec, const char **path)
* 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 *devspec, const char **path)
* 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, const char *devspec, const char **path)
}
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);
diff --git a/sys/boot/amd64/efi/elf64_freebsd.c b/sys/boot/amd64/efi/elf64_freebsd.c
new file mode 100644
index 0000000..0fb82b0
--- /dev/null
+++ b/sys/boot/amd64/efi/elf64_freebsd.c
@@ -0,0 +1,190 @@
+/*-
+ * 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", (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);
+
+ 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);
+}
diff --git a/sys/boot/amd64/efi/framebuffer.c b/sys/boot/amd64/efi/framebuffer.c
new file mode 100644
index 0000000..90bf992
--- /dev/null
+++ b/sys/boot/amd64/efi/framebuffer.c
@@ -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
+ * 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 <efi.h>
+#include <efilib.h>
+#include <machine/metadata.h>
+
+static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+
+int
+efi_find_framebuffer(struct efi_fb *efifb)
+{
+ EFI_GRAPHICS_OUTPUT *gop;
+ EFI_STATUS status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *mode;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
+
+ status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop);
+ if (EFI_ERROR(status))
+ return (1);
+
+ mode = gop->Mode;
+ info = gop->Mode->Info;
+
+ 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;
+
+ switch (info->PixelFormat) {
+ 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 = info->PixelInformation.RedMask;
+ efifb->fb_mask_green = info->PixelInformation.GreenMask;
+ efifb->fb_mask_blue = info->PixelInformation.BlueMask;
+ efifb->fb_mask_reserved =
+ info->PixelInformation.ReservedMask;
+ break;
+ default:
+ return (1);
+ }
+ return (0);
+}
diff --git a/sys/boot/amd64/efi/framebuffer.h b/sys/boot/amd64/efi/framebuffer.h
new file mode 100644
index 0000000..2ec9017
--- /dev/null
+++ b/sys/boot/amd64/efi/framebuffer.h
@@ -0,0 +1,36 @@
+/*-
+ * 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$
+ */
+
+#ifndef _EFIFB_H_
+#define _EFIFB_H_
+
+int efi_find_framebuffer(struct efi_fb *efifb);
+
+#endif /* _EFIFB_H_ */
diff --git a/sys/boot/i386/efi/ldscript.amd64 b/sys/boot/amd64/efi/ldscript.amd64
index face49e..14e1f06 100644
--- a/sys/boot/i386/efi/ldscript.amd64
+++ b/sys/boot/amd64/efi/ldscript.amd64
@@ -7,11 +7,13 @@ SECTIONS
/* Read-only sections, merged into text segment: */
. = 0;
ImageBase = .;
- . = SIZEOF_HEADERS;
+ .hash : { *(.hash) } /* this MUST come first! */
. = ALIGN(4096);
- .eh_frame : {
+ .eh_frame :
+ {
*(.eh_frame)
- }
+ }
+ . = ALIGN(4096);
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
@@ -51,24 +53,14 @@ SECTIONS
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rela.dyn : {
- *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
- *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
- *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.data*)
*(.rela.got)
- *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
- *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
- *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
- *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
- *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
- *(.rela.plt)
- *(.relset_*)
- *(.rela.dyn .rela.dyn.*)
+ *(.rela.stab)
+ *(.relaset_*)
}
. = ALIGN(4096);
.reloc : { *(.reloc) }
. = ALIGN(4096);
- .hash : { *(.hash) }
- . = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
diff --git a/sys/boot/i386/efi/main.c b/sys/boot/amd64/efi/main.c
index 1ea5c24..d1ea9c3 100644
--- a/sys/boot/i386/efi/main.c
+++ b/sys/boot/amd64/efi/main.c
@@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
#include <efilib.h>
#include <bootstrap.h>
-#include "../libi386/libi386.h"
+#include "x86_efi.h"
extern char bootprog_name[];
extern char bootprog_rev[];
@@ -61,7 +61,7 @@ main(int argc, CHAR16 *argv[])
EFI_LOADED_IMAGE *img;
int i;
- /*
+ /*
* 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
@@ -69,6 +69,11 @@ main(int argc, CHAR16 *argv[])
*/
cons_probe();
+ if (x86_efi_copy_init()) {
+ printf("failed to allocate staging area\n");
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+
/*
* March through the device switch probing for things.
*/
@@ -106,18 +111,18 @@ main(int argc, CHAR16 *argv[])
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
- env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&currdev),
- i386_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&currdev), env_noset,
+ env_setenv("currdev", EV_VOLATILE, x86_efi_fmtdev(&currdev),
+ x86_efi_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, x86_efi_fmtdev(&currdev), env_noset,
env_nounset);
setenv("LINES", "24", 1); /* optional */
-
- archsw.arch_autoload = i386_autoload;
- archsw.arch_getdev = i386_getdev;
- archsw.arch_copyin = i386_copyin;
- archsw.arch_copyout = i386_copyout;
- archsw.arch_readin = i386_readin;
+
+ archsw.arch_autoload = x86_efi_autoload;
+ archsw.arch_getdev = x86_efi_getdev;
+ archsw.arch_copyin = x86_efi_copyin;
+ archsw.arch_copyout = x86_efi_copyout;
+ archsw.arch_readin = x86_efi_readin;
interact(); /* doesn't return */
@@ -195,7 +200,7 @@ command_memmap(int argc, char *argv[])
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 %012lx %012lx %08lx ",
@@ -265,7 +270,7 @@ command_configuration(int argc, char *argv[])
}
return CMD_OK;
-}
+}
COMMAND_SET(mode, "mode", "change or display text modes", command_mode);
@@ -273,7 +278,8 @@ COMMAND_SET(mode, "mode", "change or display text modes", command_mode);
static int
command_mode(int argc, char *argv[])
{
- unsigned int cols, rows, mode;
+ UINTN cols, rows;
+ unsigned int mode;
int i;
char *cp;
char rowenv[8];
@@ -298,7 +304,7 @@ command_mode(int argc, char *argv[])
printf("couldn't set mode %d\n", mode);
return (CMD_ERROR);
}
- sprintf(rowenv, "%d", rows);
+ sprintf(rowenv, "%u", (unsigned)rows);
setenv("LINES", rowenv, 1);
return (CMD_OK);
@@ -308,7 +314,8 @@ command_mode(int argc, char *argv[])
status = conout->QueryMode(conout, i, &cols, &rows);
if (EFI_ERROR(status))
break;
- printf("Mode %d: %d columns, %d rows\n", i, cols, rows);
+ printf("Mode %d: %u columns, %u rows\n", i, (unsigned)cols,
+ (unsigned)rows);
}
if (i != 0)
@@ -327,8 +334,7 @@ command_nvram(int argc, char *argv[])
CHAR16 *data;
EFI_STATUS status;
EFI_GUID varguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
- unsigned int varsz;
- unsigned int datasz;
+ UINTN varsz, datasz;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
int i;
diff --git a/sys/boot/amd64/efi/reloc.c b/sys/boot/amd64/efi/reloc.c
new file mode 100644
index 0000000..98bcf8e
--- /dev/null
+++ b/sys/boot/amd64/efi/reloc.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2008-2010 Rui Paulo <rpaulo@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$");
+
+#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
+
+/*
+ * A simple relocator for IA32/AMD64 EFI binaries.
+ */
+EFI_STATUS
+_reloc(unsigned long ImageBase, ElfW_Dyn *dynamic, EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *system_table)
+{
+ 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 *) ((caddr_t) rel + relent);
+ }
+
+ return (EFI_SUCCESS);
+}
diff --git a/sys/boot/amd64/efi/start.S b/sys/boot/amd64/efi/start.S
new file mode 100644
index 0000000..beaeeff
--- /dev/null
+++ b/sys/boot/amd64/efi/start.S
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ * Contributed by David Mosberger <davidm@hpl.hp.com>.
+ * Copyright (C) 2005 Intel Co.
+ * Contributed by Fenghua Yu <fenghua.yu@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$
+ */
+
+ .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
diff --git a/sys/boot/i386/efi/version b/sys/boot/amd64/efi/version
index 3a4c47c..3a4c47c 100644
--- a/sys/boot/i386/efi/version
+++ b/sys/boot/amd64/efi/version
diff --git a/sys/boot/amd64/efi/x86_efi.h b/sys/boot/amd64/efi/x86_efi.h
new file mode 100644
index 0000000..73a61c8
--- /dev/null
+++ b/sys/boot/amd64/efi/x86_efi.h
@@ -0,0 +1,49 @@
+/*-
+ * 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$
+ */
+
+#ifndef _X86_EFI_COPY_H_
+#define _X86_EFI_COPY_H_
+
+int x86_efi_autoload(void);
+
+int x86_efi_getdev(void **vdev, const char *devspec, const char **path);
+char *x86_efi_fmtdev(void *vdev);
+int x86_efi_setcurrdev(struct env_var *ev, int flags, const void *value);
+
+int x86_efi_copy_init(void);
+void x86_efi_copy_finish(void);
+
+ssize_t x86_efi_copyin(const void *src, vm_offset_t dest, const size_t len);
+ssize_t x86_efi_copyout(const vm_offset_t src, void *dest, const size_t len);
+ssize_t x86_efi_readin(const int fd, vm_offset_t dest, const size_t len);
+
+extern UINTN x86_efi_mapkey;
+
+#endif /* _X86_EFI_COPY_H_ */
diff --git a/sys/boot/efi/Makefile.inc b/sys/boot/efi/Makefile.inc
index 7446d31..29ebae4 100644
--- a/sys/boot/efi/Makefile.inc
+++ b/sys/boot/efi/Makefile.inc
@@ -2,17 +2,10 @@
BINDIR?= /boot
-.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+.if ${MACHINE_CPUARCH} == "i386"
CFLAGS+= -march=i386
.endif
-.if ${MACHINE_CPUARCH} == "amd64"
-CFLAGS+= -m32
-ACFLAGS+= -m32
-LDFLAGS+= -m elf_i386_fbsd
-AFLAGS+= --32
-.endif
-
# Options used when building app-specific efi components
CFLAGS+= -ffreestanding -fshort-wchar -Wformat
LDFLAGS+= -nostdlib
diff --git a/sys/boot/efi/include/amd64/efibind.h b/sys/boot/efi/include/amd64/efibind.h
new file mode 100644
index 0000000..1905596
--- /dev/null
+++ b/sys/boot/efi/include/amd64/efibind.h
@@ -0,0 +1,267 @@
+/* $FreeBSD$ */
+/*++
+
+Copyright (c) 1999 - 2003 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ efefind.h
+
+Abstract:
+
+ EFI to compile bindings
+
+
+
+
+Revision History
+
+--*/
+
+#pragma pack()
+
+
+#ifdef __FreeBSD__
+#include <sys/stdint.h>
+#else
+//
+// Basic int types of various widths
+//
+
+#if (__STDC_VERSION__ < 199901L )
+
+ // No ANSI C 1999/2000 stdint.h integer width declarations
+
+ #if _MSC_EXTENSIONS
+
+ // Use Microsoft C compiler integer width declarations
+
+ typedef unsigned __int64 uint64_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int32 uint32_t;
+ typedef __int32 int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #else
+ #ifdef UNIX_LP64
+
+ // Use LP64 programming model from C_FLAGS for integer width declarations
+
+ typedef unsigned long uint64_t;
+ typedef long int64_t;
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #else
+
+ // Assume P64 programming model from C_FLAGS for integer width declarations
+
+ typedef unsigned long long uint64_t;
+ typedef long long int64_t;
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #endif
+ #endif
+#endif
+#endif /* __FreeBSD__ */
+
+//
+// Basic EFI types of various widths
+//
+
+typedef uint64_t UINT64;
+typedef int64_t INT64;
+
+#ifndef _BASETSD_H_
+ typedef uint32_t UINT32;
+ typedef int32_t INT32;
+#endif
+
+typedef uint16_t UINT16;
+typedef int16_t INT16;
+typedef uint8_t UINT8;
+typedef int8_t INT8;
+
+
+#undef VOID
+#define VOID void
+
+
+typedef int64_t INTN;
+typedef uint64_t UINTN;
+
+#ifdef EFI_NT_EMULATOR
+ #define POST_CODE(_Data)
+#else
+ #ifdef EFI_DEBUG
+#define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al
+ #else
+ #define POST_CODE(_Data)
+ #endif
+#endif
+
+#define EFIERR(a) (0x8000000000000000 | a)
+#define EFI_ERROR_MASK 0x8000000000000000
+#define EFIERR_OEM(a) (0xc000000000000000 | a)
+
+
+#define BAD_POINTER 0xFBFBFBFBFBFBFBFB
+#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF
+
+#define BREAKPOINT() __asm { int 3 }
+
+//
+// Pointers must be aligned to these address to function
+//
+
+#define MIN_ALIGNMENT_SIZE 4
+
+#define ALIGN_VARIABLE(Value ,Adjustment) \
+ (UINTN)Adjustment = 0; \
+ if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
+ (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
+ Value = (UINTN)Value + (UINTN)Adjustment
+
+
+//
+// Define macros to build data structure signatures from characters.
+//
+
+#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+
+//
+// EFIAPI - prototype calling convention for EFI function pointers
+// BOOTSERVICE - prototype for implementation of a boot service interface
+// RUNTIMESERVICE - prototype for implementation of a runtime service interface
+// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
+// RUNTIME_CODE - pragma macro for declaring runtime code
+//
+
+#ifdef __amd64__
+#define EFIAPI __attribute__((ms_abi))
+#endif
+
+#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
+ #if _MSC_EXTENSIONS
+ #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler
+ #else
+ #define EFIAPI // Substitute expresion to force C calling convention
+ #endif
+#endif
+
+#define BOOTSERVICE
+//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a
+//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a
+#define RUNTIMESERVICE
+#define RUNTIMEFUNCTION
+
+
+#define RUNTIME_CODE(a) alloc_text("rtcode", a)
+#define BEGIN_RUNTIME_DATA() data_seg("rtdata")
+#define END_RUNTIME_DATA() data_seg("")
+
+#define VOLATILE volatile
+
+#define MEMORY_FENCE()
+
+#ifdef EFI_NO_INTERFACE_DECL
+ #define EFI_FORWARD_DECLARATION(x)
+ #define EFI_INTERFACE_DECL(x)
+#else
+ #define EFI_FORWARD_DECLARATION(x) typedef struct _##x x
+ #define EFI_INTERFACE_DECL(x) typedef struct x
+#endif
+
+#ifdef EFI_NT_EMULATOR
+
+//
+// To help ensure proper coding of integrated drivers, they are
+// compiled as DLLs. In NT they require a dll init entry pointer.
+// The macro puts a stub entry point into the DLL so it will load.
+//
+
+#define EFI_DRIVER_ENTRY_POINT(InitFunction) \
+ EFI_STATUS \
+ InitFunction ( \
+ EFI_HANDLE ImageHandle, \
+ EFI_SYSTEM_TABLE *SystemTable \
+ ); \
+ \
+ UINTN \
+ __stdcall \
+ _DllMainCRTStartup ( \
+ UINTN Inst, \
+ UINTN reason_for_call, \
+ VOID *rserved \
+ ) \
+ { \
+ return 1; \
+ } \
+ \
+ int \
+ __declspec( dllexport ) \
+ __cdecl \
+ InitializeDriver ( \
+ void *ImageHandle, \
+ void *SystemTable \
+ ) \
+ { \
+ return InitFunction(ImageHandle, SystemTable); \
+ }
+
+
+ #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \
+ (_if)->LoadInternal(type, name, NULL)
+
+#else // EFI_NT_EMULATOR
+
+//
+// When build similiar to FW, then link everything together as
+// one big module.
+//
+
+ #define EFI_DRIVER_ENTRY_POINT(InitFunction)
+
+ #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \
+ (_if)->LoadInternal(type, name, entry)
+
+#endif // EFI_FW_NT
+
+#ifdef __FreeBSD__
+#define INTERFACE_DECL(x) struct x
+#else
+//
+// Some compilers don't support the forward reference construct:
+// typedef struct XXXXX
+//
+// The following macro provide a workaround for such cases.
+//
+#ifdef NO_INTERFACE_DECL
+#define INTERFACE_DECL(x)
+#else
+#define INTERFACE_DECL(x) typedef struct x
+#endif
+#endif /* __FreeBSD__ */
+
+#if _MSC_EXTENSIONS
+#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP
+#endif
+
diff --git a/sys/boot/efi/include/amd64/pe.h b/sys/boot/efi/include/amd64/pe.h
new file mode 100644
index 0000000..1120464
--- /dev/null
+++ b/sys/boot/efi/include/amd64/pe.h
@@ -0,0 +1,592 @@
+/* $FreeBSD$ */
+/*
+ PE32+ header file
+ */
+#ifndef _PE_H
+#define _PE_H
+
+#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
+#define IMAGE_OS2_SIGNATURE 0x454E // NE
+#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE
+#define IMAGE_NT_SIGNATURE 0x00004550 // PE00
+#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED
+
+
+typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
+ UINT16 e_magic; // Magic number
+ UINT16 e_cblp; // Bytes on last page of file
+ UINT16 e_cp; // Pages in file
+ UINT16 e_crlc; // Relocations
+ UINT16 e_cparhdr; // Size of header in paragraphs
+ UINT16 e_minalloc; // Minimum extra paragraphs needed
+ UINT16 e_maxalloc; // Maximum extra paragraphs needed
+ UINT16 e_ss; // Initial (relative) SS value
+ UINT16 e_sp; // Initial SP value
+ UINT16 e_csum; // Checksum
+ UINT16 e_ip; // Initial IP value
+ UINT16 e_cs; // Initial (relative) CS value
+ UINT16 e_lfarlc; // File address of relocation table
+ UINT16 e_ovno; // Overlay number
+ UINT16 e_res[4]; // Reserved words
+ UINT16 e_oemid; // OEM identifier (for e_oeminfo)
+ UINT16 e_oeminfo; // OEM information; e_oemid specific
+ UINT16 e_res2[10]; // Reserved words
+ UINT32 e_lfanew; // File address of new exe header
+ } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
+
+typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header
+ UINT16 ne_magic; // Magic number
+ UINT8 ne_ver; // Version number
+ UINT8 ne_rev; // Revision number
+ UINT16 ne_enttab; // Offset of Entry Table
+ UINT16 ne_cbenttab; // Number of bytes in Entry Table
+ UINT32 ne_crc; // Checksum of whole file
+ UINT16 ne_flags; // Flag UINT16
+ UINT16 ne_autodata; // Automatic data segment number
+ UINT16 ne_heap; // Initial heap allocation
+ UINT16 ne_stack; // Initial stack allocation
+ UINT32 ne_csip; // Initial CS:IP setting
+ UINT32 ne_sssp; // Initial SS:SP setting
+ UINT16 ne_cseg; // Count of file segments
+ UINT16 ne_cmod; // Entries in Module Reference Table
+ UINT16 ne_cbnrestab; // Size of non-resident name table
+ UINT16 ne_segtab; // Offset of Segment Table
+ UINT16 ne_rsrctab; // Offset of Resource Table
+ UINT16 ne_restab; // Offset of resident name table
+ UINT16 ne_modtab; // Offset of Module Reference Table
+ UINT16 ne_imptab; // Offset of Imported Names Table
+ UINT32 ne_nrestab; // Offset of Non-resident Names Table
+ UINT16 ne_cmovent; // Count of movable entries
+ UINT16 ne_align; // Segment alignment shift count
+ UINT16 ne_cres; // Count of resource segments
+ UINT8 ne_exetyp; // Target Operating system
+ UINT8 ne_flagsothers; // Other .EXE flags
+ UINT16 ne_pretthunks; // offset to return thunks
+ UINT16 ne_psegrefbytes; // offset to segment ref. bytes
+ UINT16 ne_swaparea; // Minimum code swap area size
+ UINT16 ne_expver; // Expected Windows version number
+ } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER;
+
+//
+// File header format.
+//
+
+typedef struct _IMAGE_FILE_HEADER {
+ UINT16 Machine;
+ UINT16 NumberOfSections;
+ UINT32 TimeDateStamp;
+ UINT32 PointerToSymbolTable;
+ UINT32 NumberOfSymbols;
+ UINT16 SizeOfOptionalHeader;
+ UINT16 Characteristics;
+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
+
+#define IMAGE_SIZEOF_FILE_HEADER 20
+
+#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
+#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
+#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
+#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
+#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
+#define IMAGE_FILE_SYSTEM 0x1000 // System File.
+#define IMAGE_FILE_DLL 0x2000 // File is a DLL.
+#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
+
+#define IMAGE_FILE_MACHINE_UNKNOWN 0
+#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386.
+#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian
+#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian
+#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP
+#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian
+#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine
+//
+// Directory format.
+//
+
+typedef struct _IMAGE_DATA_DIRECTORY {
+ UINT32 VirtualAddress;
+ UINT32 Size;
+} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+
+//
+// Optional header format.
+//
+
+typedef struct _IMAGE_OPTIONAL_HEADER {
+ //
+ // Standard fields.
+ //
+
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+
+ //
+ // NT additional fields.
+ //
+
+ UINT32 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Reserved1;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT32 SizeOfStackReserve;
+ UINT32 SizeOfStackCommit;
+ UINT32 SizeOfHeapReserve;
+ UINT32 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
+
+typedef struct _IMAGE_ROM_OPTIONAL_HEADER {
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ UINT32 BaseOfBss;
+ UINT32 GprMask;
+ UINT32 CprMask[4];
+ UINT32 GpValue;
+} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER;
+
+#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56
+#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28
+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224
+
+#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
+#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
+
+typedef struct _IMAGE_NT_HEADERS {
+ UINT32 Signature;
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_OPTIONAL_HEADER OptionalHeader;
+} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
+
+typedef struct _IMAGE_ROM_HEADERS {
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;
+} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS;
+
+#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \
+ ((UINT32)ntheader + \
+ FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \
+ ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \
+ ))
+
+
+// Subsystem Values
+
+#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem.
+#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem.
+#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
+#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
+#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem.
+#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem.
+
+
+// Directory Entries
+
+#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
+#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
+#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
+#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
+#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
+#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String
+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP)
+#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
+
+//
+// Section header format.
+//
+
+#define IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct _IMAGE_SECTION_HEADER {
+ UINT8 Name[IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ UINT32 PhysicalAddress;
+ UINT32 VirtualSize;
+ } Misc;
+ UINT32 VirtualAddress;
+ UINT32 SizeOfRawData;
+ UINT32 PointerToRawData;
+ UINT32 PointerToRelocations;
+ UINT32 PointerToLinenumbers;
+ UINT16 NumberOfRelocations;
+ UINT16 NumberOfLinenumbers;
+ UINT32 Characteristics;
+} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
+
+#define IMAGE_SIZEOF_SECTION_HEADER 40
+
+#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
+
+#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code.
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data.
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data.
+
+#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
+#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.
+#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
+#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat.
+
+#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 //
+#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 //
+#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 //
+#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 //
+#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified.
+#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 //
+#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 //
+
+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded.
+#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable.
+#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable.
+#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.
+#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.
+#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.
+
+//
+// Symbol format.
+//
+
+
+#define IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Section values.
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+
+#define IMAGE_SYM_UNDEFINED (UINT16)0 // Symbol is undefined or is common.
+#define IMAGE_SYM_ABSOLUTE (UINT16)-1 // Symbol is an absolute value.
+#define IMAGE_SYM_DEBUG (UINT16)-2 // Symbol is a special debug item.
+
+//
+// Type (fundamental) values.
+//
+
+#define IMAGE_SYM_TYPE_NULL 0 // no type.
+#define IMAGE_SYM_TYPE_VOID 1 //
+#define IMAGE_SYM_TYPE_CHAR 2 // type character.
+#define IMAGE_SYM_TYPE_SHORT 3 // type short integer.
+#define IMAGE_SYM_TYPE_INT 4 //
+#define IMAGE_SYM_TYPE_LONG 5 //
+#define IMAGE_SYM_TYPE_FLOAT 6 //
+#define IMAGE_SYM_TYPE_DOUBLE 7 //
+#define IMAGE_SYM_TYPE_STRUCT 8 //
+#define IMAGE_SYM_TYPE_UNION 9 //
+#define IMAGE_SYM_TYPE_ENUM 10 // enumeration.
+#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration.
+#define IMAGE_SYM_TYPE_BYTE 12 //
+#define IMAGE_SYM_TYPE_WORD 13 //
+#define IMAGE_SYM_TYPE_UINT 14 //
+#define IMAGE_SYM_TYPE_DWORD 15 //
+
+//
+// Type (derived) values.
+//
+
+#define IMAGE_SYM_DTYPE_NULL 0 // no derived type.
+#define IMAGE_SYM_DTYPE_POINTER 1 // pointer.
+#define IMAGE_SYM_DTYPE_FUNCTION 2 // function.
+#define IMAGE_SYM_DTYPE_ARRAY 3 // array.
+
+//
+// Storage classes.
+//
+
+#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1
+#define IMAGE_SYM_CLASS_NULL 0
+#define IMAGE_SYM_CLASS_AUTOMATIC 1
+#define IMAGE_SYM_CLASS_EXTERNAL 2
+#define IMAGE_SYM_CLASS_STATIC 3
+#define IMAGE_SYM_CLASS_REGISTER 4
+#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define IMAGE_SYM_CLASS_LABEL 6
+#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define IMAGE_SYM_CLASS_ARGUMENT 9
+#define IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define IMAGE_SYM_CLASS_UNION_TAG 12
+#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define IMAGE_SYM_CLASS_ENUM_TAG 15
+#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define IMAGE_SYM_CLASS_BIT_FIELD 18
+#define IMAGE_SYM_CLASS_BLOCK 100
+#define IMAGE_SYM_CLASS_FUNCTION 101
+#define IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define IMAGE_SYM_CLASS_FILE 103
+// new
+#define IMAGE_SYM_CLASS_SECTION 104
+#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+// type packing constants
+
+#define N_BTMASK 017
+#define N_TMASK 060
+#define N_TMASK1 0300
+#define N_TMASK2 0360
+#define N_BTSHFT 4
+#define N_TSHIFT 2
+
+// MACROS
+
+//
+// Communal selection types.
+//
+
+#define IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define IMAGE_COMDAT_SELECT_ANY 2
+#define IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+
+#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
+#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
+#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
+
+
+//
+// Relocation format.
+//
+
+typedef struct _IMAGE_RELOCATION {
+ UINT32 VirtualAddress;
+ UINT32 SymbolTableIndex;
+ UINT16 Type;
+} IMAGE_RELOCATION;
+
+#define IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+
+#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary
+#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address
+#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address
+#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address
+#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included
+#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
+#define IMAGE_REL_I386_SECTION 012
+#define IMAGE_REL_I386_SECREL 013
+#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address
+
+//
+// MIPS relocation types.
+//
+
+#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary
+#define IMAGE_REL_MIPS_REFHALF 01
+#define IMAGE_REL_MIPS_REFWORD 02
+#define IMAGE_REL_MIPS_JMPADDR 03
+#define IMAGE_REL_MIPS_REFHI 04
+#define IMAGE_REL_MIPS_REFLO 05
+#define IMAGE_REL_MIPS_GPREL 06
+#define IMAGE_REL_MIPS_LITERAL 07
+#define IMAGE_REL_MIPS_SECTION 012
+#define IMAGE_REL_MIPS_SECREL 013
+#define IMAGE_REL_MIPS_REFWORDNB 042
+#define IMAGE_REL_MIPS_PAIR 045
+
+//
+// Alpha Relocation types.
+//
+
+#define IMAGE_REL_ALPHA_ABSOLUTE 0x0
+#define IMAGE_REL_ALPHA_REFLONG 0x1
+#define IMAGE_REL_ALPHA_REFQUAD 0x2
+#define IMAGE_REL_ALPHA_GPREL32 0x3
+#define IMAGE_REL_ALPHA_LITERAL 0x4
+#define IMAGE_REL_ALPHA_LITUSE 0x5
+#define IMAGE_REL_ALPHA_GPDISP 0x6
+#define IMAGE_REL_ALPHA_BRADDR 0x7
+#define IMAGE_REL_ALPHA_HINT 0x8
+#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9
+#define IMAGE_REL_ALPHA_REFHI 0xA
+#define IMAGE_REL_ALPHA_REFLO 0xB
+#define IMAGE_REL_ALPHA_PAIR 0xC
+#define IMAGE_REL_ALPHA_MATCH 0xD
+#define IMAGE_REL_ALPHA_SECTION 0xE
+#define IMAGE_REL_ALPHA_SECREL 0xF
+#define IMAGE_REL_ALPHA_REFLONGNB 0x10
+
+//
+// IBM PowerPC relocation types.
+//
+
+#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP
+#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address
+#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address
+#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute)
+#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address
+#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword)
+#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative)
+#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative)
+#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base
+#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword)
+
+#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base
+#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr)
+#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number
+#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code
+#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction
+
+#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type
+
+// Flag bits in IMAGE_RELOCATION.TYPE
+
+#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it
+#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken
+#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken
+#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc)
+
+//
+// Based relocation format.
+//
+
+typedef struct _IMAGE_BASE_RELOCATION {
+ UINT32 VirtualAddress;
+ UINT32 SizeOfBlock;
+// UINT16 TypeOffset[1];
+} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;
+
+#define IMAGE_SIZEOF_BASE_RELOCATION 8
+
+//
+// Based relocation types.
+//
+
+#define IMAGE_REL_BASED_ABSOLUTE 0
+#define IMAGE_REL_BASED_HIGH 1
+#define IMAGE_REL_BASED_LOW 2
+#define IMAGE_REL_BASED_HIGHLOW 3
+#define IMAGE_REL_BASED_HIGHADJ 4
+#define IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define IMAGE_REL_BASED_IA64_IMM64 9
+#define IMAGE_REL_BASED_DIR64 10
+
+//
+// Line number format.
+//
+
+typedef struct _IMAGE_LINENUMBER {
+ union {
+ UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.
+ UINT32 VirtualAddress; // Virtual address of line number.
+ } Type;
+ UINT16 Linenumber; // Line number.
+} IMAGE_LINENUMBER;
+
+#define IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+
+#define IMAGE_ARCHIVE_START_SIZE 8
+#define IMAGE_ARCHIVE_START "!<arch>\n"
+#define IMAGE_ARCHIVE_END "`\n"
+#define IMAGE_ARCHIVE_PAD "\n"
+#define IMAGE_ARCHIVE_LINKER_MEMBER "/ "
+#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
+
+typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER {
+ UINT8 Name[16]; // File member name - `/' terminated.
+ UINT8 Date[12]; // File member date - decimal.
+ UINT8 UserID[6]; // File member user id - decimal.
+ UINT8 GroupID[6]; // File member group id - decimal.
+ UINT8 Mode[8]; // File member mode - octal.
+ UINT8 Size[10]; // File member size - decimal.
+ UINT8 EndHeader[2]; // String to end header.
+} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER;
+
+#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+//
+// DLL support.
+//
+
+//
+// Export Format
+//
+
+typedef struct _IMAGE_EXPORT_DIRECTORY {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Name;
+ UINT32 Base;
+ UINT32 NumberOfFunctions;
+ UINT32 NumberOfNames;
+ UINT32 *AddressOfFunctions;
+ UINT32 *AddressOfNames;
+ UINT32 *AddressOfNameOrdinals;
+} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
+
+//
+// Import Format
+//
+
+typedef struct _IMAGE_IMPORT_BY_NAME {
+ UINT16 Hint;
+ UINT8 Name[1];
+} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
+
+typedef struct _IMAGE_THUNK_DATA {
+ union {
+ UINT32 Function;
+ UINT32 Ordinal;
+ PIMAGE_IMPORT_BY_NAME AddressOfData;
+ } u1;
+} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;
+
+#define IMAGE_ORDINAL_FLAG 0x80000000
+#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0)
+#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+typedef struct _IMAGE_IMPORT_DESCRIPTOR {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT32 ForwarderChain;
+ UINT32 Name;
+ PIMAGE_THUNK_DATA FirstThunk;
+} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
+
+#endif
diff --git a/sys/boot/efi/include/efi.h b/sys/boot/efi/include/efi.h
index 4869e38..513ab9d 100644
--- a/sys/boot/efi/include/efi.h
+++ b/sys/boot/efi/include/efi.h
@@ -52,6 +52,7 @@ Revision History
#include "efiapi.h"
#include "efifs.h"
#include "efierr.h"
+#include "efigop.h"
#define EFI_STRINGIZE(a) #a
#define EFI_PROTOCOL_DEFINITION(a) EFI_STRINGIZE(Protocol/a/a.h)
diff --git a/sys/boot/efi/include/efigop.h b/sys/boot/efi/include/efigop.h
new file mode 100644
index 0000000..dfc4bba
--- /dev/null
+++ b/sys/boot/efi/include/efigop.h
@@ -0,0 +1,122 @@
+/* $FreeBSD$ */
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ efigop.h
+
+Abstract:
+ Info about framebuffers
+
+
+
+
+Revision History
+
+--*/
+
+#ifndef _EFIGOP_H
+#define _EFIGOP_H
+
+#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
+ { 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, \
+ 0x51, 0x6a }
+
+INTERFACE_DECL(_EFI_GRAPHICS_OUTPUT);
+
+typedef struct {
+ UINT32 RedMask;
+ UINT32 GreenMask;
+ UINT32 BlueMask;
+ UINT32 ReservedMask;
+} EFI_PIXEL_BITMASK;
+
+typedef enum {
+ PixelRedGreenBlueReserved8BitPerColor,
+ PixelBlueGreenRedReserved8BitPerColor,
+ PixelBitMask,
+ PixelBltOnly,
+ PixelFormatMax,
+} EFI_GRAPHICS_PIXEL_FORMAT;
+
+typedef struct {
+ UINT32 Version;
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
+ EFI_PIXEL_BITMASK PixelInformation;
+ UINT32 PixelsPerScanLine;
+} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
+
+typedef struct {
+ UINT32 MaxMode;
+ UINT32 Mode;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ UINTN SizeOfInfo;
+ EFI_PHYSICAL_ADDRESS FrameBufferBase;
+ UINTN FrameBufferSize;
+} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) (
+ IN struct _EFI_GRAPHICS_OUTPUT *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) (
+ IN struct _EFI_GRAPHICS_OUTPUT *This,
+ IN UINT32 ModeNumber
+ );
+
+typedef struct {
+ UINT8 Blue;
+ UINT8 Green;
+ UINT8 Red;
+ UINT8 Reserved;
+} EFI_GRAPHICS_OUTPUT_BLT_PIXEL;
+
+typedef enum {
+ EfiBltVideoFill,
+ EfiBltVideoToBltBuffer,
+ EfiBltBufferToVideo,
+ EfiBltVideoToVideo,
+ EfiGraphcisOutputBltOperationMax,
+} EFI_GRAPHICS_OUTPUT_BLT_OPERATION;
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) (
+ IN struct _EFI_GRAPHICS_OUTPUT *This,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ );
+
+typedef struct _EFI_GRAPHICS_OUTPUT {
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
+} EFI_GRAPHICS_OUTPUT;
+
+#endif /* _EFIGOP_H */
diff --git a/sys/boot/efi/include/efilib.h b/sys/boot/efi/include/efilib.h
index cf825a6..ef03028 100644
--- a/sys/boot/efi/include/efilib.h
+++ b/sys/boot/efi/include/efilib.h
@@ -41,7 +41,7 @@ extern struct netif_driver efinetif;
void *efi_get_table(EFI_GUID *tbl);
void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
-int efi_register_handles(struct devsw *, EFI_HANDLE *, int);
+int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
EFI_HANDLE efi_find_handle(struct devsw *, int);
int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *);
diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile
index beb9269..60cb43f 100644
--- a/sys/boot/efi/libefi/Makefile
+++ b/sys/boot/efi/libefi/Makefile
@@ -6,11 +6,18 @@ INTERNALLIB=
SRCS= delay.c efi_console.c efinet.c efipart.c errno.c handles.c \
libefi.c time.c
+.if ${MACHINE_ARCH} == "amd64"
+CFLAGS+= -fPIC
+.endif
CFLAGS+= -I${.CURDIR}/../include
-CFLAGS+= -I${.CURDIR}/../include/${MACHINE_CPUARCH:S/amd64/i386/}
+CFLAGS+= -I${.CURDIR}/../include/${MACHINE_CPUARCH}
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand
# Pick up the bootstrap header for some interface items
CFLAGS+= -I${.CURDIR}/../../common
+
+# Suppress warning from clang for FreeBSD %b and %D formats
+CFLAGS+= -fformat-extensions
+
.include <bsd.lib.mk>
diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c
index 5b3e401..3f08ed2 100644
--- a/sys/boot/efi/libefi/efinet.c
+++ b/sys/boot/efi/libefi/efinet.c
@@ -274,7 +274,7 @@ efinet_dev_init()
if (EFI_ERROR(status))
return (efi_status_to_errno(status));
nifs = sz / sizeof(EFI_HANDLE);
- err = efi_register_handles(&efinet_dev, handles, nifs);
+ err = efi_register_handles(&efinet_dev, handles, NULL, nifs);
free(handles);
if (err != 0)
return (err);
diff --git a/sys/boot/efi/libefi/efipart.c b/sys/boot/efi/libefi/efipart.c
index 264a2a4..13dc0ac 100644
--- a/sys/boot/efi/libefi/efipart.c
+++ b/sys/boot/efi/libefi/efipart.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <efiprot.h>
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
+static EFI_GUID devpath_guid = DEVICE_PATH_PROTOCOL;
static int efipart_init(void);
static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *);
@@ -62,9 +63,11 @@ static int
efipart_init(void)
{
EFI_BLOCK_IO *blkio;
- EFI_HANDLE *hin, *hout;
+ EFI_DEVICE_PATH *devpath, *node;
+ EFI_HANDLE *hin, *hout, *aliases, handle;
EFI_STATUS status;
UINTN sz;
+ CHAR16 *path;
u_int n, nin, nout;
int err;
@@ -72,7 +75,7 @@ efipart_init(void)
hin = NULL;
status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
if (status == EFI_BUFFER_TOO_SMALL) {
- hin = (EFI_HANDLE *)malloc(sz * 2);
+ hin = (EFI_HANDLE *)malloc(sz * 3);
status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
hin);
if (EFI_ERROR(status))
@@ -84,19 +87,50 @@ efipart_init(void)
/* Filter handles to only include FreeBSD partitions. */
nin = sz / sizeof(EFI_HANDLE);
hout = hin + nin;
+ aliases = hout + nin;
nout = 0;
+ bzero(aliases, nin * sizeof(EFI_HANDLE));
+
for (n = 0; n < nin; n++) {
- status = BS->HandleProtocol(hin[n], &blkio_guid, &blkio);
+ status = BS->HandleProtocol(hin[n], &devpath_guid,
+ (void **)&devpath);
+ if (EFI_ERROR(status)) {
+ continue;
+ }
+ node = devpath;
+ while (!IsDevicePathEnd(NextDevicePathNode(node)))
+ node = NextDevicePathNode(node);
+ status = BS->HandleProtocol(hin[n], &blkio_guid,
+ (void**)&blkio);
if (EFI_ERROR(status))
continue;
if (!blkio->Media->LogicalPartition)
continue;
- hout[nout] = hin[n];
+
+ /*
+ * If we come across a logical partition of subtype CDROM
+ * it doesn't refer to the CD filesystem itself, but rather
+ * to any usable El Torito boot image on it. In this case
+ * we try to find the parent device and add that instead as
+ * that will be the CD filesystem.
+ */
+ if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(node) == MEDIA_CDROM_DP) {
+ node->Type = END_DEVICE_PATH_TYPE;
+ node->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ status = BS->LocateDevicePath(&blkio_guid, &devpath,
+ &handle);
+ if (EFI_ERROR(status))
+ continue;
+ hout[nout] = handle;
+ aliases[nout] = hin[n];
+ } else
+ hout[nout] = hin[n];
nout++;
}
- err = efi_register_handles(&efipart_dev, hout, nout);
+ err = efi_register_handles(&efipart_dev, hout, aliases, nout);
free(hin);
return (err);
}
@@ -115,7 +149,7 @@ efipart_print(int verbose)
sprintf(line, " %s%d:", efipart_dev.dv_name, unit);
pager_output(line);
- status = BS->HandleProtocol(h, &blkio_guid, &blkio);
+ status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
if (!EFI_ERROR(status)) {
sprintf(line, " %llu blocks",
(unsigned long long)(blkio->Media->LastBlock + 1));
@@ -144,7 +178,7 @@ efipart_open(struct open_file *f, ...)
if (h == NULL)
return (EINVAL);
- status = BS->HandleProtocol(h, &blkio_guid, &blkio);
+ status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
if (EFI_ERROR(status))
return (efi_status_to_errno(status));
diff --git a/sys/boot/efi/libefi/handles.c b/sys/boot/efi/libefi/handles.c
index 7c78a15..b15c0a5 100644
--- a/sys/boot/efi/libefi/handles.c
+++ b/sys/boot/efi/libefi/handles.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
struct entry {
EFI_HANDLE handle;
+ EFI_HANDLE alias;
struct devsw *dev;
int unit;
};
@@ -40,7 +41,8 @@ struct entry *entry;
int nentries;
int
-efi_register_handles(struct devsw *sw, EFI_HANDLE *handles, int count)
+efi_register_handles(struct devsw *sw, EFI_HANDLE *handles,
+ EFI_HANDLE *aliases, int count)
{
size_t sz;
int idx, unit;
@@ -51,6 +53,10 @@ efi_register_handles(struct devsw *sw, EFI_HANDLE *handles, int count)
entry = (entry == NULL) ? malloc(sz) : realloc(entry, sz);
for (unit = 0; idx < nentries; idx++, unit++) {
entry[idx].handle = handles[unit];
+ if (aliases != NULL)
+ entry[idx].alias = aliases[unit];
+ else
+ entry[idx].alias = NULL;
entry[idx].dev = sw;
entry[idx].unit = unit;
}
@@ -78,7 +84,7 @@ efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit)
int idx;
for (idx = 0; idx < nentries; idx++) {
- if (entry[idx].handle != h)
+ if (entry[idx].handle != h && entry[idx].alias != h)
continue;
if (dev != NULL)
*dev = entry[idx].dev;
diff --git a/sys/boot/ficl/Makefile b/sys/boot/ficl/Makefile
index 9a3e399..6fad54f 100644
--- a/sys/boot/ficl/Makefile
+++ b/sys/boot/ficl/Makefile
@@ -3,7 +3,7 @@
FICLDIR?= ${.CURDIR}
-.if !defined(FICL64)
+.if defined(FICL32)
.PATH: ${FICLDIR}/${MACHINE_CPUARCH:S/amd64/i386/}
.else
.PATH: ${FICLDIR}/${MACHINE_CPUARCH}
@@ -14,11 +14,12 @@ BASE_SRCS= dict.c ficl.c fileaccess.c float.c loader.c math64.c \
SRCS= ${BASE_SRCS} sysdep.c softcore.c
CLEANFILES= softcore.c testmain testmain.o
CFLAGS+= -ffreestanding
-.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
-.if !defined(FICL64)
+.if ${MACHINE_CPUARCH} == "i386" || \
+ (${MACHINE_CPUARCH} == "amd64" && defined(FICL32))
CFLAGS+= -march=i386
CFLAGS.gcc+= -mpreferred-stack-boundary=2
.endif
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
CFLAGS+= -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
.endif
.if ${MACHINE_CPUARCH} == "powerpc" || ${MACHINE_CPUARCH} == "arm"
@@ -48,22 +49,32 @@ SOFTWORDS= softcore.fr jhlocal.fr marker.fr freebsd.fr ficllocal.fr \
# Optional OO extension softwords
#SOFTWORDS+= oo.fr classes.fr
-.if ${MACHINE_CPUARCH} == "amd64" && !defined(FICL64)
+.if ${MACHINE_CPUARCH} == "amd64"
+.if defined(FICL32)
CFLAGS+= -m32 -I.
+.else
+CFLAGS+= -fPIC
+.endif
.endif
.if ${MACHINE_ARCH} == "powerpc64"
CFLAGS+= -m32 -mcpu=powerpc -I.
.endif
-CFLAGS+= -I${FICLDIR} -I${FICLDIR}/${MACHINE_CPUARCH:S/amd64/i386/} \
+.if ${MACHINE_CPUARCH} == "amd64" && defined(FICL32)
+FICL_CPUARCH= i386
+.else
+FICL_CPUARCH= ${MACHINE_CPUARCH}
+.endif
+
+CFLAGS+= -I${FICLDIR} -I${FICLDIR}/${FICL_CPUARCH} \
-I${FICLDIR}/../common
softcore.c: ${SOFTWORDS} softcore.awk
(cd ${FICLDIR}/softwords; cat ${SOFTWORDS} \
| awk -f softcore.awk -v datestamp="`LC_ALL=C date`") > ${.TARGET}
-.if ${MACHINE_CPUARCH} == "amd64"
+.if ${MACHINE_CPUARCH} == "amd64" && defined(FICL32)
.if !exists(machine)
${SRCS:M*.c:R:S/$/.o/g}: machine
diff --git a/sys/boot/ficl/tools.c b/sys/boot/ficl/tools.c
index 7201663..db1e948 100644
--- a/sys/boot/ficl/tools.c
+++ b/sys/boot/ficl/tools.c
@@ -201,7 +201,7 @@ static void seeColon(FICL_VM *pVM, CELL *pc)
*cp++ = '>';
else
*cp++ = ' ';
- cp += sprintf(cp, "%3d ", pc-param0);
+ cp += sprintf(cp, "%3d ", (int)(pc-param0));
if (isAFiclWord(pd, pFW))
{
@@ -239,40 +239,40 @@ static void seeColon(FICL_VM *pVM, CELL *pc)
case IF:
c = *++pc;
if (c.i > 0)
- sprintf(cp, "if / while (branch %d)", pc+c.i-param0);
+ sprintf(cp, "if / while (branch %d)", (int)(pc+c.i-param0));
else
- sprintf(cp, "until (branch %d)", pc+c.i-param0);
+ sprintf(cp, "until (branch %d)", (int)(pc+c.i-param0));
break;
case BRANCH:
c = *++pc;
if (c.i == 0)
- sprintf(cp, "repeat (branch %d)", pc+c.i-param0);
+ sprintf(cp, "repeat (branch %d)", (int)(pc+c.i-param0));
else if (c.i == 1)
- sprintf(cp, "else (branch %d)", pc+c.i-param0);
+ sprintf(cp, "else (branch %d)", (int)(pc+c.i-param0));
else
- sprintf(cp, "endof (branch %d)", pc+c.i-param0);
+ sprintf(cp, "endof (branch %d)", (int)(pc+c.i-param0));
break;
case OF:
c = *++pc;
- sprintf(cp, "of (branch %d)", pc+c.i-param0);
+ sprintf(cp, "of (branch %d)", (int)(pc+c.i-param0));
break;
case QDO:
c = *++pc;
- sprintf(cp, "?do (leave %d)", (CELL *)c.p-param0);
+ sprintf(cp, "?do (leave %d)", (int)((CELL *)c.p-param0));
break;
case DO:
c = *++pc;
- sprintf(cp, "do (leave %d)", (CELL *)c.p-param0);
+ sprintf(cp, "do (leave %d)", (int)((CELL *)c.p-param0));
break;
case LOOP:
c = *++pc;
- sprintf(cp, "loop (branch %d)", pc+c.i-param0);
+ sprintf(cp, "loop (branch %d)", (int)(pc+c.i-param0));
break;
case PLOOP:
c = *++pc;
- sprintf(cp, "+loop (branch %d)", pc+c.i-param0);
+ sprintf(cp, "+loop (branch %d)", (int)(pc+c.i-param0));
break;
default:
sprintf(cp, "%.*s", pFW->nName, pFW->name);
diff --git a/sys/boot/ficl/words.c b/sys/boot/ficl/words.c
index 48e073d..c32e352 100644
--- a/sys/boot/ficl/words.c
+++ b/sys/boot/ficl/words.c
@@ -2567,7 +2567,7 @@ static void setObjectFlag(FICL_VM *pVM)
static void isObject(FICL_VM *pVM)
{
- int flag;
+ FICL_INT flag;
FICL_WORD *pFW = (FICL_WORD *)stackPopPtr(pVM->pStack);
flag = ((pFW != NULL) && (pFW->flags & FW_ISOBJECT)) ? FICL_TRUE : FICL_FALSE;
diff --git a/sys/boot/ficl64/Makefile b/sys/boot/ficl32/Makefile
index 4c6777b..57c44ca 100644
--- a/sys/boot/ficl64/Makefile
+++ b/sys/boot/ficl32/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-FICL64=
+FICL32=
FICLDIR= ${.CURDIR}/../ficl
.PATH: ${FICLDIR}
diff --git a/sys/boot/forth/beastie.4th b/sys/boot/forth/beastie.4th
index 7a2cbb0..2fc073d 100644
--- a/sys/boot/forth/beastie.4th
+++ b/sys/boot/forth/beastie.4th
@@ -242,6 +242,11 @@ variable logoY
;
: beastie-start ( -- ) \ starts the menu
+ s" console" getenv dup -1 <> if
+ s" efi" 2swap contains? if
+ s" set beastie_disable=YES" evaluate
+ then
+ else drop then
s" beastie_disable" getenv
dup -1 <> if
s" YES" compare-insensitive 0= if
diff --git a/sys/boot/forth/beastie.4th.8 b/sys/boot/forth/beastie.4th.8
index 30d29b2..534a60c 100644
--- a/sys/boot/forth/beastie.4th.8
+++ b/sys/boot/forth/beastie.4th.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 16, 2011
+.Dd April 27, 2014
.Dt BEASTIE.4TH 8
.Os
.Sh NAME
@@ -119,6 +119,8 @@ Sets the desired row position of the logo. Default is 4.
If set to
.Dq YES ,
the beastie boot menu will be skipped.
+The beastie boot menu is always skipped if booting UEFI or running non-x86
+hardware.
.It Va loader_delay
If set to a number higher than zero, introduces a delay before starting the
beastie boot menu. During the delay the user can press either Ctrl-C to skip
diff --git a/sys/boot/forth/loader.conf.5 b/sys/boot/forth/loader.conf.5
index d638909..3c1ce1d 100644
--- a/sys/boot/forth/loader.conf.5
+++ b/sys/boot/forth/loader.conf.5
@@ -23,7 +23,7 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd October 18, 2013
+.Dd April 27, 2014
.Dt LOADER.CONF 5
.Os
.Sh NAME
@@ -236,6 +236,8 @@ be displayed.
If set to
.Dq YES ,
the beastie boot menu will be skipped.
+The beastie boot menu is always skipped if booting UEFI or running non-x86
+hardware.
.It Va loader_logo Pq Dq Li orbbw
Selects a desired logo in the beastie boot menu.
Possible values are:
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
index 20ed02c..1c4f049 100644
--- a/sys/boot/i386/libi386/Makefile
+++ b/sys/boot/i386/libi386/Makefile
@@ -52,6 +52,9 @@ CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../common \
# the location of libstand
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
+# Suppress warning from clang for FreeBSD %b and %D formats
+CFLAGS+= -fformat-extensions
+
.if ${MACHINE_CPUARCH} == "amd64"
CLEANFILES+= machine
machine:
diff --git a/sys/boot/i386/loader/Makefile b/sys/boot/i386/loader/Makefile
index b0a129e..b98a725 100644
--- a/sys/boot/i386/loader/Makefile
+++ b/sys/boot/i386/loader/Makefile
@@ -41,8 +41,12 @@ HAVE_ISABUS= yes
# Enable BootForth
BOOT_FORTH= yes
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/i386
+.if ${MACHINE_CPUARCH} == "amd64"
+LIBFICL= ${.OBJDIR}/../../ficl32/libficl.a
+.else
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
.endif
+.endif
.if defined(LOADER_BZIP2_SUPPORT)
CFLAGS+= -DLOADER_BZIP2_SUPPORT
OpenPOWER on IntegriCloud