Support UEFI booting on amd64 via loader.efi

This is largely the work from the projects/uefi branch, with some
additional refinements.  This is derived from (and replaces) the
original i386 efi implementation; i386 support will be restored later.

Specific revisions of note from projects/uefi:

r247380:

  Adjust our load device when we boot from CD under UEFI.

  The process for booting from a CD under UEFI involves adding a FAT
  filesystem containing your loader code as an El Torito boot image.
  When UEFI detects this, it provides a block IO instance that points at
  the FAT filesystem as a child of the device that represents the CD
  itself. The problem being that the CD device is flagged as a "raw
  device" while the boot image is flagged as a "logical partition". The
  existing EFI partition code only looks for logical partitions and so
  the CD filesystem was rendered invisible.

  To fix this, check the type of each block IO device. If it's found to
  be a CD, and thus an El Torito boot image, look up its parent device
  and add that instead so that the loader will then load the kernel from
  the CD filesystem.  This is done by using the handle for the boot
  filesystem as an alias.

  Something similar to this will be required for booting from other
  media as well as the loader will live in the EFI system partition, not
  on the partition containing the kernel.

r246231:

  Add necessary code to hand off from loader to an amd64 kernel.

r246335:

  Grab the EFI memory map and store it as module metadata on the kernel.

  This is the same approach used to provide the BIOS SMAP to the kernel.

r246336:

  Pass the ACPI table metadata via hints so the kernel ACPI code can
  find them.

r246608:

  Rework copy routines to ensure we always use memory allocated via EFI.

  The previous code assumed it could copy wherever it liked. This is not
  the case. The approach taken by this code is pretty ham-fisted in that
  it simply allocates a large (32MB) buffer area and stages into that,
  then copies the whole area into place when it's time to execute. A more
  elegant solution could be used but this works for now.

r247214:

  Fix a number of problems preventing proper handover to the kernel.

  There were two issues at play here. Firstly, there was nothing
  preventing UEFI from placing the loader code above 1GB in RAM. This
  meant that when we switched in the page tables the kernel expects to
  be running on, we are suddenly unmapped and things no longer work. We
  solve this by making our trampoline code not dependent on being at any
  given position and simply copying it to a "safe" location before
  calling it.

  Secondly, UEFI could allocate our stack wherever it wants. As it
  happened on my PC, that was right where I was copying the kernel to.
  This did not cause happiness. The solution to this was to also switch
  to a temporary stack in a safe location before performing the final
  copy of the loaded kernel.

r246231:

  Add necessary code to hand off from loader to an amd64 kernel.

r246335:

  Grab the EFI memory map and store it as module metadata on the kernel.

  This is the same approach used to provide the BIOS SMAP to the kernel.

r246336:

  Pass the ACPI table metadata via hints so the kernel ACPI code can
  find them.

r246608:

  Rework copy routines to ensure we always use memory allocated via EFI.

  The previous code assumed it could copy wherever it liked. This is not
  the case. The approach taken by this code is pretty ham-fisted in that
  it simply allocates a large (32MB) buffer area and stages into that,
  then copies the whole area into place when it's time to execute. A more
  elegant solution could be used but this works for now.

r247214:

  Fix a number of problems preventing proper handover to the kernel.

  There were two issues at play here. Firstly, there was nothing
  preventing UEFI from placing the loader code above 1GB in RAM. This
  meant that when we switched in the page tables the kernel expects to
  be running on, we are suddenly unmapped and things no longer work. We
  solve this by making our trampoline code not dependent on being at any
  given position and simply copying it to a "safe" location before
  calling it.

  Secondly, UEFI could allocate our stack wherever it wants. As it
  happened on my PC, that was right where I was copying the kernel to.
  This did not cause happiness. The solution to this was to also switch
  to a temporary stack in a safe location before performing the final
  copy of the loaded kernel.

r247216:

  Use the UEFI Graphics Output Protocol to get the parameters of the
  framebuffer.

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
emaste 2014-04-04 00:16:46 +00:00
parent 1792ca3cfb
commit c72005d63b
20 changed files with 1170 additions and 72 deletions

7
sys/boot/amd64/Makefile Normal file
View File

@ -0,0 +1,7 @@
# $FreeBSD$
.include <bsd.own.mk>
SUBDIR= efi
.include <bsd.subdir.mk>

View File

@ -0,0 +1,11 @@
# Common defines for all of /sys/boot/amd64/
#
# $FreeBSD$
BINDIR?= /boot
CFLAGS+= -ffreestanding
CFLAGS+= -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
LDFLAGS+= -nostdlib
.include "../Makefile.inc"

View File

@ -1,7 +1,6 @@
# $FreeBSD$
NO_MAN=
BUILDING_EFI=
.include <bsd.own.mk>
MK_SSP= no
@ -13,30 +12,30 @@ INTERNALPROG=
SRCS= autoload.c \
bootinfo.c \
conf.c \
copy.c \
devicename.c \
efimd.c \
elf32_freebsd.c \
exec.c \
i386_copy.c \
elf64_freebsd.c \
framebuffer.c \
main.c \
reloc.c \
vers.c
SRCS+= start.S
SRCS+= amd64_tramp.S \
start.S
CFLAGS+= -fPIC
CFLAGS+= -I.
CFLAGS+= -I${.CURDIR}/../../efi/include
CFLAGS+= -I${.CURDIR}/../../efi/include/i386
CFLAGS+= -I${.CURDIR}/../../efi/include/${MACHINE_CPUARCH}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
.if ${MK_FORTH} != "no"
BOOT_FORTH= yes
CFLAGS+= -DBOOT_FORTH
CFLAGS+= -I${.CURDIR}/../../ficl
CFLAGS+= -I${.CURDIR}/../../ficl/i386
.if ${MACHINE_CPUARCH} == "amd64"
LIBFICL= ${.OBJDIR}/../../ficl32/libficl.a
.else
CFLAGS+= -I${.CURDIR}/../../ficl/${MACHINE_CPUARCH}
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
.endif
.endif
# Include bcache code.
HAVE_BCACHE= yes
@ -49,14 +48,14 @@ CFLAGS+= -I${.CURDIR}/../../common
FILES= loader.efi
FILESMODE_loader.efi= ${BINMODE}
LDSCRIPT= ${.CURDIR}/ldscript.i386
LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared
LDSCRIPT= ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared -Wl,-znocombreloc
${PROG}: ${LDSCRIPT}
CLEANFILES= vers.c loader.efi
NEWVERSWHAT= "EFI loader" x86
NEWVERSWHAT= "EFI loader" ${MACHINE_CPUARCH}
vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
@ -64,28 +63,36 @@ vers.c: ${.CURDIR}/../../common/newvers.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}
.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

View File

@ -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

View File

@ -28,7 +28,7 @@
__FBSDID("$FreeBSD$");
int
i386_autoload(void)
x86_efi_autoload(void)
{
return (0);

View File

@ -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);
}

View File

@ -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
};

102
sys/boot/amd64/efi/copy.c Normal file
View File

@ -0,0 +1,102 @@
/*-
* Copyright (c) 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Benno Rice under sponsorship from
* the FreeBSD Foundation.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <stand.h>
#include <bootstrap.h>
#include <efi.h>
#include <efilib.h>
#define STAGE_PAGES 8192 /* 32MB */
EFI_PHYSICAL_ADDRESS staging;
int stage_offset_set = 0;
ssize_t stage_offset;
int
x86_efi_copy_init(void)
{
EFI_STATUS status;
status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
STAGE_PAGES, &staging);
if (EFI_ERROR(status)) {
printf("failed to allocate staging area: %d\n",
status & EFI_ERROR_MASK);
return (status);
}
return (0);
}
ssize_t
x86_efi_copyin(const void *src, vm_offset_t dest, const size_t len)
{
if (!stage_offset_set) {
stage_offset = (vm_offset_t)staging - dest;
stage_offset_set = 1;
}
bcopy(src, (void *)(dest + stage_offset), len);
return (len);
}
ssize_t
x86_efi_copyout(const vm_offset_t src, void *dest, const size_t len)
{
bcopy((void *)(src + stage_offset), dest, len);
return (len);
}
ssize_t
x86_efi_readin(const int fd, vm_offset_t dest, const size_t len)
{
return (read(fd, (void *)(dest + stage_offset), len));
}
void
x86_efi_copy_finish(void)
{
uint64_t *src, *dst, *last;
src = (uint64_t *)staging;
dst = (uint64_t *)(staging - stage_offset);
last = (uint64_t *)(staging + STAGE_PAGES * EFI_PAGE_SIZE);
while (src < last)
*dst++ = *src++;
}

View File

@ -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);

View File

@ -0,0 +1,189 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#define __ELF_WORD_SIZE 64
#include <sys/param.h>
#include <sys/exec.h>
#include <sys/linker.h>
#include <string.h>
#include <machine/elf.h>
#include <stand.h>
#include <efi.h>
#include <efilib.h>
#include "bootstrap.h"
#include "platform/acfreebsd.h"
#include "acconfig.h"
#define ACPI_SYSTEM_XFACE
#include "actypes.h"
#include "actbl.h"
#include "x86_efi.h"
static EFI_GUID acpi_guid = ACPI_TABLE_GUID;
static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID;
extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp);
static int elf64_exec(struct preloaded_file *amp);
static int elf64_obj_exec(struct preloaded_file *amp);
struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
#define PG_V 0x001
#define PG_RW 0x002
#define PG_U 0x004
#define PG_PS 0x080
typedef u_int64_t p4_entry_t;
typedef u_int64_t p3_entry_t;
typedef u_int64_t p2_entry_t;
static p4_entry_t *PT4;
static p3_entry_t *PT3;
static p2_entry_t *PT2;
static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend,
uint64_t modulep, p4_entry_t *pagetable,
uint64_t entry);
extern uintptr_t amd64_tramp;
extern uint32_t amd64_tramp_size;
/*
* There is an ELF kernel and one or more ELF modules loaded.
* We wish to start executing the kernel image, so make such
* preparations as are required, and do so.
*/
static int
elf64_exec(struct preloaded_file *fp)
{
struct file_metadata *md;
Elf_Ehdr *ehdr;
vm_offset_t modulep, kernend, trampcode, trampstack;
int err, i;
ACPI_TABLE_RSDP *rsdp;
char buf[24];
int revision;
EFI_STATUS status;
rsdp = efi_get_table(&acpi20_guid);
if (rsdp == NULL) {
rsdp = efi_get_table(&acpi_guid);
}
if (rsdp != NULL) {
sprintf(buf, "0x%016llx", rsdp);
setenv("hint.acpi.0.rsdp", buf, 1);
revision = rsdp->Revision;
if (revision == 0)
revision = 1;
sprintf(buf, "%d", revision);
setenv("hint.acpi.0.revision", buf, 1);
strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
buf[sizeof(rsdp->OemId)] = '\0';
setenv("hint.acpi.0.oem", buf, 1);
sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress);
setenv("hint.acpi.0.rsdt", buf, 1);
if (revision >= 2) {
/* XXX extended checksum? */
sprintf(buf, "0x%016llx", rsdp->XsdtPhysicalAddress);
setenv("hint.acpi.0.xsdt", buf, 1);
sprintf(buf, "%d", rsdp->Length);
setenv("hint.acpi.0.xsdt_length", buf, 1);
}
}
if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
return(EFTYPE);
ehdr = (Elf_Ehdr *)&(md->md_data);
trampcode = (vm_offset_t)0x0000000040000000;
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1,
(EFI_PHYSICAL_ADDRESS *)&trampcode);
bzero((void *)trampcode, EFI_PAGE_SIZE);
trampstack = trampcode + EFI_PAGE_SIZE - 8;
bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size);
trampoline = (void *)trampcode;
PT4 = (p4_entry_t *)0x0000000040000000;
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3,
(EFI_PHYSICAL_ADDRESS *)&PT4);
bzero(PT4, 3 * EFI_PAGE_SIZE);
PT3 = &PT4[512];
PT2 = &PT3[512];
/*
* This is kinda brutal, but every single 1GB VM memory segment points
* to the same first 1GB of physical memory. But it is more than
* adequate.
*/
for (i = 0; i < 512; i++) {
/* Each slot of the L4 pages points to the same L3 page. */
PT4[i] = (p4_entry_t)PT3;
PT4[i] |= PG_V | PG_RW | PG_U;
/* Each slot of the L3 pages points to the same L2 page. */
PT3[i] = (p3_entry_t)PT2;
PT3[i] |= PG_V | PG_RW | PG_U;
/* The L2 page slots are mapped with 2MB pages for 1GB. */
PT2[i] = i * (2 * 1024 * 1024);
PT2[i] |= PG_V | PG_RW | PG_PS | PG_U;
}
printf("Start @ 0x%lx ...\n", ehdr->e_entry);
err = bi_load(fp->f_args, &modulep, &kernend);
if (err != 0)
return(err);
status = BS->ExitBootServices(IH, x86_efi_mapkey);
if (EFI_ERROR(status)) {
printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
(long)status);
return (EINVAL);
}
dev_cleanup();
trampoline(trampstack, x86_efi_copy_finish, kernend, modulep, PT4,
ehdr->e_entry);
panic("exec returned");
}
static int
elf64_obj_exec(struct preloaded_file *fp)
{
return (EFTYPE);
}

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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) }

View File

@ -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);

View File

@ -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

View File

@ -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_ */

View File

@ -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)

View File

@ -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 */