summaryrefslogtreecommitdiffstats
path: root/sys/boot/efi/libefi
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/efi/libefi')
-rw-r--r--sys/boot/efi/libefi/Makefile39
-rw-r--r--sys/boot/efi/libefi/arch/ia64/ldscript.ia6473
-rw-r--r--sys/boot/efi/libefi/arch/ia64/start.S305
-rw-r--r--sys/boot/efi/libefi/bootinfo.c348
-rw-r--r--sys/boot/efi/libefi/copy.c68
-rw-r--r--sys/boot/efi/libefi/delay.c47
-rw-r--r--sys/boot/efi/libefi/devicename.c240
-rw-r--r--sys/boot/efi/libefi/efi_console.c98
-rw-r--r--sys/boot/efi/libefi/efiboot.h94
-rw-r--r--sys/boot/efi/libefi/efifpswa.c59
-rw-r--r--sys/boot/efi/libefi/efifs.c401
-rw-r--r--sys/boot/efi/libefi/efinet.c267
-rw-r--r--sys/boot/efi/libefi/elf_freebsd.c223
-rw-r--r--sys/boot/efi/libefi/libefi.c188
-rw-r--r--sys/boot/efi/libefi/module.c40
-rw-r--r--sys/boot/efi/libefi/time.c224
16 files changed, 2714 insertions, 0 deletions
diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile
new file mode 100644
index 0000000..bd8e034
--- /dev/null
+++ b/sys/boot/efi/libefi/Makefile
@@ -0,0 +1,39 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../${MACHINE_ARCH}/${MACHINE_ARCH}
+
+LIB= efi
+INTERNALLIB= true
+
+SRCS= libefi.c efi_console.c time.c copy.c devicename.c module.c
+SRCS+= delay.c efifs.c efinet.c elf_freebsd.c bootinfo.c pal.S
+
+.if ${MACHINE_ARCH} == "ia64"
+SRCS+= efifpswa.c
+.endif
+
+CFLAGS+= -ffreestanding -fpic
+CFLAGS+= -I${.CURDIR}/../include
+CFLAGS+= -I${.CURDIR}/../include/${MACHINE_ARCH}
+CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
+
+# Pick up the bootstrap header for some interface items
+CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../../.. -I.
+
+.if ${MACHINE_ARCH} == "powerpc"
+CFLAGS+= -msoft-float
+.endif
+
+.ifdef(BOOT_DISK_DEBUG)
+# Make the disk code more talkative
+CFLAGS+= -DDISK_DEBUG
+.endif
+
+machine:
+ ln -sf ${.CURDIR}/../../../${MACHINE_ARCH}/include machine
+
+CLEANFILES+= machine
+
+.include <bsd.lib.mk>
+
+beforedepend ${OBJS}: machine
diff --git a/sys/boot/efi/libefi/arch/ia64/ldscript.ia64 b/sys/boot/efi/libefi/arch/ia64/ldscript.ia64
new file mode 100644
index 0000000..002c263
--- /dev/null
+++ b/sys/boot/efi/libefi/arch/ia64/ldscript.ia64
@@ -0,0 +1,73 @@
+/* $FreeBSD$ */
+OUTPUT_FORMAT("elf64-ia64-little", "elf64-ia64-little", "elf64-ia64-little")
+OUTPUT_ARCH(ia64)
+ENTRY(_start_plabel)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0;
+ ImageBase = .;
+ . = SIZEOF_HEADERS;
+ . = ALIGN(4096);
+ .text : {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.plt)
+ } =0x00300000010070000002000001000400
+ . = ALIGN(4096);
+ .data : {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.rodata1)
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+ *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
+ *(.opd)
+ *(.IA_64.unwind_info* .gnu.linkonce.ia64unwi.*)
+ *(.IA_64.unwind* .gnu.linkonce.ia64unw.*)
+ __start_set_Xcommand_set = .;
+ *(set_Xcommand_set)
+ __stop_set_Xcommand_set = .;
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.data1)
+ *(.plabel)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ }
+ . = ALIGN(4096);
+ __gp = .;
+ .sdata : {
+ *(.got.plt .got)
+ *(.IA_64.pltoff)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ *(dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ }
+ . = ALIGN(4096);
+ .dynamic : { *(.dynamic) }
+ . = ALIGN(4096);
+ .rela : {
+ *(.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.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)
+ *(.rela.IA_64.pltoff)
+ *(.relaset_*)
+ *(.rela.dyn .rela.dyn.*)
+ }
+ . = ALIGN(4096);
+ .reloc : { *(.reloc) }
+ . = ALIGN(4096);
+ .hash : { *(.hash) }
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+}
diff --git a/sys/boot/efi/libefi/arch/ia64/start.S b/sys/boot/efi/libefi/arch/ia64/start.S
new file mode 100644
index 0000000..643f1c9
--- /dev/null
+++ b/sys/boot/efi/libefi/arch/ia64/start.S
@@ -0,0 +1,305 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+ .text
+
+#include <machine/asm.h>
+
+#define EFI_SUCCESS 0
+#define EFI_LOAD_ERROR 1
+#define EFI_BUFFER_TOO_SMALL 5
+
+#define DT_NULL 0 /* Terminating entry. */
+#define DT_NEEDED 1 /* String table offset of a needed shared
+ library. */
+#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
+#define DT_PLTGOT 3 /* Processor-dependent address. */
+#define DT_HASH 4 /* Address of symbol hash table. */
+#define DT_STRTAB 5 /* Address of string table. */
+#define DT_SYMTAB 6 /* Address of symbol table. */
+#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
+#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
+#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
+#define DT_STRSZ 10 /* Size of string table. */
+#define DT_SYMENT 11 /* Size of each symbol table entry. */
+#define DT_INIT 12 /* Address of initialization function. */
+#define DT_FINI 13 /* Address of finalization function. */
+#define DT_SONAME 14 /* String table offset of shared object
+ name. */
+#define DT_RPATH 15 /* String table offset of library path. */
+#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. */
+#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
+#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */
+#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
+#define DT_PLTREL 20 /* Type of relocation used for PLT. */
+#define DT_DEBUG 21 /* Reserved (not used). */
+#define DT_TEXTREL 22 /* Indicates there may be relocations in
+ non-writable segments. */
+#define DT_JMPREL 23 /* Address of PLT relocations. */
+
+#define DT_COUNT 24 /* Number of defined d_tag values. */
+
+#define R_IA64_NONE 0 /* None */
+#define R_IA64_DIR64MSB 0x26 /* word64 MSB S + A */
+#define R_IA64_DIR64LSB 0x27 /* word64 LSB S + A */
+#define R_IA64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */
+#define R_IA64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */
+#define R_IA64_REL64MSB 0x6e /* word64 MSB BD + A */
+#define R_IA64_REL64LSB 0x6f /* word64 LSB BD + A */
+#define R_IA64_IPLTLSB 0x81 /* function descriptor LSB speciaal */
+
+ENTRY(_start, 2)
+ alloc loc0=ar.pfs,2,3,3,0
+ mov loc1=rp
+ movl loc2=@gprel(ImageBase)
+ ;;
+ add loc2=gp,loc2
+ ;;
+ mov out0=loc2
+ mov out1=in1
+ ;;
+ br.call.sptk.few rp=_reloc // relocate image
+
+ cmp.ne p6,p0=EFI_SUCCESS,r8 // did it work?
+(p6) br.cond.dpnt.few 9f
+
+ mov out0=in0 // image_handle
+ mov out1=in1 // system_table
+ br.call.sptk.few rp=efi_main
+9:
+ mov ar.pfs=loc0
+ mov rp=loc1
+ ;;
+ br.ret.sptk.few rp
+END(_start)
+
+ // PLABEL for PE32+
+ .global _start_plabel
+ .section .plabel, "a"
+ .align 16
+_start_plabel:
+ .quad _start
+ .quad __gp
+ .previous
+
+ // A PE32+ relocation entry for the plabel
+
+ .section .reloc, "a"
+ .long _start_plabel
+ .long 12
+ .short (10 << 12) + 0
+ .short (10 << 12) + 8
+ .previous
+
+// in0: image base
+// in1: system table
+//
+// XXX Assumes PLT relocations are of type Elf_Rela
+//
+// r2 = address of fptr_storage
+// r3 = address of fptr_storage_end
+// r4 = address of first free fptr
+//
+// r15 = r_offset
+// r16 = r_info -OR- d_tag
+// r17 = r_addend -OR- d_val (=d_ptr)
+// r18 = address of .rela dynamic section
+// r19 = size of .rela section
+// r20 = size of .rela element (Elf_Rela)
+// r21 = address of first PLT relocation
+// r22 = size of PLT relocations
+// r23 = relocation type
+// r24 = address of symbol
+// r28 = R_IA64_IPLTLSB
+// f8 = address of symbol table
+// f9 = size of symtab element
+
+STATIC_ENTRY(_reloc, 2)
+ alloc loc0=ar.pfs,2,2,0,0
+ ;;
+ mov loc1=rp
+ movl r29=@gprel(_DYNAMIC) // find _DYNAMIC etc.
+ ;;
+ add r15=r29,gp
+ movl r29=@gprel(fptr_storage)
+ ;;
+ add r2=r29,gp
+ movl r29=@gprel(fptr_storage_end)
+ ;;
+ add r3=r29,gp
+ mov r4=r2
+ mov r19=0
+ mov r22=0
+ mov r20=24
+ mov r28=R_IA64_IPLTLSB
+ ;;
+1:
+ ld8 r16=[r15],8 // read r15->d_tag
+ ;;
+ ld8 r17=[r15],8 // and r15->d_val
+ ;;
+ cmp.eq p6,p0=DT_NULL,r16 // done?
+(p6) br.cond.dpnt.few 2f
+ ;;
+ cmp.eq p6,p0=DT_RELA,r16 // rela section?
+ ;;
+(p6) add r18=r17,in0
+ cmp.eq p6,p0=DT_RELASZ,r16 // rela section size?
+ ;;
+(p6) mov r19=r17
+ cmp.eq p6,p0=DT_RELAENT,r16 // rela entry size?
+ ;;
+(p6) mov r20=r17
+ cmp.eq p6,p0=DT_JMPREL,r16 // PLT relocs?
+ ;;
+(p6) add r21=r17,in0
+ cmp.eq p6,p0=DT_PLTRELSZ,r16 // PLT relocs size?
+ ;;
+(p6) mov r22=r17
+ cmp.eq p6,p0=DT_SYMTAB,r16 // symbol table?
+ ;;
+(p6) add r29=r17,in0
+ ;;
+(p6) setf.sig f8=r29
+ cmp.eq p6,p0=DT_SYMENT,r16 // symbol entry size?
+ ;;
+(p6) setf.sig f9=r17
+ br.dptk 1b
+
+2:
+ cmp.lt p6,p0=0,r19
+(p6) br.cond.dptk 3f
+ ;;
+ mov r19=r22
+ mov r18=r21
+ mov r21=0
+ mov r22=0
+ ;;
+ cmp.lt p6,p0=0,r19
+(p6) br.cond.dptk 3f
+ ;;
+ mov r8=EFI_SUCCESS
+ br.dptk 9f
+3:
+ ld8 r29=[r18],8 // read r_offset
+ ;;
+ ld8 r16=[r18],8 // read r_info
+ add r15=r29,in0 // relocate r_offset
+ ;;
+ ld8 r17=[r18],8 // read r_addend
+ sub r19=r19,r20 // update relasz
+ extr.u r23=r16,0,32 // ELF64_R_TYPE(r16)
+ ;;
+ cmp.eq p6,p0=R_IA64_NONE,r23
+(p6) br.cond.dpnt.few 2b
+ ;;
+ cmp.eq p6,p0=R_IA64_REL64LSB,r23
+(p6) br.cond.dptk.few 4f
+ ;;
+ extr.u r29=r16,32,32 // ELF64_R_SYM(r16)
+ ;;
+ setf.sig f10=r29 // so we can multiply
+ ;;
+ xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment
+ ;;
+ getf.sig r29=f10
+ ;;
+ add r29=8,r29 // address of st_value
+ ;;
+ ld8 r29=[r29] // read symbol value
+ ;;
+ add r24=r29,in0 // relocate symbol value
+ ;;
+ cmp.eq p6,p0=R_IA64_DIR64LSB,r23
+(p6) br.cond.dptk.few 5f
+ ;;
+ cmp.eq p6,p0=R_IA64_FPTR64LSB,r23
+(p6) br.cond.dptk.few 6f
+ ;;
+ cmp.ne p6,p0=r28,r23 // IPLTLSB
+(p6) br.cond.dptk.few 2b
+
+ // IPLTLSB
+ add r29=r24,r17 // S + A
+ ;;
+ st8 [r15]=r29,8 // fdesc:FP
+ ;;
+ st8 [r15]=gp // fdesc:GP
+ br.cond.sptk.few 2b
+
+ // REL64LSB
+4:
+ add r29=in0,r17 // BD + A
+ ;;
+ st8 [r15]=r29 // word64
+ br.cond.sptk.few 2b
+
+ // DIR64LSB
+5:
+ add r29=r24,r17 // S + A
+ ;;
+ st8 [r15]=r29 // word64
+ br.cond.sptk.few 2b
+
+6:
+ mov r29=r2 // FPTR64LSB
+ ;;
+7:
+ cmp.geu p6,p0=r29,r4 // end of fptrs?
+(p6) br.cond.dpnt.few 8f // can't find existing fptr
+ ld8 r17=[r29] // read function from fptr
+ ;;
+ cmp.eq p6,p0=r24,r17 // same function?
+ ;;
+(p6) st8 [r15]=r29 // reuse fptr
+(p6) br.cond.sptk.few 2b // done
+ add r29=16,r29 // next fptr
+ br.sptk.few 7b
+8:
+ mov r8=EFI_BUFFER_TOO_SMALL // failure return value
+ cmp.geu p6,p0=r4,r3 // space left?
+(p6) br.cond.dpnt.few 9f // bail out
+ st8 [r15]=r4 // install fptr
+ ;;
+ st8 [r4]=r24,8 // write fptr address
+ ;;
+ st8 [r4]=gp,8 // write fptr gp
+ br.cond.sptk.few 2b
+
+9:
+ mov ar.pfs=loc0
+ mov rp=loc1
+ ;;
+ br.ret.sptk.few rp
+END(_reloc)
+
+ .data
+ .align 16
+fptr_storage:
+ .space 1024*16 // XXX
+fptr_storage_end:
diff --git a/sys/boot/efi/libefi/bootinfo.c b/sys/boot/efi/libefi/bootinfo.c
new file mode 100644
index 0000000..076aed1
--- /dev/null
+++ b/sys/boot/efi/libefi/bootinfo.c
@@ -0,0 +1,348 @@
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith@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.
+ *
+ * $FreeBSD$
+ */
+
+#include <stand.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <sys/linker.h>
+#include <machine/elf.h>
+#include <machine/bootinfo.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+
+static EFI_GUID hcdp = HCDP_TABLE_GUID;
+
+/*
+ * Return a 'boothowto' value corresponding to the kernel arguments in
+ * (kargs) and any relevant environment variables.
+ */
+static struct
+{
+ const char *ev;
+ int mask;
+} howto_names[] = {
+ {"boot_askname", RB_ASKNAME},
+ {"boot_cdrom", RB_CDROM},
+ {"boot_userconfig", RB_CONFIG},
+ {"boot_ddb", RB_KDB},
+ {"boot_gdb", RB_GDB},
+ {"boot_single", RB_SINGLE},
+ {"boot_verbose", RB_VERBOSE},
+ {"boot_multicons", RB_MULTIPLE},
+ {"boot_serial", RB_SERIAL},
+ {NULL, 0}
+};
+
+extern char *efi_fmtdev(void *vdev);
+
+int
+bi_getboothowto(char *kargs)
+{
+ char *cp;
+ int howto;
+ int active;
+ int i;
+
+ /* Parse kargs */
+ howto = 0;
+ if (kargs != NULL) {
+ cp = kargs;
+ active = 0;
+ while (*cp != 0) {
+ if (!active && (*cp == '-')) {
+ active = 1;
+ } else if (active)
+ switch (*cp) {
+ case 'a':
+ howto |= RB_ASKNAME;
+ break;
+ case 'c':
+ howto |= RB_CONFIG;
+ break;
+ case 'C':
+ howto |= RB_CDROM;
+ break;
+ case 'd':
+ howto |= RB_KDB;
+ break;
+ case 'D':
+ howto |= RB_MULTIPLE;
+ break;
+ case 'm':
+ howto |= RB_MUTE;
+ break;
+ case 'g':
+ howto |= RB_GDB;
+ break;
+ case 'h':
+ howto |= RB_SERIAL;
+ break;
+ case 'r':
+ howto |= RB_DFLTROOT;
+ break;
+ case 's':
+ howto |= RB_SINGLE;
+ break;
+ case 'v':
+ howto |= RB_VERBOSE;
+ break;
+ default:
+ active = 0;
+ break;
+ }
+ cp++;
+ }
+ }
+ /* get equivalents from the environment */
+ for (i = 0; howto_names[i].ev != NULL; i++)
+ if (getenv(howto_names[i].ev) != NULL)
+ howto |= howto_names[i].mask;
+ if (!strcmp(getenv("console"), "comconsole"))
+ howto |= RB_SERIAL;
+ if (!strcmp(getenv("console"), "nullconsole"))
+ howto |= RB_MUTE;
+ 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.
+ */
+vm_offset_t
+bi_copyenv(vm_offset_t addr)
+{
+ struct env_var *ep;
+
+ /* traverse the environment */
+ for (ep = environ; ep != NULL; ep = ep->ev_next) {
+ efi_copyin(ep->ev_name, addr, strlen(ep->ev_name));
+ addr += strlen(ep->ev_name);
+ efi_copyin("=", addr, 1);
+ addr++;
+ if (ep->ev_value != NULL) {
+ efi_copyin(ep->ev_value, addr, strlen(ep->ev_value));
+ addr += strlen(ep->ev_value);
+ }
+ efi_copyin("", addr, 1);
+ addr++;
+ }
+ efi_copyin("", addr, 1);
+ addr++;
+ return(addr);
+}
+
+/*
+ * 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) { \
+ u_int32_t x = (v); \
+ efi_copyin(&x, a, sizeof(x)); \
+ a += sizeof(x); \
+}
+
+#define MOD_STR(t, a, s) { \
+ COPY32(t, a); \
+ COPY32(strlen(s) + 1, a); \
+ efi_copyin(s, a, strlen(s) + 1); \
+ a += roundup(strlen(s) + 1, sizeof(u_int64_t));\
+}
+
+#define MOD_NAME(a, s) MOD_STR(MODINFO_NAME, a, s)
+#define MOD_TYPE(a, s) MOD_STR(MODINFO_TYPE, a, s)
+#define MOD_ARGS(a, s) MOD_STR(MODINFO_ARGS, a, s)
+
+#define MOD_VAR(t, a, s) { \
+ COPY32(t, a); \
+ COPY32(sizeof(s), a); \
+ efi_copyin(&s, a, sizeof(s)); \
+ a += roundup(sizeof(s), sizeof(u_int64_t)); \
+}
+
+#define MOD_ADDR(a, s) MOD_VAR(MODINFO_ADDR, a, s)
+#define MOD_SIZE(a, s) MOD_VAR(MODINFO_SIZE, a, s)
+
+#define MOD_METADATA(a, mm) { \
+ COPY32(MODINFO_METADATA | mm->md_type, a); \
+ COPY32(mm->md_size, a); \
+ efi_copyin(mm->md_data, a, mm->md_size); \
+ a += roundup(mm->md_size, sizeof(u_int64_t));\
+}
+
+#define MOD_END(a) { \
+ COPY32(MODINFO_END, a); \
+ COPY32(0, a); \
+}
+
+vm_offset_t
+bi_copymodules(vm_offset_t addr)
+{
+ struct preloaded_file *fp;
+ struct file_metadata *md;
+
+ /* 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); /* this field must come first */
+ MOD_TYPE(addr, fp->f_type);
+ if (fp->f_args)
+ MOD_ARGS(addr, fp->f_args);
+ MOD_ADDR(addr, fp->f_addr);
+ MOD_SIZE(addr, fp->f_size);
+ for (md = fp->f_metadata; md != NULL; md = md->md_next)
+ if (!(md->md_type & MODINFOMD_NOCOPY))
+ MOD_METADATA(addr, md);
+ }
+ MOD_END(addr);
+ return(addr);
+}
+
+/*
+ * Load the information expected by an alpha kernel.
+ *
+ * - The kernel environment is copied into kernel space.
+ * - Module metadata are formatted and placed in kernel space.
+ */
+int
+bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey,
+ UINTN pages)
+{
+ char *rootdevname;
+ struct efi_devdesc *rootdev;
+ struct preloaded_file *xp;
+ vm_offset_t addr, bootinfo_addr;
+ vm_offset_t ssym, esym;
+ struct file_metadata *md;
+ EFI_STATUS status;
+ UINTN bisz, key;
+
+ /*
+ * Version 1 bootinfo.
+ */
+ bi->bi_magic = BOOTINFO_MAGIC;
+ bi->bi_version = 1;
+
+ /*
+ * Calculate boothowto.
+ */
+ bi->bi_boothowto = bi_getboothowto(fp->f_args);
+
+ /*
+ * Stash EFI System Table.
+ */
+ bi->bi_systab = (u_int64_t) ST;
+
+ /*
+ * 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");
+ efi_getdev((void **)(&rootdev), rootdevname, NULL);
+ if (rootdev == NULL) { /* bad $rootdev/$currdev */
+ printf("can't determine root device\n");
+ return(EINVAL);
+ }
+
+ /* Try reading the /etc/fstab file to select the root device */
+ getrootmount(efi_fmtdev((void *)rootdev));
+ free(rootdev);
+
+ ssym = esym = 0;
+ if ((md = file_findmetadata(fp, MODINFOMD_SSYM)) != NULL)
+ ssym = *((vm_offset_t *)&(md->md_data));
+ if ((md = file_findmetadata(fp, MODINFOMD_ESYM)) != NULL)
+ esym = *((vm_offset_t *)&(md->md_data));
+ if (ssym == 0 || esym == 0)
+ ssym = esym = 0; /* sanity */
+
+ bi->bi_symtab = ssym;
+ bi->bi_esymtab = esym;
+
+ bi->bi_hcdp = (uint64_t)efi_get_table(&hcdp); /* DIG64 HCDP table addr. */
+ fpswa_init(&bi->bi_fpswa); /* find FPSWA interface */
+
+ /* find the last module in the chain */
+ 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 = (addr + PAGE_MASK) & ~PAGE_MASK;
+
+ /* copy our environment */
+ bi->bi_envp = addr;
+ addr = bi_copyenv(addr);
+
+ /* pad to a page boundary */
+ addr = (addr + PAGE_MASK) & ~PAGE_MASK;
+
+ /* copy module list and metadata */
+ bi->bi_modulep = addr;
+ addr = bi_copymodules(addr);
+
+ /* all done copying stuff in, save end of loaded object space */
+ bi->bi_kernend = addr;
+
+ /*
+ * Read the memory map and stash it after bootinfo. Align the memory map
+ * on a 16-byte boundary (the bootinfo block is page aligned).
+ */
+ bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f;
+ bi->bi_memmap = ((u_int64_t)bi) + bisz;
+ bi->bi_memmap_size = EFI_PAGE_SIZE * pages - bisz;
+ status = BS->GetMemoryMap(&bi->bi_memmap_size,
+ (EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, &key,
+ &bi->bi_memdesc_size, &bi->bi_memdesc_version);
+ if (EFI_ERROR(status)) {
+ printf("bi_load: Can't read memory map\n");
+ return EINVAL;
+ }
+ *mapkey = key;
+
+ return(0);
+}
diff --git a/sys/boot/efi/libefi/copy.c b/sys/boot/efi/libefi/copy.c
new file mode 100644
index 0000000..7bc4edf
--- /dev/null
+++ b/sys/boot/efi/libefi/copy.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith@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$");
+
+/*
+ * MD primitives supporting placement of module data
+ */
+#include <stand.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <machine/ia64_cpu.h>
+#include <machine/vmparam.h>
+
+int
+efi_copyin(void *src, vm_offset_t dest, size_t len)
+{
+ EFI_PHYSICAL_ADDRESS p = IA64_RR_MASK(dest);
+#if 0
+ BS->AllocatePages(AllocateAddress, EfiRuntimeServicesData,
+ len >> 12, &p);
+#endif
+ bcopy(src, (void*) p, len);
+ return (len);
+}
+
+int
+efi_copyout(vm_offset_t src, void *dest, size_t len)
+{
+ bcopy((void*) IA64_RR_MASK(src), dest, len);
+ return (len);
+}
+
+int
+efi_readin(int fd, vm_offset_t dest, size_t len)
+{
+ EFI_PHYSICAL_ADDRESS p = IA64_RR_MASK(dest);
+#if 0
+ BS->AllocatePages(AllocateAddress, EfiRuntimeServicesData,
+ len >> 12, &p);
+#endif
+ return (read(fd, (void*) p, len));
+}
diff --git a/sys/boot/efi/libefi/delay.c b/sys/boot/efi/libefi/delay.c
new file mode 100644
index 0000000..723f681
--- /dev/null
+++ b/sys/boot/efi/libefi/delay.c
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * 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 <efi.h>
+#include <efilib.h>
+
+void
+delay(int usecs)
+{
+ static EFI_EVENT ev = 0;
+ UINTN junk;
+
+ if (!ev) {
+ if (BS->CreateEvent(EVT_TIMER, TPL_APPLICATION, 0, 0, &ev)
+ != EFI_SUCCESS)
+ return;
+ }
+
+ BS->SetTimer(ev, TimerRelative, usecs * 10);
+ BS->WaitForEvent(1, &ev, &junk);
+}
diff --git a/sys/boot/efi/libefi/devicename.c b/sys/boot/efi/libefi/devicename.c
new file mode 100644
index 0000000..dda2fb0
--- /dev/null
+++ b/sys/boot/efi/libefi/devicename.c
@@ -0,0 +1,240 @@
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith@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.
+ *
+ * $FreeBSD$
+ */
+
+#include <stand.h>
+#include <string.h>
+#include <sys/disklabel.h>
+#include "bootstrap.h"
+
+#include <efi.h>
+#include <efilib.h>
+#include "efiboot.h"
+
+static int efi_parsedev(struct efi_devdesc **dev, const char *devspec, const char **path);
+
+/*
+ * Point (dev) at an allocated device specifier for the device matching the
+ * path in (devspec). If it contains an explicit device specification,
+ * use that. If not, use the default device.
+ */
+int
+efi_getdev(void **vdev, const char *devspec, const char **path)
+{
+ struct efi_devdesc **dev = (struct efi_devdesc **)vdev;
+ int rv;
+
+ /*
+ * If it looks like this is just a path and no
+ * device, go with the current device.
+ */
+ if ((devspec == NULL) ||
+ (devspec[0] == '/') ||
+ (strchr(devspec, ':') == NULL)) {
+
+ if (((rv = efi_parsedev(dev, getenv("currdev"), NULL)) == 0) &&
+ (path != NULL))
+ *path = devspec;
+ return(rv);
+ }
+
+ /*
+ * Try to parse the device name off the beginning of the devspec
+ */
+ return(efi_parsedev(dev, devspec, path));
+}
+
+/*
+ * Point (dev) at an allocated device specifier matching the string version
+ * at the beginning of (devspec). Return a pointer to the remaining
+ * text in (path).
+ *
+ * In all cases, the beginning of (devspec) is compared to the names
+ * of known devices in the device switch, and then any following text
+ * is parsed according to the rules applied to the device type.
+ *
+ * For disk-type devices, the syntax is:
+ *
+ * disk<unit>[s<slice>][<partition>]:
+ *
+ */
+static int
+efi_parsedev(struct efi_devdesc **dev, const char *devspec, const char **path)
+{
+ struct efi_devdesc *idev;
+ struct devsw *dv;
+ int i, unit, slice, partition, err;
+ char *cp;
+ const char *np;
+
+ /* minimum length check */
+ if (strlen(devspec) < 2)
+ return(EINVAL);
+
+ /* look for a device that matches */
+ for (i = 0, dv = NULL; devsw[i] != NULL; i++) {
+ if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) {
+ dv = devsw[i];
+ break;
+ }
+ }
+
+ if (dv == NULL)
+ return(ENOENT);
+ idev = malloc(sizeof(struct efi_devdesc));
+ err = 0;
+ np = (devspec + strlen(dv->dv_name));
+
+ switch(dv->dv_type) {
+ case DEVT_NONE: /* XXX what to do here? Do we care? */
+ break;
+
+ case DEVT_DISK:
+ unit = -1;
+ slice = -1;
+ partition = -1;
+ if (*np && (*np != ':')) {
+ unit = strtol(np, &cp, 10); /* next comes the unit number */
+ if (cp == np) {
+ err = EUNIT;
+ goto fail;
+ }
+ if (*cp == 's') { /* got a slice number */
+ np = cp + 1;
+ slice = strtol(np, &cp, 10);
+ if (cp == np) {
+ err = ESLICE;
+ goto fail;
+ }
+ }
+ if (*cp && (*cp != ':')) {
+ partition = *cp - 'a'; /* get a partition number */
+ if ((partition < 0) || (partition >= MAXPARTITIONS)) {
+ err = EPART;
+ goto fail;
+ }
+ cp++;
+ }
+ }
+ if (*cp && (*cp != ':')) {
+ err = EINVAL;
+ goto fail;
+ }
+
+ idev->d_kind.efidisk.unit = unit;
+ idev->d_kind.efidisk.slice = slice;
+ idev->d_kind.efidisk.partition = partition;
+
+ if (path != NULL)
+ *path = (*cp == 0) ? cp : cp + 1;
+ break;
+
+ case DEVT_NET:
+ unit = 0;
+
+ if (*np && (*np != ':')) {
+ unit = strtol(np, &cp, 0); /* get unit number if present */
+ if (cp == np) {
+ err = EUNIT;
+ goto fail;
+ }
+ }
+ if (*cp && (*cp != ':')) {
+ err = EINVAL;
+ goto fail;
+ }
+
+ idev->d_kind.netif.unit = unit;
+ if (path != NULL)
+ *path = (*cp == 0) ? cp : cp + 1;
+ break;
+
+ default:
+ err = EINVAL;
+ goto fail;
+ }
+ idev->d_dev = dv;
+ idev->d_type = dv->dv_type;
+ if (dev == NULL) {
+ free(idev);
+ } else {
+ *dev = idev;
+ }
+ return(0);
+
+ fail:
+ free(idev);
+ return(err);
+}
+
+
+char *
+efi_fmtdev(void *vdev)
+{
+ struct efi_devdesc *dev = (struct efi_devdesc *)vdev;
+ static char buf[128]; /* XXX device length constant? */
+ char *cp;
+
+ switch(dev->d_type) {
+ case DEVT_NONE:
+ strcpy(buf, "(no device)");
+ break;
+
+ case DEVT_DISK:
+ cp = buf;
+ cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_kind.efidisk.unit);
+ if (dev->d_kind.efidisk.slice > 0)
+ cp += sprintf(cp, "s%d", dev->d_kind.efidisk.slice);
+ if (dev->d_kind.efidisk.partition >= 0)
+ cp += sprintf(cp, "%c", dev->d_kind.efidisk.partition + 'a');
+ strcat(cp, ":");
+ break;
+
+ case DEVT_NET:
+ sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_kind.netif.unit);
+ break;
+ }
+ return(buf);
+}
+
+
+/*
+ * Set currdev to suit the value being supplied in (value)
+ */
+int
+efi_setcurrdev(struct env_var *ev, int flags, void *value)
+{
+ struct efi_devdesc *ncurr;
+ int rv;
+
+ if ((rv = efi_parsedev(&ncurr, value, NULL)) != 0)
+ return(rv);
+ free(ncurr);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ return(0);
+}
+
diff --git a/sys/boot/efi/libefi/efi_console.c b/sys/boot/efi/libefi/efi_console.c
new file mode 100644
index 0000000..c88462e
--- /dev/null
+++ b/sys/boot/efi/libefi/efi_console.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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 <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+
+static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
+static SIMPLE_INPUT_INTERFACE *conin;
+
+static void
+efi_cons_probe(struct console *cp)
+{
+ conout = ST->ConOut;
+ conin = ST->ConIn;
+ cp->c_flags |= C_PRESENTIN | C_PRESENTOUT;
+}
+
+static int
+efi_cons_init(int arg)
+{
+ return 0;
+}
+
+void
+efi_cons_putchar(int c)
+{
+ CHAR16 buf[2];
+
+ if (c == '\n')
+ efi_cons_putchar('\r');
+
+ buf[0] = c;
+ buf[1] = 0;
+
+ conout->OutputString(conout, buf);
+}
+
+int
+efi_cons_getchar()
+{
+ EFI_INPUT_KEY key;
+ EFI_STATUS status;
+ UINTN junk;
+
+ /* Try to read a key stroke. We wait for one if none is pending. */
+ status = conin->ReadKeyStroke(conin, &key);
+ if (status == EFI_NOT_READY) {
+ BS->WaitForEvent(1, &conin->WaitForKey, &junk);
+ status = conin->ReadKeyStroke(conin, &key);
+ }
+ return (key.UnicodeChar);
+}
+
+int
+efi_cons_poll()
+{
+ /* This can clear the signaled state. */
+ return (BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS);
+}
+
+struct console efi_console = {
+ "efi",
+ "EFI console",
+ 0,
+ efi_cons_probe,
+ efi_cons_init,
+ efi_cons_putchar,
+ efi_cons_getchar,
+ efi_cons_poll
+};
diff --git a/sys/boot/efi/libefi/efiboot.h b/sys/boot/efi/libefi/efiboot.h
new file mode 100644
index 0000000..18af3f4
--- /dev/null
+++ b/sys/boot/efi/libefi/efiboot.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * EFI fully-qualified device descriptor
+ */
+struct efi_devdesc {
+ struct devsw *d_dev;
+ int d_type;
+#define DEVT_NONE 0
+#define DEVT_DISK 1
+#define DEVT_NET 2
+ EFI_HANDLE d_handle;
+ union {
+ struct {
+ int unit;
+ int slice;
+ int partition;
+ } efidisk;
+ struct {
+ int unit; /* XXX net layer lives over these? */
+ } netif;
+ } d_kind;
+};
+
+extern int efi_getdev(void **vdev, const char *devspec, const char **path);
+extern char *efi_fmtdev(void *vdev);
+extern int efi_setcurrdev(struct env_var *ev, int flags, void *value);
+
+#define MAXDEV 31 /* maximum number of distinct devices */
+
+typedef unsigned long physaddr_t;
+
+/* exported devices XXX rename? */
+extern struct devsw efifs_dev;
+extern struct devsw efi_disk;
+extern struct netif_driver efi_net;
+
+/* Find EFI network resources */
+extern void efinet_init_driver(void);
+
+/* Map handles to units */
+int efifs_get_unit(EFI_HANDLE);
+
+/* Wrapper over EFI filesystems. */
+extern struct fs_ops efi_fsops;
+
+/* this is in startup code */
+extern void delay(int);
+extern void reboot(void);
+
+extern ssize_t efi_copyin(const void *src, vm_offset_t dest, size_t len);
+extern ssize_t efi_copyout(const vm_offset_t src, void *dest, size_t len);
+extern ssize_t efi_readin(int fd, vm_offset_t dest, size_t len);
+
+extern int efi_boot(void);
+extern int efi_autoload(void);
+
+extern int fpswa_init(u_int64_t *fpswa_interface);
+
+struct bootinfo;
+struct preloaded_file;
+extern int bi_load(struct bootinfo *, struct preloaded_file *,
+ UINTN *mapkey, UINTN pages);
diff --git a/sys/boot/efi/libefi/efifpswa.c b/sys/boot/efi/libefi/efifpswa.c
new file mode 100644
index 0000000..b3bff92
--- /dev/null
+++ b/sys/boot/efi/libefi/efifpswa.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2001 Peter Wemm <peter@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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <stddef.h>
+#include <stand.h>
+#include <stdarg.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include "efiboot.h"
+
+int
+fpswa_init(u_int64_t *fpswa_interface)
+{
+ EFI_STATUS status;
+ static EFI_GUID fpswaid = EFI_INTEL_FPSWA;
+ UINTN sz;
+ EFI_HANDLE fpswa_handle;
+ FPSWA_INTERFACE *fpswa;
+
+ *fpswa_interface = 0;
+ sz = sizeof(EFI_HANDLE);
+ status = BS->LocateHandle(ByProtocol, &fpswaid, 0, &sz, &fpswa_handle);
+ if (EFI_ERROR(status))
+ return ENOENT;
+
+ status = BS->HandleProtocol(fpswa_handle, &fpswaid, (VOID **)&fpswa);
+ if (EFI_ERROR(status))
+ return ENOENT;
+ *fpswa_interface = (u_int64_t)fpswa;
+ return 0;
+}
diff --git a/sys/boot/efi/libefi/efifs.c b/sys/boot/efi/libefi/efifs.c
new file mode 100644
index 0000000..cf89a9d
--- /dev/null
+++ b/sys/boot/efi/libefi/efifs.c
@@ -0,0 +1,401 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <stddef.h>
+#include <stand.h>
+#include <stdarg.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include "efiboot.h"
+
+/* Perform I/O in blocks of size EFI_BLOCK_SIZE. */
+#define EFI_BLOCK_SIZE (1024 * 1024)
+
+static int
+efifs_open(const char *upath, struct open_file *f)
+{
+ struct efi_devdesc *dev = f->f_devdata;
+ static EFI_GUID sfsid = SIMPLE_FILE_SYSTEM_PROTOCOL;
+ EFI_FILE_IO_INTERFACE *sfs;
+ EFI_FILE *root;
+ EFI_FILE *file;
+ EFI_STATUS status;
+ CHAR16 *cp;
+ CHAR16 *path;
+
+ /*
+ * We cannot blindly assume that f->f_devdata points to a
+ * efi_devdesc structure. Before we dereference 'dev', make
+ * sure that the underlying device is ours.
+ */
+ if (f->f_dev != &efifs_dev || dev->d_handle == NULL)
+ return ENOENT;
+
+ status = BS->HandleProtocol(dev->d_handle, &sfsid, (VOID **)&sfs);
+ if (EFI_ERROR(status))
+ return ENOENT;
+
+ /*
+ * Find the root directory.
+ */
+ status = sfs->OpenVolume(sfs, &root);
+
+ /*
+ * Convert path to CHAR16, skipping leading separators.
+ */
+ while (*upath == '/')
+ upath++;
+ if (!*upath) {
+ /* Opening the root directory, */
+ f->f_fsdata = root;
+ return 0;
+ }
+ cp = path = malloc((strlen(upath) + 1) * sizeof(CHAR16));
+ if (path == NULL)
+ return ENOMEM;
+ while (*upath) {
+ if (*upath == '/')
+ *cp = '\\';
+ else
+ *cp = *upath;
+ upath++;
+ cp++;
+ }
+ *cp++ = 0;
+
+ /*
+ * Try to open it.
+ */
+ status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0);
+ free(path);
+ if (EFI_ERROR(status)) {
+ root->Close(root);
+ return ENOENT;
+ }
+
+ root->Close(root);
+ f->f_fsdata = file;
+ return 0;
+}
+
+static int
+efifs_close(struct open_file *f)
+{
+ EFI_FILE *file = f->f_fsdata;
+
+ file->Close(file);
+ return 0;
+}
+
+static int
+efifs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
+{
+ EFI_FILE *file = f->f_fsdata;
+ EFI_STATUS status;
+ UINTN sz = size;
+ char *bufp;
+
+ bufp = buf;
+ while (size > 0) {
+ sz = size;
+ if (sz > EFI_BLOCK_SIZE)
+ sz = EFI_BLOCK_SIZE;
+ status = file->Read(file, &sz, bufp);
+ twiddle();
+ if (EFI_ERROR(status))
+ return EIO;
+ if (sz == 0)
+ break;
+ size -= sz;
+ bufp += sz;
+ }
+ if (resid)
+ *resid = size;
+ return 0;
+}
+
+static int
+efifs_write(struct open_file *f, void *buf, size_t size, size_t *resid)
+{
+ EFI_FILE *file = f->f_fsdata;
+ EFI_STATUS status;
+ UINTN sz = size;
+ char *bufp;
+
+ bufp = buf;
+ while (size > 0) {
+ sz = size;
+ if (sz > EFI_BLOCK_SIZE)
+ sz = EFI_BLOCK_SIZE;
+ status = file->Write(file, &sz, bufp);
+ twiddle();
+ if (EFI_ERROR(status))
+ return EIO;
+ if (sz == 0)
+ break;
+ size -= sz;
+ bufp += sz;
+ }
+ if (resid)
+ *resid = size;
+ return 0;
+}
+
+static off_t
+efifs_seek(struct open_file *f, off_t offset, int where)
+{
+ EFI_FILE *file = f->f_fsdata;
+ EFI_STATUS status;
+ UINT64 base;
+ UINTN sz;
+ static EFI_GUID infoid = EFI_FILE_INFO_ID;
+ EFI_FILE_INFO info;
+
+ switch (where) {
+ case SEEK_SET:
+ base = 0;
+ break;
+
+ case SEEK_CUR:
+ status = file->GetPosition(file, &base);
+ if (EFI_ERROR(status))
+ return -1;
+ break;
+
+ case SEEK_END:
+ sz = sizeof(info);
+ status = file->GetInfo(file, &infoid, &sz, &info);
+ if (EFI_ERROR(status))
+ return -1;
+ base = info.FileSize;
+ break;
+ }
+
+ status = file->SetPosition(file, base + offset);
+ if (EFI_ERROR(status))
+ return -1;
+ file->GetPosition(file, &base);
+
+ return base;
+}
+
+static int
+efifs_stat(struct open_file *f, struct stat *sb)
+{
+ EFI_FILE *file = f->f_fsdata;
+ EFI_STATUS status;
+ char *buf;
+ UINTN sz;
+ static EFI_GUID infoid = EFI_FILE_INFO_ID;
+ EFI_FILE_INFO *info;
+
+ bzero(sb, sizeof(*sb));
+
+ buf = malloc(1024);
+ sz = 1024;
+
+ status = file->GetInfo(file, &infoid, &sz, buf);
+ if (EFI_ERROR(status)) {
+ free(buf);
+ return -1;
+ }
+
+ info = (EFI_FILE_INFO *) buf;
+
+ if (info->Attribute & EFI_FILE_READ_ONLY)
+ sb->st_mode = S_IRUSR;
+ else
+ sb->st_mode = S_IRUSR | S_IWUSR;
+ if (info->Attribute & EFI_FILE_DIRECTORY)
+ sb->st_mode |= S_IFDIR;
+ else
+ sb->st_mode |= S_IFREG;
+ sb->st_size = info->FileSize;
+
+ free(buf);
+ return 0;
+}
+
+static int
+efifs_readdir(struct open_file *f, struct dirent *d)
+{
+ EFI_FILE *file = f->f_fsdata;
+ EFI_STATUS status;
+ char *buf;
+ UINTN sz;
+ EFI_FILE_INFO *info;
+ int i;
+
+ buf = malloc(1024);
+ sz = 1024;
+
+ status = file->Read(file, &sz, buf);
+ if (EFI_ERROR(status) || sz < offsetof(EFI_FILE_INFO, FileName))
+ return ENOENT;
+
+ info = (EFI_FILE_INFO *) buf;
+
+ d->d_fileno = 0;
+ d->d_reclen = sizeof(*d);
+ if (info->Attribute & EFI_FILE_DIRECTORY)
+ d->d_type = DT_DIR;
+ else
+ d->d_type = DT_REG;
+ d->d_namlen = ((info->Size - offsetof(EFI_FILE_INFO, FileName))
+ / sizeof(CHAR16));
+ for (i = 0; i < d->d_namlen; i++)
+ d->d_name[i] = info->FileName[i];
+ d->d_name[i] = 0;
+
+ free(buf);
+ return 0;
+}
+
+struct fs_ops efi_fsops = {
+ "fs",
+ efifs_open,
+ efifs_close,
+ efifs_read,
+ efifs_write,
+ efifs_seek,
+ efifs_stat,
+ efifs_readdir
+};
+
+static EFI_HANDLE *fs_handles;
+UINTN fs_handle_count;
+
+int
+efifs_get_unit(EFI_HANDLE h)
+{
+ UINTN u;
+
+ u = 0;
+ while (u < fs_handle_count && fs_handles[u] != h)
+ u++;
+ return ((u < fs_handle_count) ? u : -1);
+}
+
+static int
+efifs_dev_init(void)
+{
+ EFI_STATUS status;
+ UINTN sz;
+ static EFI_GUID sfsid = SIMPLE_FILE_SYSTEM_PROTOCOL;
+
+ sz = 0;
+ status = BS->LocateHandle(ByProtocol, &sfsid, 0, &sz, 0);
+ if (status != EFI_BUFFER_TOO_SMALL)
+ return ENOENT;
+ fs_handles = (EFI_HANDLE *) malloc(sz);
+ status = BS->LocateHandle(ByProtocol, &sfsid, 0,
+ &sz, fs_handles);
+ if (EFI_ERROR(status)) {
+ free(fs_handles);
+ return ENOENT;
+ }
+ fs_handle_count = sz / sizeof(EFI_HANDLE);
+
+ return 0;
+}
+
+/*
+ * Print information about disks
+ */
+static void
+efifs_dev_print(int verbose)
+{
+ int i;
+ char line[80];
+
+ for (i = 0; i < fs_handle_count; i++) {
+ sprintf(line, " fs%d: EFI filesystem", i);
+ pager_output(line);
+ /* XXX more detail? */
+ pager_output("\n");
+ }
+}
+
+/*
+ * Attempt to open the disk described by (dev) for use by (f).
+ *
+ * Note that the philosophy here is "give them exactly what
+ * they ask for". This is necessary because being too "smart"
+ * about what the user might want leads to complications.
+ * (eg. given no slice or partition value, with a disk that is
+ * sliced - are they after the first BSD slice, or the DOS
+ * slice before it?)
+ */
+static int
+efifs_dev_open(struct open_file *f, ...)
+{
+ va_list args;
+ struct efi_devdesc *dev;
+ int unit;
+
+ va_start(args, f);
+ dev = va_arg(args, struct efi_devdesc*);
+ va_end(args);
+
+ unit = dev->d_kind.efidisk.unit;
+ if (unit < 0 || unit >= fs_handle_count) {
+ printf("attempt to open nonexistent EFI filesystem\n");
+ return(ENXIO);
+ }
+
+ dev->d_handle = fs_handles[unit];
+
+ return 0;
+}
+
+static int
+efifs_dev_close(struct open_file *f)
+{
+
+ return 0;
+}
+
+static int
+efifs_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize)
+{
+ return 0;
+}
+
+struct devsw efifs_dev = {
+ "fs",
+ DEVT_DISK,
+ efifs_dev_init,
+ efifs_dev_strategy,
+ efifs_dev_open,
+ efifs_dev_close,
+ noioctl,
+ efifs_dev_print
+};
diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c
new file mode 100644
index 0000000..85814f9
--- /dev/null
+++ b/sys/boot/efi/libefi/efinet.c
@@ -0,0 +1,267 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include <stand.h>
+#include <net.h>
+#include <netif.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+extern struct netif_driver efi_net;
+
+#ifdef EFINET_DEBUG
+static void
+dump_mode(EFI_SIMPLE_NETWORK_MODE *mode)
+{
+ int i;
+
+ printf("State = %x\n", mode->State);
+ printf("HwAddressSize = %u\n", mode->HwAddressSize);
+ printf("MediaHeaderSize = %u\n", mode->MediaHeaderSize);
+ printf("MaxPacketSize = %u\n", mode->MaxPacketSize);
+ printf("NvRamSize = %u\n", mode->NvRamSize);
+ printf("NvRamAccessSize = %u\n", mode->NvRamAccessSize);
+ printf("ReceiveFilterMask = %x\n", mode->ReceiveFilterMask);
+ printf("ReceiveFilterSetting = %u\n", mode->ReceiveFilterSetting);
+ printf("MaxMCastFilterCount = %u\n", mode->MaxMCastFilterCount);
+ printf("MCastFilterCount = %u\n", mode->MCastFilterCount);
+ printf("MCastFilter = {");
+ for (i = 0; i < mode->MCastFilterCount; i++)
+ printf(" %s", ether_sprintf(mode->MCastFilter[i].Addr));
+ printf(" }\n");
+ printf("CurrentAddress = %s\n",
+ ether_sprintf(mode->CurrentAddress.Addr));
+ printf("BroadcastAddress = %s\n",
+ ether_sprintf(mode->BroadcastAddress.Addr));
+ printf("PermanentAddress = %s\n",
+ ether_sprintf(mode->PermanentAddress.Addr));
+ printf("IfType = %u\n", mode->IfType);
+ printf("MacAddressChangeable = %d\n", mode->MacAddressChangeable);
+ printf("MultipleTxSupported = %d\n", mode->MultipleTxSupported);
+ printf("MediaPresentSupported = %d\n", mode->MediaPresentSupported);
+ printf("MediaPresent = %d\n", mode->MediaPresent);
+}
+#endif
+
+int
+efinet_match(struct netif *nif, void *machdep_hint)
+{
+
+ return (1);
+}
+
+int
+efinet_probe(struct netif *nif, void *machdep_hint)
+{
+
+ return (0);
+}
+
+int
+efinet_put(struct iodesc *desc, void *pkt, size_t len)
+{
+ struct netif *nif = desc->io_netif;
+ EFI_SIMPLE_NETWORK *net;
+ EFI_STATUS status;
+ void *buf;
+
+ net = nif->nif_devdata;
+
+ status = net->Transmit(net, 0, len, pkt, 0, 0, 0);
+ if (status != EFI_SUCCESS)
+ return -1;
+
+ /* Wait for the buffer to be transmitted */
+ do {
+ buf = 0; /* XXX Is this needed? */
+ status = net->GetStatus(net, 0, &buf);
+ /*
+ * XXX EFI1.1 and the E1000 card returns a different
+ * address than we gave. Sigh.
+ */
+ } while (status == EFI_SUCCESS && buf == 0);
+
+ /* XXX How do we deal with status != EFI_SUCCESS now? */
+ return (status == EFI_SUCCESS) ? len : -1;
+}
+
+
+int
+efinet_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout)
+{
+ struct netif *nif = desc->io_netif;
+ EFI_SIMPLE_NETWORK *net;
+ EFI_STATUS status;
+ UINTN bufsz;
+ time_t t;
+ char buf[2048];
+
+ net = nif->nif_devdata;
+
+ t = time(0);
+ while ((time(0) - t) < timeout) {
+ bufsz = sizeof(buf);
+ status = net->Receive(net, 0, &bufsz, buf, 0, 0, 0);
+ if (status == EFI_SUCCESS) {
+ /*
+ * XXX EFI1.1 and the E1000 card trash our
+ * workspace if we do not do this silly copy.
+ * Either they are not respecting the len
+ * value or do not like the alignment.
+ */
+ if (bufsz > len)
+ bufsz = len;
+ bcopy(buf, pkt, bufsz);
+ return bufsz;
+ }
+ if (status != EFI_NOT_READY)
+ return 0;
+ }
+
+ return 0;
+}
+
+void
+efinet_init(struct iodesc *desc, void *machdep_hint)
+{
+ struct netif *nif = desc->io_netif;
+ EFI_SIMPLE_NETWORK *net;
+ EFI_STATUS status;
+
+ net = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private;
+ nif->nif_devdata = net;
+
+ if (net->Mode->State == EfiSimpleNetworkStopped) {
+ status = net->Start(net);
+ if (status != EFI_SUCCESS) {
+ printf("net%d: cannot start interface (status=%ld)\n",
+ nif->nif_unit, status);
+ return;
+ }
+ }
+
+ if (net->Mode->State != EfiSimpleNetworkInitialized) {
+ status = net->Initialize(net, 0, 0);
+ if (status != EFI_SUCCESS) {
+ printf("net%d: cannot init. interface (status=%ld)\n",
+ nif->nif_unit, status);
+ return;
+ }
+ }
+
+ if (net->Mode->ReceiveFilterSetting == 0) {
+ UINT32 mask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
+
+ status = net->ReceiveFilters(net, mask, 0, FALSE, 0, 0);
+ if (status != EFI_SUCCESS) {
+ printf("net%d: cannot set rx. filters (status=%ld)\n",
+ nif->nif_unit, status);
+ return;
+ }
+ }
+
+#ifdef EFINET_DEBUG
+ dump_mode(net->Mode);
+#endif
+
+ bcopy(net->Mode->CurrentAddress.Addr, desc->myea, 6);
+ desc->xid = 1;
+
+ return;
+}
+
+void
+efinet_init_driver()
+{
+ EFI_STATUS status;
+ UINTN sz;
+ static EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
+ EFI_HANDLE *handles;
+ int nifs, i;
+#define MAX_INTERFACES 4
+ static struct netif_dif difs[MAX_INTERFACES];
+ static struct netif_stats stats[MAX_INTERFACES];
+
+ sz = 0;
+ status = BS->LocateHandle(ByProtocol, &netid, 0, &sz, 0);
+ if (status != EFI_BUFFER_TOO_SMALL)
+ return;
+ handles = (EFI_HANDLE *) malloc(sz);
+ status = BS->LocateHandle(ByProtocol, &netid, 0, &sz, handles);
+ if (EFI_ERROR(status)) {
+ free(handles);
+ return;
+ }
+
+ nifs = sz / sizeof(EFI_HANDLE);
+ if (nifs > MAX_INTERFACES)
+ nifs = MAX_INTERFACES;
+
+ efi_net.netif_nifs = nifs;
+ efi_net.netif_ifs = difs;
+
+ bzero(stats, sizeof(stats));
+ for (i = 0; i < nifs; i++) {
+ struct netif_dif *dif = &efi_net.netif_ifs[i];
+ dif->dif_unit = i;
+ dif->dif_nsel = 1;
+ dif->dif_stats = &stats[i];
+
+ BS->HandleProtocol(handles[i], &netid,
+ (VOID**) &dif->dif_private);
+ }
+
+ return;
+}
+
+void
+efinet_end(struct netif *nif)
+{
+ EFI_SIMPLE_NETWORK *net = nif->nif_devdata;
+
+ net->Shutdown(net);
+}
+
+struct netif_driver efi_net = {
+ "net", /* netif_bname */
+ efinet_match, /* netif_match */
+ efinet_probe, /* netif_probe */
+ efinet_init, /* netif_init */
+ efinet_get, /* netif_get */
+ efinet_put, /* netif_put */
+ efinet_end, /* netif_end */
+ 0, /* netif_ifs */
+ 0 /* netif_nifs */
+};
+
diff --git a/sys/boot/efi/libefi/elf_freebsd.c b/sys/boot/efi/libefi/elf_freebsd.c
new file mode 100644
index 0000000..27d2b6e
--- /dev/null
+++ b/sys/boot/efi/libefi/elf_freebsd.c
@@ -0,0 +1,223 @@
+/* $FreeBSD$ */
+/* $NetBSD: loadfile.c,v 1.10 1998/06/25 06:45:46 ross Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)boot.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <stand.h>
+#include <string.h>
+
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <machine/elf.h>
+#include <machine/bootinfo.h>
+#include <machine/ia64_cpu.h>
+#include <machine/pte.h>
+#include <machine/vmparam.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+
+#define _KERNEL
+
+static int elf64_exec(struct preloaded_file *amp);
+
+struct file_format ia64_elf = { elf64_loadfile, elf64_exec };
+
+static __inline u_int64_t
+disable_ic()
+{
+ u_int64_t psr;
+ __asm __volatile("mov %0=psr;;" : "=r" (psr));
+ __asm __volatile("rsm psr.ic|psr.i;; srlz.i;;");
+ return psr;
+}
+
+static __inline void
+restore_ic(u_int64_t psr)
+{
+ __asm __volatile("mov psr.l=%0;; srlz.i" :: "r" (psr));
+}
+
+/*
+ * Entered with psr.ic and psr.i both zero.
+ */
+void
+enter_kernel(u_int64_t start, struct bootinfo *bi)
+{
+ u_int64_t psr;
+
+ __asm __volatile("srlz.i;;");
+ __asm __volatile("mov cr.ipsr=%0"
+ :: "r"(IA64_PSR_IC
+ | IA64_PSR_DT
+ | IA64_PSR_RT
+ | IA64_PSR_IT
+ | IA64_PSR_BN));
+ __asm __volatile("mov cr.iip=%0" :: "r"(start));
+ __asm __volatile("mov cr.ifs=r0;;");
+ __asm __volatile("mov ar.rsc=0;; flushrs;;");
+ __asm __volatile("mov r8=%0" :: "r" (bi));
+ __asm __volatile("rfi;;");
+}
+
+static int
+elf64_exec(struct preloaded_file *fp)
+{
+ struct file_metadata *md;
+ Elf_Ehdr *hdr;
+ struct ia64_pte pte;
+ struct bootinfo *bi;
+ u_int64_t psr;
+ UINTN mapkey, pages, size;
+ UINTN descsz;
+ UINT32 descver;
+ EFI_STATUS status;
+
+ if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
+ return(EFTYPE); /* XXX actually EFUCKUP */
+ hdr = (Elf_Ehdr *)&(md->md_data);
+
+ /*
+ * 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.
+ */
+ size = 0;
+ descsz = sizeof(EFI_MEMORY_DESCRIPTOR);
+ BS->GetMemoryMap(&size, NULL, &mapkey, &descsz, &descver);
+ size += descsz + ((sizeof(struct bootinfo) + 0x0f) & ~0x0f);
+ pages = EFI_SIZE_TO_PAGES(size);
+ status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages,
+ (void*)&bi);
+ if (EFI_ERROR(status)) {
+ printf("unable to create bootinfo block (status=0x%lx)\n",
+ (long)status);
+ return (ENOMEM);
+ }
+
+ bzero(bi, sizeof(struct bootinfo));
+ bi_load(bi, fp, &mapkey, pages);
+
+ printf("Entering %s at 0x%lx...\n", fp->f_name, hdr->e_entry);
+
+ status = BS->ExitBootServices(IH, mapkey);
+ if (EFI_ERROR(status)) {
+ printf("ExitBootServices returned 0x%lx\n", status);
+ return (EINVAL);
+ }
+
+ psr = disable_ic();
+
+ /*
+ * Region 6 is direct mapped UC and region 7 is direct mapped
+ * WC. The details of this is controlled by the Alt {I,D}TLB
+ * handlers. Here we just make sure that they have the largest
+ * possible page size to minimise TLB usage.
+ */
+ ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (28 << 2));
+ ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (28 << 2));
+
+ bzero(&pte, sizeof(pte));
+ pte.pte_p = 1;
+ pte.pte_ma = PTE_MA_WB;
+ pte.pte_a = 1;
+ pte.pte_d = 1;
+ pte.pte_pl = PTE_PL_KERN;
+ pte.pte_ar = PTE_AR_RWX;
+ pte.pte_ppn = 0;
+
+ __asm __volatile("mov cr.ifa=%0" :: "r"(IA64_RR_BASE(7)));
+ __asm __volatile("mov cr.itir=%0" :: "r"(28 << 2));
+ __asm __volatile("ptr.i %0,%1" :: "r"(IA64_RR_BASE(7)), "r"(28<<2));
+ __asm __volatile("ptr.d %0,%1" :: "r"(IA64_RR_BASE(7)), "r"(28<<2));
+ __asm __volatile("srlz.i;;");
+ __asm __volatile("itr.i itr[%0]=%1;;"
+ :: "r"(0), "r"(*(u_int64_t*)&pte));
+ __asm __volatile("srlz.i;;");
+ __asm __volatile("itr.d dtr[%0]=%1;;"
+ :: "r"(0), "r"(*(u_int64_t*)&pte));
+ __asm __volatile("srlz.i;;");
+
+ enter_kernel(hdr->e_entry, bi);
+
+ restore_ic(psr);
+}
diff --git a/sys/boot/efi/libefi/libefi.c b/sys/boot/efi/libefi/libefi.c
new file mode 100644
index 0000000..563b533
--- /dev/null
+++ b/sys/boot/efi/libefi/libefi.c
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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 <efi.h>
+#include <efilib.h>
+#include <stand.h>
+
+EFI_HANDLE IH;
+EFI_SYSTEM_TABLE *ST;
+EFI_BOOT_SERVICES *BS;
+EFI_RUNTIME_SERVICES *RS;
+
+static EFI_PHYSICAL_ADDRESS heap;
+static UINTN heapsize;
+
+static CHAR16 *
+arg_skipsep(CHAR16 *argp)
+{
+
+ while (*argp == ' ' || *argp == '\t')
+ argp++;
+ return (argp);
+}
+
+static CHAR16 *
+arg_skipword(CHAR16 *argp)
+{
+
+ while (*argp && *argp != ' ' && *argp != '\t')
+ argp++;
+ return (argp);
+}
+
+void *
+efi_get_table(EFI_GUID *tbl)
+{
+ EFI_GUID *id;
+ int i;
+
+ for (i = 0; i < ST->NumberOfTableEntries; i++) {
+ id = &ST->ConfigurationTable[i].VendorGuid;
+ if (!memcmp(id, tbl, sizeof(EFI_GUID)))
+ return (ST->ConfigurationTable[i].VendorTable);
+ }
+ return (NULL);
+}
+
+void exit(EFI_STATUS exit_code)
+{
+
+ BS->FreePages(heap, EFI_SIZE_TO_PAGES(heapsize));
+ BS->Exit(IH, exit_code, 0, NULL);
+}
+
+void
+efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
+{
+ static EFI_GUID image_protocol = LOADED_IMAGE_PROTOCOL;
+ EFI_LOADED_IMAGE *img;
+ CHAR16 *argp, *args, **argv;
+ EFI_STATUS status;
+ int argc, addprog;
+
+ IH = image_handle;
+ ST = system_table;
+ BS = ST->BootServices;
+ RS = ST->RuntimeServices;
+
+ heapsize = 512*1024;
+ status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+ EFI_SIZE_TO_PAGES(heapsize), &heap);
+ if (status != EFI_SUCCESS)
+ BS->Exit(IH, status, 0, NULL);
+
+ setheap((void *)heap, (void *)(heap + heapsize));
+
+ /* Use exit() from here on... */
+
+ status = BS->HandleProtocol(IH, &image_protocol, (VOID**)&img);
+ if (status != EFI_SUCCESS)
+ exit(status);
+
+ /*
+ * Pre-process the (optional) load options. If the option string
+ * is given as an ASCII string, we use a poor man's ASCII to
+ * Unicode-16 translation. The size of the option string as given
+ * to us includes the terminating null character. We assume the
+ * string is an ASCII string if strlen() plus the terminating
+ * '\0' is less than LoadOptionsSize. Even if all Unicode-16
+ * characters have the upper 8 bits non-zero, the terminating
+ * null character will cause a one-off.
+ * If the string is already in Unicode-16, we make a copy so that
+ * we know we can always modify the string.
+ */
+ if (img->LoadOptionsSize > 0 && img->LoadOptions != NULL) {
+ if (img->LoadOptionsSize == strlen(img->LoadOptions) + 1) {
+ args = malloc(img->LoadOptionsSize << 1);
+ for (argc = 0; argc < img->LoadOptionsSize; argc++)
+ args[argc] = ((char*)img->LoadOptions)[argc];
+ } else {
+ args = malloc(img->LoadOptionsSize);
+ memcpy(args, img->LoadOptions, img->LoadOptionsSize);
+ }
+ } else
+ args = NULL;
+
+ /*
+ * Use a quick and dirty algorithm to build the argv vector. We
+ * first count the number of words. Then, after allocating the
+ * vector, we split the string up. We don't deal with quotes or
+ * other more advanced shell features.
+ * The EFI shell will pas the name of the image as the first
+ * word in the argument list. This does not happen if we're
+ * loaded by the boot manager. This is not so easy to figure
+ * out though. The ParentHandle is not always NULL, because
+ * there can be a function (=image) that will perform the task
+ * for the boot manager.
+ */
+ /* Part 1: Figure out if we need to add our program name. */
+ addprog = (args == NULL || img->ParentHandle == NULL ||
+ img->FilePath == NULL) ? 1 : 0;
+ if (!addprog) {
+ addprog =
+ (DevicePathType(img->FilePath) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType(img->FilePath) != MEDIA_FILEPATH_DP ||
+ DevicePathNodeLength(img->FilePath) <=
+ sizeof(FILEPATH_DEVICE_PATH)) ? 1 : 0;
+ if (!addprog) {
+ /* XXX todo. */
+ }
+ }
+ /* Part 2: count words. */
+ argc = (addprog) ? 1 : 0;
+ argp = args;
+ while (argp != NULL && *argp != 0) {
+ argp = arg_skipsep(argp);
+ if (*argp == 0)
+ break;
+ argc++;
+ argp = arg_skipword(argp);
+ }
+ /* Part 3: build vector. */
+ argv = malloc((argc + 1) * sizeof(CHAR16*));
+ argc = 0;
+ if (addprog)
+ argv[argc++] = L"loader.efi";
+ argp = args;
+ while (argp != NULL && *argp != 0) {
+ argp = arg_skipsep(argp);
+ if (*argp == 0)
+ break;
+ argv[argc++] = argp;
+ argp = arg_skipword(argp);
+ /* Terminate the words. */
+ if (*argp != 0)
+ *argp++ = 0;
+ }
+ argv[argc] = NULL;
+
+ status = main(argc, argv);
+ exit(status);
+}
diff --git a/sys/boot/efi/libefi/module.c b/sys/boot/efi/libefi/module.c
new file mode 100644
index 0000000..7a3f4b2
--- /dev/null
+++ b/sys/boot/efi/libefi/module.c
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith@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 <stand.h>
+
+/*
+ * Use voodoo to load modules required by current hardware.
+ */
+int
+efi_autoload(void)
+{
+ /* XXX use PnP to locate stuff here */
+ return (0);
+}
diff --git a/sys/boot/efi/libefi/time.c b/sys/boot/efi/libefi/time.c
new file mode 100644
index 0000000..3ca456e
--- /dev/null
+++ b/sys/boot/efi/libefi/time.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1999, 2000
+ * Intel Corporation.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION 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 INTEL CORPORATION 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 <efi.h>
+#include <efilib.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+/*
+// Accurate only for the past couple of centuries;
+// that will probably do.
+//
+// (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h)
+*/
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define SECSPERHOUR ( 60*60 )
+#define SECSPERDAY (24 * SECSPERHOUR)
+
+time_t
+EfiTimeToUnixTime(EFI_TIME *ETime)
+{
+ /*
+ // These arrays give the cumulative number of days up to the first of the
+ // month number used as the index (1 -> 12) for regular and leap years.
+ // The value at index 13 is for the whole year.
+ */
+ static time_t CumulativeDays[2][14] = {
+ {0,
+ 0,
+ 31,
+ 31 + 28,
+ 31 + 28 + 31,
+ 31 + 28 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
+ {0,
+ 0,
+ 31,
+ 31 + 29,
+ 31 + 29 + 31,
+ 31 + 29 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
+
+ time_t UTime;
+ int Year;
+
+ /*
+ // Do a santity check
+ */
+ if ( ETime->Year < 1998 || ETime->Year > 2099 ||
+ ETime->Month == 0 || ETime->Month > 12 ||
+ ETime->Day == 0 || ETime->Month > 31 ||
+ ETime->Hour > 23 ||
+ ETime->Minute > 59 ||
+ ETime->Second > 59 ||
+ ETime->TimeZone < -1440 ||
+ (ETime->TimeZone > 1440 && ETime->TimeZone != 2047) ) {
+ return (0);
+ }
+
+ /*
+ // Years
+ */
+ UTime = 0;
+ for (Year = 1970; Year != ETime->Year; ++Year) {
+ UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY);
+ }
+
+ /*
+ // UTime should now be set to 00:00:00 on Jan 1 of the file's year.
+ //
+ // Months
+ */
+ UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] * SECSPERDAY);
+
+ /*
+ // UTime should now be set to 00:00:00 on the first of the file's month and year
+ //
+ // Days -- Don't count the file's day
+ */
+ UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY);
+
+ /*
+ // Hours
+ */
+ UTime += (ETime->Hour * SECSPERHOUR);
+
+ /*
+ // Minutes
+ */
+ UTime += (ETime->Minute * 60);
+
+ /*
+ // Seconds
+ */
+ UTime += ETime->Second;
+
+ /*
+ // EFI time is repored in local time. Adjust for any time zone offset to
+ // get true UT
+ */
+ if ( ETime->TimeZone != EFI_UNSPECIFIED_TIMEZONE ) {
+ /*
+ // TimeZone is kept in minues...
+ */
+ UTime += (ETime->TimeZone * 60);
+ }
+
+ return UTime;
+}
+
+int
+EFI_GetTimeOfDay(
+ OUT struct timeval *tp,
+ OUT struct timezone *tzp
+ )
+{
+ EFI_TIME EfiTime;
+ EFI_TIME_CAPABILITIES Capabilities;
+ EFI_STATUS Status;
+
+ /*
+ // Get time from EFI
+ */
+
+ Status = RS->GetTime( &EfiTime, &Capabilities );
+ if (EFI_ERROR(Status))
+ return (-1);
+
+ /*
+ // Convert to UNIX time (ie seconds since the epoch
+ */
+
+ tp->tv_sec = EfiTimeToUnixTime( &EfiTime );
+ tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */
+
+ /*
+ // Do something with the timezone if needed
+ */
+
+ if (tzp) {
+ tzp->tz_minuteswest =
+ EfiTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE ? 0 : EfiTime.TimeZone;
+ /*
+ // This isn't quit right since it doesn't deal with EFI_TIME_IN_DAYLIGHT
+ */
+ tzp->tz_dsttime =
+ EfiTime.Daylight & EFI_TIME_ADJUST_DAYLIGHT ? 1 : 0;
+ }
+
+ return (0);
+}
+
+time_t
+time(time_t *tloc)
+{
+ struct timeval tv;
+ EFI_GetTimeOfDay(&tv, 0);
+
+ if (tloc)
+ *tloc = tv.tv_sec;
+ return tv.tv_sec;
+}
+
+time_t
+getsecs()
+{
+ return time(0);
+}
OpenPOWER on IntegriCloud