summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/boot/sys/amd64/include/cpufunc.h74
-rw-r--r--usr/src/boot/sys/amd64/include/frame.h5
-rw-r--r--usr/src/boot/sys/amd64/include/segments.h105
-rw-r--r--usr/src/boot/sys/amd64/include/tss.h69
-rw-r--r--usr/src/boot/sys/boot/common/bootstrap.h2
-rw-r--r--usr/src/boot/sys/boot/common/pnp.c45
-rw-r--r--usr/src/boot/sys/boot/efi/include/Guid/MemoryTypeInformation.h36
-rw-r--r--usr/src/boot/sys/boot/efi/include/Guid/MtcVendor.h31
-rw-r--r--usr/src/boot/sys/boot/efi/include/Guid/ZeroGuid.h25
-rw-r--r--usr/src/boot/sys/boot/efi/include/Protocol/EdidActive.h52
-rw-r--r--usr/src/boot/sys/boot/efi/include/Protocol/EdidDiscovered.h50
-rw-r--r--usr/src/boot/sys/boot/efi/include/Protocol/EdidOverride.h67
-rw-r--r--usr/src/boot/sys/boot/efi/include/efiapi.h3
-rw-r--r--usr/src/boot/sys/boot/efi/include/efidef.h28
-rw-r--r--usr/src/boot/sys/boot/efi/include/efilib.h23
-rw-r--r--usr/src/boot/sys/boot/efi/libefi/Makefile7
-rw-r--r--usr/src/boot/sys/boot/efi/libefi/env.c1160
-rw-r--r--usr/src/boot/sys/boot/efi/libefi/wchar.c72
-rw-r--r--usr/src/boot/sys/boot/efi/loader/Makefile1
-rw-r--r--usr/src/boot/sys/boot/efi/loader/arch/amd64/Makefile.inc8
-rw-r--r--usr/src/boot/sys/boot/efi/loader/arch/amd64/exc.S163
-rw-r--r--usr/src/boot/sys/boot/efi/loader/arch/amd64/ldscript.amd645
-rw-r--r--usr/src/boot/sys/boot/efi/loader/arch/amd64/trap.c407
-rw-r--r--usr/src/boot/sys/boot/efi/loader/arch/arm/ldscript.arm5
-rw-r--r--usr/src/boot/sys/boot/efi/loader/arch/arm64/ldscript.arm645
-rw-r--r--usr/src/boot/sys/boot/efi/loader/arch/i386/ldscript.i3865
-rw-r--r--usr/src/boot/sys/boot/efi/loader/main.c334
-rw-r--r--usr/src/boot/sys/boot/forth/Makefile.inc1
-rw-r--r--usr/src/boot/sys/boot/forth/efi.4th29
-rw-r--r--usr/src/boot/sys/boot/forth/loader.4th3
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/Makefile5
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/biospci.c179
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/libi386.h4
-rw-r--r--usr/src/boot/sys/x86/include/frame.h157
-rw-r--r--usr/src/boot/sys/x86/include/segments.h273
-rw-r--r--usr/src/common/ficl/ficl.h10
-rw-r--r--usr/src/common/ficl/loader.c197
-rw-r--r--usr/src/pkg/manifests/system-boot-loader.mf1
-rw-r--r--usr/src/uts/i86pc/os/cpuid.c6
-rw-r--r--usr/src/uts/intel/ia32/ml/float.s5
-rw-r--r--usr/src/uts/intel/io/pci/pci_resource.c18
-rw-r--r--usr/src/uts/sun4/os/machdep.c2
42 files changed, 3112 insertions, 565 deletions
diff --git a/usr/src/boot/sys/amd64/include/cpufunc.h b/usr/src/boot/sys/amd64/include/cpufunc.h
index f2348739d6..2997d9e79c 100644
--- a/usr/src/boot/sys/amd64/include/cpufunc.h
+++ b/usr/src/boot/sys/amd64/include/cpufunc.h
@@ -11,7 +11,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. 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.
*
@@ -327,6 +327,13 @@ mfence(void)
}
static __inline void
+sfence(void)
+{
+
+ __asm __volatile("sfence" : : : "memory");
+}
+
+static __inline void
ia32_pause(void)
{
__asm __volatile("pause");
@@ -645,12 +652,36 @@ load_gs(u_short sel)
#endif
static __inline void
+bare_lgdt(struct region_descriptor *addr)
+{
+ __asm __volatile("lgdt (%0)" : : "r" (addr));
+}
+
+static __inline void
+sgdt(struct region_descriptor *addr)
+{
+ char *loc;
+
+ loc = (char *)addr;
+ __asm __volatile("sgdt %0" : "=m" (*loc) : : "memory");
+}
+
+static __inline void
lidt(struct region_descriptor *addr)
{
__asm __volatile("lidt (%0)" : : "r" (addr));
}
static __inline void
+sidt(struct region_descriptor *addr)
+{
+ char *loc;
+
+ loc = (char *)addr;
+ __asm __volatile("sidt %0" : "=m" (*loc) : : "memory");
+}
+
+static __inline void
lldt(u_short sel)
{
__asm __volatile("lldt %0" : : "r" (sel));
@@ -662,6 +693,15 @@ ltr(u_short sel)
__asm __volatile("ltr %0" : : "r" (sel));
}
+static __inline uint32_t
+read_tr(void)
+{
+ u_short sel;
+
+ __asm __volatile("str %0" : "=r" (sel));
+ return (sel);
+}
+
static __inline uint64_t
rdr0(void)
{
@@ -719,34 +759,6 @@ load_dr3(uint64_t dr3)
}
static __inline uint64_t
-rdr4(void)
-{
- uint64_t data;
- __asm __volatile("movq %%dr4,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr4(uint64_t dr4)
-{
- __asm __volatile("movq %0,%%dr4" : : "r" (dr4));
-}
-
-static __inline uint64_t
-rdr5(void)
-{
- uint64_t data;
- __asm __volatile("movq %%dr5,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr5(uint64_t dr5)
-{
- __asm __volatile("movq %0,%%dr5" : : "r" (dr5));
-}
-
-static __inline uint64_t
rdr6(void)
{
uint64_t data;
@@ -823,8 +835,6 @@ void load_dr0(uint64_t dr0);
void load_dr1(uint64_t dr1);
void load_dr2(uint64_t dr2);
void load_dr3(uint64_t dr3);
-void load_dr4(uint64_t dr4);
-void load_dr5(uint64_t dr5);
void load_dr6(uint64_t dr6);
void load_dr7(uint64_t dr7);
void load_fs(u_short sel);
@@ -847,8 +857,6 @@ uint64_t rdr0(void);
uint64_t rdr1(void);
uint64_t rdr2(void);
uint64_t rdr3(void);
-uint64_t rdr4(void);
-uint64_t rdr5(void);
uint64_t rdr6(void);
uint64_t rdr7(void);
uint64_t rdtsc(void);
diff --git a/usr/src/boot/sys/amd64/include/frame.h b/usr/src/boot/sys/amd64/include/frame.h
new file mode 100644
index 0000000000..39fa191f38
--- /dev/null
+++ b/usr/src/boot/sys/amd64/include/frame.h
@@ -0,0 +1,5 @@
+/*-
+ * This file is in the public domain.
+ */
+
+#include <x86/frame.h>
diff --git a/usr/src/boot/sys/amd64/include/segments.h b/usr/src/boot/sys/amd64/include/segments.h
new file mode 100644
index 0000000000..c1e423868c
--- /dev/null
+++ b/usr/src/boot/sys/amd64/include/segments.h
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1989, 1990 William F. Jolitz
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 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.
+ *
+ * from: @(#)segments.h 7.1 (Berkeley) 5/9/91
+ */
+
+#ifndef _MACHINE_SEGMENTS_H_
+#define _MACHINE_SEGMENTS_H_
+
+/*
+ * AMD64 Segmentation Data Structures and definitions
+ */
+
+#include <x86/segments.h>
+
+/*
+ * System segment descriptors (128 bit wide)
+ */
+struct system_segment_descriptor {
+ u_int64_t sd_lolimit:16; /* segment extent (lsb) */
+ u_int64_t sd_lobase:24; /* segment base address (lsb) */
+ u_int64_t sd_type:5; /* segment type */
+ u_int64_t sd_dpl:2; /* segment descriptor priority level */
+ u_int64_t sd_p:1; /* segment descriptor present */
+ u_int64_t sd_hilimit:4; /* segment extent (msb) */
+ u_int64_t sd_xx0:3; /* unused */
+ u_int64_t sd_gran:1; /* limit granularity (byte/page units)*/
+ u_int64_t sd_hibase:40 __packed;/* segment base address (msb) */
+ u_int64_t sd_xx1:8;
+ u_int64_t sd_mbz:5; /* MUST be zero */
+ u_int64_t sd_xx2:19;
+} __packed;
+
+/*
+ * Software definitions are in this convenient format,
+ * which are translated into inconvenient segment descriptors
+ * when needed to be used by the 386 hardware
+ */
+
+struct soft_segment_descriptor {
+ unsigned long ssd_base; /* segment base address */
+ unsigned long ssd_limit; /* segment extent */
+ unsigned long ssd_type:5; /* segment type */
+ unsigned long ssd_dpl:2; /* segment descriptor priority level */
+ unsigned long ssd_p:1; /* segment descriptor present */
+ unsigned long ssd_long:1; /* long mode (for %cs) */
+ unsigned long ssd_def32:1; /* default 32 vs 16 bit size */
+ unsigned long ssd_gran:1; /* limit granularity (byte/page units)*/
+} __packed;
+
+/*
+ * region descriptors, used to load gdt/idt tables before segments yet exist.
+ */
+struct region_descriptor {
+ uint64_t rd_limit:16; /* segment extent */
+ uint64_t rd_base:64 __packed; /* base address */
+} __packed;
+
+#ifdef _KERNEL
+extern struct user_segment_descriptor gdt[];
+extern struct soft_segment_descriptor gdt_segs[];
+extern struct gate_descriptor *idt;
+extern struct region_descriptor r_gdt, r_idt;
+
+void lgdt(struct region_descriptor *rdp);
+void sdtossd(struct user_segment_descriptor *sdp,
+ struct soft_segment_descriptor *ssdp);
+void ssdtosd(struct soft_segment_descriptor *ssdp,
+ struct user_segment_descriptor *sdp);
+void ssdtosyssd(struct soft_segment_descriptor *ssdp,
+ struct system_segment_descriptor *sdp);
+void update_gdt_gsbase(struct thread *td, uint32_t base);
+void update_gdt_fsbase(struct thread *td, uint32_t base);
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_SEGMENTS_H_ */
diff --git a/usr/src/boot/sys/amd64/include/tss.h b/usr/src/boot/sys/amd64/include/tss.h
new file mode 100644
index 0000000000..f06a4938c5
--- /dev/null
+++ b/usr/src/boot/sys/amd64/include/tss.h
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 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.
+ *
+ * from: @(#)tss.h 5.4 (Berkeley) 1/18/91
+ */
+
+#ifndef _MACHINE_TSS_H_
+#define _MACHINE_TSS_H_ 1
+
+/*
+ * amd64 Context Data Type
+ *
+ * The alignment is pretty messed up here due to reuse of the original 32 bit
+ * fields. It might be worth trying to set the tss on a +4 byte offset to
+ * make the 64 bit fields aligned in practice.
+ */
+struct amd64tss {
+ u_int32_t tss_rsvd0;
+ u_int64_t tss_rsp0 __packed; /* kernel stack pointer ring 0 */
+ u_int64_t tss_rsp1 __packed; /* kernel stack pointer ring 1 */
+ u_int64_t tss_rsp2 __packed; /* kernel stack pointer ring 2 */
+ u_int32_t tss_rsvd1;
+ u_int32_t tss_rsvd2;
+ u_int64_t tss_ist1 __packed; /* Interrupt stack table 1 */
+ u_int64_t tss_ist2 __packed; /* Interrupt stack table 2 */
+ u_int64_t tss_ist3 __packed; /* Interrupt stack table 3 */
+ u_int64_t tss_ist4 __packed; /* Interrupt stack table 4 */
+ u_int64_t tss_ist5 __packed; /* Interrupt stack table 5 */
+ u_int64_t tss_ist6 __packed; /* Interrupt stack table 6 */
+ u_int64_t tss_ist7 __packed; /* Interrupt stack table 7 */
+ u_int32_t tss_rsvd3;
+ u_int32_t tss_rsvd4;
+ u_int16_t tss_rsvd5;
+ u_int16_t tss_iobase; /* io bitmap offset */
+};
+
+#ifdef _KERNEL
+extern struct amd64tss common_tss[];
+#endif
+
+#endif /* _MACHINE_TSS_H_ */
diff --git a/usr/src/boot/sys/boot/common/bootstrap.h b/usr/src/boot/sys/boot/common/bootstrap.h
index 010dda130e..8b0d9c50f0 100644
--- a/usr/src/boot/sys/boot/common/bootstrap.h
+++ b/usr/src/boot/sys/boot/common/bootstrap.h
@@ -143,8 +143,6 @@ struct pnpinfo
STAILQ_HEAD(pnpinfo_stql, pnpinfo);
-extern struct pnpinfo_stql pnp_devices;
-
extern struct pnphandler *pnphandlers[]; /* provided by MD code */
void pnp_addident(struct pnpinfo *pi, char *ident);
diff --git a/usr/src/boot/sys/boot/common/pnp.c b/usr/src/boot/sys/boot/common/pnp.c
index 589926b590..14b0b965f0 100644
--- a/usr/src/boot/sys/boot/common/pnp.c
+++ b/usr/src/boot/sys/boot/common/pnp.c
@@ -4,7 +4,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
/*
* "Plug and Play" functionality.
@@ -17,8 +16,9 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include <string.h>
#include <bootstrap.h>
+#include "ficl.h"
-struct pnpinfo_stql pnp_devices;
+static struct pnpinfo_stql pnp_devices;
static int pnp_devices_initted = 0;
static void pnp_discard(void);
@@ -182,3 +182,44 @@ pnp_eisaformat(u_int8_t *data)
return(idbuf);
}
+void
+ficlPnpdevices(ficlVm *pVM)
+{
+ static int pnp_devices_initted = 0;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
+
+ if (!pnp_devices_initted) {
+ STAILQ_INIT(&pnp_devices);
+ pnp_devices_initted = 1;
+ }
+
+ ficlStackPushPointer(ficlVmGetDataStack(pVM), &pnp_devices);
+}
+
+void
+ficlPnphandlers(ficlVm *pVM)
+{
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
+
+ ficlStackPushPointer(ficlVmGetDataStack(pVM), pnphandlers);
+}
+
+/*
+ * Glue function to add the appropriate forth words to access pnp BIOS
+ * functionality.
+ */
+static void
+ficlCompilePnp(ficlSystem *pSys)
+{
+ ficlDictionary *dp = ficlSystemGetDictionary(pSys);
+
+ FICL_SYSTEM_ASSERT(pSys, dp);
+
+ ficlDictionarySetPrimitive(dp, "pnpdevices", ficlPnpdevices,
+ FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dp, "pnphandlers", ficlPnphandlers,
+ FICL_WORD_DEFAULT);
+}
+
+FICL_COMPILE_SET(ficlCompilePnp);
diff --git a/usr/src/boot/sys/boot/efi/include/Guid/MemoryTypeInformation.h b/usr/src/boot/sys/boot/efi/include/Guid/MemoryTypeInformation.h
new file mode 100644
index 0000000000..be9c4b5177
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/include/Guid/MemoryTypeInformation.h
@@ -0,0 +1,36 @@
+/** @file
+ This file defines:
+ * Memory Type Information GUID for HOB and Variable.
+ * Memory Type Information Variable Name.
+ * Memory Type Information GUID HOB data structure.
+
+ The memory type information HOB and variable can
+ be used to store the information for each memory type in Variable or HOB.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __MEMORY_TYPE_INFORMATION_GUID_H__
+#define __MEMORY_TYPE_INFORMATION_GUID_H__
+
+#define EFI_MEMORY_TYPE_INFORMATION_GUID \
+ { 0x4c19049f,0x4137,0x4dd3, { 0x9c,0x10,0x8b,0x97,0xa8,0x3f,0xfd,0xfa } }
+
+#define EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME "MemoryTypeInformation"
+
+extern EFI_GUID gEfiMemoryTypeInformationGuid;
+
+typedef struct {
+ UINT32 Type; ///< EFI memory type defined in UEFI specification.
+ UINT32 NumberOfPages; ///< The pages of this type memory.
+} EFI_MEMORY_TYPE_INFORMATION;
+
+#endif
diff --git a/usr/src/boot/sys/boot/efi/include/Guid/MtcVendor.h b/usr/src/boot/sys/boot/efi/include/Guid/MtcVendor.h
new file mode 100644
index 0000000000..3aa774f554
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/include/Guid/MtcVendor.h
@@ -0,0 +1,31 @@
+/** @file
+ GUID is for MTC variable.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __MTC_VENDOR_GUID_H__
+#define __MTC_VENDOR_GUID_H__
+
+//
+// Vendor GUID of the variable for the high part of monotonic counter (UINT32).
+//
+#define MTC_VENDOR_GUID \
+ { 0xeb704011, 0x1402, 0x11d3, { 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } }
+
+//
+// Name of the variable for the high part of monotonic counter
+//
+#define MTC_VARIABLE_NAME "MTC"
+
+extern EFI_GUID gMtcVendorGuid;
+
+#endif
diff --git a/usr/src/boot/sys/boot/efi/include/Guid/ZeroGuid.h b/usr/src/boot/sys/boot/efi/include/Guid/ZeroGuid.h
new file mode 100644
index 0000000000..6de8c3821f
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/include/Guid/ZeroGuid.h
@@ -0,0 +1,25 @@
+/** @file
+ GUID has all zero values.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __ZERO_GUID_H__
+#define __ZERO_GUID_H__
+
+#define ZERO_GUID \
+ { \
+ 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} \
+ }
+
+extern EFI_GUID gZeroGuid;
+
+#endif
diff --git a/usr/src/boot/sys/boot/efi/include/Protocol/EdidActive.h b/usr/src/boot/sys/boot/efi/include/Protocol/EdidActive.h
new file mode 100644
index 0000000000..1f6ff052a9
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/include/Protocol/EdidActive.h
@@ -0,0 +1,52 @@
+/** @file
+ EDID Active Protocol from the UEFI 2.0 specification.
+
+ Placed on the video output device child handle that is actively displaying output.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EDID_ACTIVE_H__
+#define __EDID_ACTIVE_H__
+
+#define EFI_EDID_ACTIVE_PROTOCOL_GUID \
+ { \
+ 0xbd8c1056, 0x9f36, 0x44ec, {0x92, 0xa8, 0xa6, 0x33, 0x7f, 0x81, 0x79, 0x86 } \
+ }
+
+///
+/// This protocol contains the EDID information for an active video output device. This is either the
+/// EDID information retrieved from the EFI_EDID_OVERRIDE_PROTOCOL if an override is
+/// available, or an identical copy of the EDID information from the
+/// EFI_EDID_DISCOVERED_PROTOCOL if no overrides are available.
+///
+typedef struct {
+ ///
+ /// The size, in bytes, of the Edid buffer. 0 if no EDID information
+ /// is available from the video output device. Otherwise, it must be a
+ /// minimum of 128 bytes.
+ ///
+ UINT32 SizeOfEdid;
+
+ ///
+ /// A pointer to a read-only array of bytes that contains the EDID
+ /// information for an active video output device. This pointer is
+ /// NULL if no EDID information is available for the video output
+ /// device. The minimum size of a valid Edid buffer is 128 bytes.
+ /// EDID information is defined in the E-EDID EEPROM
+ /// specification published by VESA (www.vesa.org).
+ ///
+ UINT8 *Edid;
+} EFI_EDID_ACTIVE_PROTOCOL;
+
+extern EFI_GUID gEfiEdidActiveProtocolGuid;
+
+#endif
diff --git a/usr/src/boot/sys/boot/efi/include/Protocol/EdidDiscovered.h b/usr/src/boot/sys/boot/efi/include/Protocol/EdidDiscovered.h
new file mode 100644
index 0000000000..c10b6ee89a
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/include/Protocol/EdidDiscovered.h
@@ -0,0 +1,50 @@
+/** @file
+ EDID Discovered Protocol from the UEFI 2.0 specification.
+
+ This protocol is placed on the video output device child handle. It represents
+ the EDID information being used for the output device represented by the child handle.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EDID_DISCOVERED_H__
+#define __EDID_DISCOVERED_H__
+
+#define EFI_EDID_DISCOVERED_PROTOCOL_GUID \
+ { \
+ 0x1c0c34f6, 0xd380, 0x41fa, {0xa0, 0x49, 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa } \
+ }
+
+///
+/// This protocol contains the EDID information retrieved from a video output device.
+///
+typedef struct {
+ ///
+ /// The size, in bytes, of the Edid buffer. 0 if no EDID information
+ /// is available from the video output device. Otherwise, it must be a
+ /// minimum of 128 bytes.
+ ///
+ UINT32 SizeOfEdid;
+
+ ///
+ /// A pointer to a read-only array of bytes that contains the EDID
+ /// information for an active video output device. This pointer is
+ /// NULL if no EDID information is available for the video output
+ /// device. The minimum size of a valid Edid buffer is 128 bytes.
+ /// EDID information is defined in the E-EDID EEPROM
+ /// specification published by VESA (www.vesa.org).
+ ///
+ UINT8 *Edid;
+} EFI_EDID_DISCOVERED_PROTOCOL;
+
+extern EFI_GUID gEfiEdidDiscoveredProtocolGuid;
+
+#endif
diff --git a/usr/src/boot/sys/boot/efi/include/Protocol/EdidOverride.h b/usr/src/boot/sys/boot/efi/include/Protocol/EdidOverride.h
new file mode 100644
index 0000000000..450c95641f
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/include/Protocol/EdidOverride.h
@@ -0,0 +1,67 @@
+/** @file
+ EDID Override Protocol from the UEFI 2.0 specification.
+
+ Allow platform to provide EDID information to the producer of the Graphics Output
+ protocol.
+
+ Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EDID_OVERRIDE_H__
+#define __EDID_OVERRIDE_H__
+
+#define EFI_EDID_OVERRIDE_PROTOCOL_GUID \
+ { \
+ 0x48ecb431, 0xfb72, 0x45c0, {0xa9, 0x22, 0xf4, 0x58, 0xfe, 0x4, 0xb, 0xd5 } \
+ }
+
+typedef struct _EFI_EDID_OVERRIDE_PROTOCOL EFI_EDID_OVERRIDE_PROTOCOL;
+
+#define EFI_EDID_OVERRIDE_DONT_OVERRIDE 0x01
+#define EFI_EDID_OVERRIDE_ENABLE_HOT_PLUG 0x02
+
+/**
+ Returns policy information and potentially a replacement EDID for the specified video output device.
+
+ @param This The EFI_EDID_OVERRIDE_PROTOCOL instance.
+ @param ChildHandle A child handle produced by the Graphics Output EFI
+ driver that represents a video output device.
+ @param Attributes The attributes associated with ChildHandle video output device.
+ @param EdidSize A pointer to the size, in bytes, of the Edid buffer.
+ @param Edid A pointer to callee allocated buffer that contains the EDID that
+ should be used for ChildHandle. A value of NULL
+ represents no EDID override for ChildHandle.
+
+ @retval EFI_SUCCESS Valid overrides returned for ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle has no overrides.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID)(
+ IN EFI_EDID_OVERRIDE_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle,
+ OUT UINT32 *Attributes,
+ IN OUT UINTN *EdidSize,
+ IN OUT UINT8 **Edid
+ );
+
+///
+/// This protocol is produced by the platform to allow the platform to provide
+/// EDID information to the producer of the Graphics Output protocol.
+///
+struct _EFI_EDID_OVERRIDE_PROTOCOL {
+ EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid;
+};
+
+extern EFI_GUID gEfiEdidOverrideProtocolGuid;
+
+#endif
diff --git a/usr/src/boot/sys/boot/efi/include/efiapi.h b/usr/src/boot/sys/boot/efi/include/efiapi.h
index 347cee92b9..16c598952e 100644
--- a/usr/src/boot/sys/boot/efi/include/efiapi.h
+++ b/usr/src/boot/sys/boot/efi/include/efiapi.h
@@ -858,9 +858,6 @@ typedef struct {
#define HOB_LIST_TABLE_GUID \
{ 0x7739f24c, 0x93d7, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
-#define MEMORY_TYPE_INFORMATION_TABLE_GUID \
- { 0x4c19049f, 0x4137, 0x4dd3, {0x9c, 0x10, 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa} }
-
#define DEBUG_IMAGE_INFO_TABLE_GUID \
{ 0x49152e77, 0x1ada, 0x4764, {0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b} }
diff --git a/usr/src/boot/sys/boot/efi/include/efidef.h b/usr/src/boot/sys/boot/efi/include/efidef.h
index 8ab963aabe..4c075b0e2e 100644
--- a/usr/src/boot/sys/boot/efi/include/efidef.h
+++ b/usr/src/boot/sys/boot/efi/include/efidef.h
@@ -170,25 +170,29 @@ typedef enum {
EfiMemoryMappedIO,
EfiMemoryMappedIOPortSpace,
EfiPalCode,
+ EfiPersistentMemory,
EfiMaxMemoryType
} EFI_MEMORY_TYPE;
// possible caching types for the memory range
-#define EFI_MEMORY_UC 0x0000000000000001
-#define EFI_MEMORY_WC 0x0000000000000002
-#define EFI_MEMORY_WT 0x0000000000000004
-#define EFI_MEMORY_WB 0x0000000000000008
-#define EFI_MEMORY_UCE 0x0000000000000010
-
-// physical memory protection on range
-#define EFI_MEMORY_WP 0x0000000000001000
-#define EFI_MEMORY_RP 0x0000000000002000
-#define EFI_MEMORY_XP 0x0000000000004000
+#define EFI_MEMORY_UC 0x0000000000000001
+#define EFI_MEMORY_WC 0x0000000000000002
+#define EFI_MEMORY_WT 0x0000000000000004
+#define EFI_MEMORY_WB 0x0000000000000008
+#define EFI_MEMORY_UCE 0x0000000000000010
+
+// physical memory protection on range
+#define EFI_MEMORY_WP 0x0000000000001000
+#define EFI_MEMORY_RP 0x0000000000002000
+#define EFI_MEMORY_XP 0x0000000000004000
+#define EFI_MEMORY_NV 0x0000000000008000
+#define EFI_MEMORY_MORE_RELIABLE 0x0000000000010000
+#define EFI_MEMORY_RO 0x0000000000020000
// range requires a runtime mapping
-#define EFI_MEMORY_RUNTIME 0x8000000000000000
+#define EFI_MEMORY_RUNTIME 0x8000000000000000
-#define EFI_MEMORY_DESCRIPTOR_VERSION 1
+#define EFI_MEMORY_DESCRIPTOR_VERSION 1
typedef struct {
UINT32 Type; // Field size is 32 bits followed by 32 bit pad
UINT32 Pad;
diff --git a/usr/src/boot/sys/boot/efi/include/efilib.h b/usr/src/boot/sys/boot/efi/include/efilib.h
index de9e692e74..6a94fd172a 100644
--- a/usr/src/boot/sys/boot/efi/include/efilib.h
+++ b/usr/src/boot/sys/boot/efi/include/efilib.h
@@ -25,7 +25,11 @@
* SUCH DAMAGE.
*/
+#ifndef _LOADER_EFILIB_H
+#define _LOADER_EFILIB_H
+
#include <stand.h>
+#include <stdbool.h>
extern EFI_HANDLE IH;
extern EFI_SYSTEM_TABLE *ST;
@@ -60,3 +64,22 @@ void efi_time_fini(void);
EFI_STATUS main(int argc, CHAR16 *argv[]);
void exit(EFI_STATUS status);
void delay(int usecs);
+
+/* EFI environment initialization. */
+void efi_init_environment(void);
+
+/* EFI Memory type strings. */
+const char *efi_memory_type(EFI_MEMORY_TYPE);
+
+/* CHAR16 utility functions. */
+int wcscmp(CHAR16 *, CHAR16 *);
+void cpy8to16(const char *, CHAR16 *, size_t);
+void cpy16to8(const CHAR16 *, char *, size_t);
+
+/* guids and names */
+bool efi_guid_to_str(const EFI_GUID *, char **);
+bool efi_str_to_guid(const char *, EFI_GUID *);
+bool efi_name_to_guid(const char *, EFI_GUID *);
+bool efi_guid_to_name(EFI_GUID *, char **);
+
+#endif /* _LOADER_EFILIB_H */
diff --git a/usr/src/boot/sys/boot/efi/libefi/Makefile b/usr/src/boot/sys/boot/efi/libefi/Makefile
index 39923b58b7..228203f701 100644
--- a/usr/src/boot/sys/boot/efi/libefi/Makefile
+++ b/usr/src/boot/sys/boot/efi/libefi/Makefile
@@ -24,8 +24,8 @@ all: lib$(LIB).a
install:
-SRCS= delay.c devpath.c efi_console.c efinet.c efipart.c errno.c handles.c \
- libefi.c time.c
+SRCS= delay.c devpath.c efi_console.c efinet.c efipart.c env.c errno.c \
+ handles.c libefi.c time.c wchar.c
#.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
#SRCS += time.c
@@ -35,7 +35,7 @@ SRCS= delay.c devpath.c efi_console.c efinet.c efipart.c errno.c handles.c \
OBJS= $(SRCS:%.c=%.o)
-CPPFLAGS= -DTERM_EMU
+CPPFLAGS= -DTERM_EMU -DSTAND
CFLAGS = -O2
#.if ${MACHINE_CPUARCH} == "aarch64"
@@ -46,6 +46,7 @@ CFLAGS += -fPIC
#.endif
CFLAGS += -nostdinc -I. -I../../../../include -I../../..
+CFLAGS += -I$(SRC)/common/ficl -I../../ficl
CFLAGS += -I../include
CFLAGS += -I../include/${MACH64}
CFLAGS += -I../../../../lib/libstand
diff --git a/usr/src/boot/sys/boot/efi/libefi/env.c b/usr/src/boot/sys/boot/efi/libefi/env.c
new file mode 100644
index 0000000000..bd92324021
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/libefi/env.c
@@ -0,0 +1,1160 @@
+/*
+ * Copyright (c) 2015 Netflix, Inc. 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>
+
+#include <stand.h>
+#include <string.h>
+#include <efi.h>
+#include <efilib.h>
+#include <efigpt.h> /* Partition GUIDS */
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/MtcVendor.h>
+#include <Guid/ZeroGuid.h>
+#include <Protocol/EdidActive.h>
+#include <Protocol/EdidDiscovered.h>
+#include <uuid.h>
+#include <stdbool.h>
+#include <sys/param.h>
+#include "bootstrap.h"
+#include "ficl.h"
+
+static struct efi_uuid_mapping {
+ const char *efi_guid_name;
+ EFI_GUID efi_guid;
+} efi_uuid_mapping[] = {
+ { .efi_guid_name = "global", .efi_guid = EFI_GLOBAL_VARIABLE },
+ /* EFI Systab entry names. */
+ { .efi_guid_name = "MPS Table", .efi_guid = MPS_TABLE_GUID },
+ { .efi_guid_name = "ACPI Table", .efi_guid = ACPI_TABLE_GUID },
+ { .efi_guid_name = "ACPI 2.0 Table", .efi_guid = ACPI_20_TABLE_GUID },
+ { .efi_guid_name = "SMBIOS Table", .efi_guid = SMBIOS_TABLE_GUID },
+ { .efi_guid_name = "SMBIOS3 Table", .efi_guid = SMBIOS3_TABLE_GUID },
+ { .efi_guid_name = "DXE Table", .efi_guid = DXE_SERVICES_TABLE_GUID },
+ { .efi_guid_name = "HOB List Table", .efi_guid = HOB_LIST_TABLE_GUID },
+ { .efi_guid_name = EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+ .efi_guid = EFI_MEMORY_TYPE_INFORMATION_GUID },
+ { .efi_guid_name = "Debug Image Info Table",
+ .efi_guid = DEBUG_IMAGE_INFO_TABLE_GUID },
+ { .efi_guid_name = "FDT Table", .efi_guid = FDT_TABLE_GUID },
+ /*
+ * Protocol names for debug purposes.
+ * Can be removed along with lsefi command.
+ */
+ { .efi_guid_name = "device path", .efi_guid = DEVICE_PATH_PROTOCOL },
+ { .efi_guid_name = "block io", .efi_guid = BLOCK_IO_PROTOCOL },
+ { .efi_guid_name = "disk io", .efi_guid = DISK_IO_PROTOCOL },
+ { .efi_guid_name = "disk info", .efi_guid =
+ EFI_DISK_INFO_PROTOCOL_GUID },
+ { .efi_guid_name = "simple fs",
+ .efi_guid = SIMPLE_FILE_SYSTEM_PROTOCOL },
+ { .efi_guid_name = "load file", .efi_guid = LOAD_FILE_PROTOCOL },
+ { .efi_guid_name = "device io", .efi_guid = DEVICE_IO_PROTOCOL },
+ { .efi_guid_name = "unicode collation",
+ .efi_guid = UNICODE_COLLATION_PROTOCOL },
+ { .efi_guid_name = "unicode collation2",
+ .efi_guid = EFI_UNICODE_COLLATION2_PROTOCOL_GUID },
+ { .efi_guid_name = "simple network",
+ .efi_guid = EFI_SIMPLE_NETWORK_PROTOCOL },
+ { .efi_guid_name = "simple text output",
+ .efi_guid = SIMPLE_TEXT_OUTPUT_PROTOCOL },
+ { .efi_guid_name = "simple text input",
+ .efi_guid = SIMPLE_TEXT_INPUT_PROTOCOL },
+ { .efi_guid_name = "simple text ex input",
+ .efi_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID },
+ { .efi_guid_name = "console control",
+ .efi_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID },
+ { .efi_guid_name = "stdin", .efi_guid = EFI_CONSOLE_IN_DEVICE_GUID },
+ { .efi_guid_name = "stdout", .efi_guid = EFI_CONSOLE_OUT_DEVICE_GUID },
+ { .efi_guid_name = "stderr",
+ .efi_guid = EFI_STANDARD_ERROR_DEVICE_GUID },
+ { .efi_guid_name = "GOP",
+ .efi_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID },
+ { .efi_guid_name = "UGA draw", .efi_guid = EFI_UGA_DRAW_PROTOCOL_GUID },
+ { .efi_guid_name = "PXE base code",
+ .efi_guid = EFI_PXE_BASE_CODE_PROTOCOL },
+ { .efi_guid_name = "PXE base code callback",
+ .efi_guid = EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL },
+ { .efi_guid_name = "serial io", .efi_guid = SERIAL_IO_PROTOCOL },
+ { .efi_guid_name = "loaded image", .efi_guid = LOADED_IMAGE_PROTOCOL },
+ { .efi_guid_name = "loaded image device path",
+ .efi_guid = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID },
+ { .efi_guid_name = "ISA io", .efi_guid = EFI_ISA_IO_PROTOCOL_GUID },
+ { .efi_guid_name = "IDE controller init",
+ .efi_guid = EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID },
+ { .efi_guid_name = "ISA ACPI", .efi_guid = EFI_ISA_ACPI_PROTOCOL_GUID },
+ { .efi_guid_name = "PCI", .efi_guid = EFI_PCI_IO_PROTOCOL_GUID },
+ { .efi_guid_name = "PCI root", .efi_guid = EFI_PCI_ROOT_IO_GUID },
+ { .efi_guid_name = "PCI enumeration",
+ .efi_guid = EFI_PCI_ENUMERATION_COMPLETE_GUID },
+ { .efi_guid_name = "Driver diagnostics",
+ .efi_guid = EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID },
+ { .efi_guid_name = "Driver diagnostics2",
+ .efi_guid = EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID },
+ { .efi_guid_name = "simple pointer",
+ .efi_guid = EFI_SIMPLE_POINTER_PROTOCOL_GUID },
+ { .efi_guid_name = "absolute pointer",
+ .efi_guid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID },
+ { .efi_guid_name = "VLAN config",
+ .efi_guid = EFI_VLAN_CONFIG_PROTOCOL_GUID },
+ { .efi_guid_name = "ARP service binding",
+ .efi_guid = EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID },
+ { .efi_guid_name = "ARP", .efi_guid = EFI_ARP_PROTOCOL_GUID },
+ { .efi_guid_name = "IPv4 service binding",
+ .efi_guid = EFI_IP4_SERVICE_BINDING_PROTOCOL },
+ { .efi_guid_name = "IPv4", .efi_guid = EFI_IP4_PROTOCOL },
+ { .efi_guid_name = "IPv4 config",
+ .efi_guid = EFI_IP4_CONFIG_PROTOCOL_GUID },
+ { .efi_guid_name = "IPv6 service binding",
+ .efi_guid = EFI_IP6_SERVICE_BINDING_PROTOCOL },
+ { .efi_guid_name = "IPv6", .efi_guid = EFI_IP6_PROTOCOL },
+ { .efi_guid_name = "IPv6 config",
+ .efi_guid = EFI_IP6_CONFIG_PROTOCOL_GUID },
+ { .efi_guid_name = "UDPv4", .efi_guid = EFI_UDP4_PROTOCOL },
+ { .efi_guid_name = "UDPv4 service binding",
+ .efi_guid = EFI_UDP4_SERVICE_BINDING_PROTOCOL },
+ { .efi_guid_name = "UDPv6", .efi_guid = EFI_UDP6_PROTOCOL },
+ { .efi_guid_name = "UDPv6 service binding",
+ .efi_guid = EFI_UDP6_SERVICE_BINDING_PROTOCOL },
+ { .efi_guid_name = "TCPv4", .efi_guid = EFI_TCP4_PROTOCOL },
+ { .efi_guid_name = "TCPv4 service binding",
+ .efi_guid = EFI_TCP4_SERVICE_BINDING_PROTOCOL },
+ { .efi_guid_name = "TCPv6", .efi_guid = EFI_TCP6_PROTOCOL },
+ { .efi_guid_name = "TCPv6 service binding",
+ .efi_guid = EFI_TCP6_SERVICE_BINDING_PROTOCOL },
+ { .efi_guid_name = "EFI System partition",
+ .efi_guid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID },
+ { .efi_guid_name = "MBR legacy",
+ .efi_guid = EFI_PART_TYPE_LEGACY_MBR_GUID },
+ { .efi_guid_name = "device tree", .efi_guid = EFI_DEVICE_TREE_GUID },
+ { .efi_guid_name = "USB io", .efi_guid = EFI_USB_IO_PROTOCOL_GUID },
+ { .efi_guid_name = "USB2 HC", .efi_guid = EFI_USB2_HC_PROTOCOL_GUID },
+ { .efi_guid_name = "component name",
+ .efi_guid = EFI_COMPONENT_NAME_PROTOCOL_GUID },
+ { .efi_guid_name = "component name2",
+ .efi_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID },
+ { .efi_guid_name = "driver binding",
+ .efi_guid = EFI_DRIVER_BINDING_PROTOCOL_GUID },
+ { .efi_guid_name = "driver configuration",
+ .efi_guid = EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID },
+ { .efi_guid_name = "driver configuration2",
+ .efi_guid = EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID },
+ { .efi_guid_name = "decompress",
+ .efi_guid = EFI_DECOMPRESS_PROTOCOL_GUID },
+ { .efi_guid_name = "ebc interpreter",
+ .efi_guid = EFI_EBC_INTERPRETER_PROTOCOL_GUID },
+ { .efi_guid_name = "network interface identifier",
+ .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL },
+ { .efi_guid_name = "network interface identifier_31",
+ .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_31 },
+ { .efi_guid_name = "managed network service binding",
+ .efi_guid = EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID },
+ { .efi_guid_name = "managed network",
+ .efi_guid = EFI_MANAGED_NETWORK_PROTOCOL_GUID },
+ { .efi_guid_name = "form browser",
+ .efi_guid = EFI_FORM_BROWSER2_PROTOCOL_GUID },
+ { .efi_guid_name = "HII config routing",
+ .efi_guid = EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID },
+ { .efi_guid_name = "HII database",
+ .efi_guid = EFI_HII_DATABASE_PROTOCOL_GUID },
+ { .efi_guid_name = "HII string",
+ .efi_guid = EFI_HII_STRING_PROTOCOL_GUID },
+ { .efi_guid_name = "HII image",
+ .efi_guid = EFI_HII_IMAGE_PROTOCOL_GUID },
+ { .efi_guid_name = "HII font", .efi_guid = EFI_HII_FONT_PROTOCOL_GUID },
+ { .efi_guid_name = "HII config",
+ .efi_guid = EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID },
+ { .efi_guid_name = "MTFTP4 service binding",
+ .efi_guid = EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID },
+ { .efi_guid_name = "MTFTP4", .efi_guid = EFI_MTFTP4_PROTOCOL_GUID },
+ { .efi_guid_name = "MTFTP6 service binding",
+ .efi_guid = EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID },
+ { .efi_guid_name = "MTFTP6", .efi_guid = EFI_MTFTP6_PROTOCOL_GUID },
+ { .efi_guid_name = "DHCP4 service binding",
+ .efi_guid = EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID },
+ { .efi_guid_name = "DHCP4", .efi_guid = EFI_DHCP4_PROTOCOL_GUID },
+ { .efi_guid_name = "DHCP6 service binding",
+ .efi_guid = EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID },
+ { .efi_guid_name = "DHCP6", .efi_guid = EFI_DHCP6_PROTOCOL_GUID },
+ { .efi_guid_name = "SCSI io", .efi_guid = EFI_SCSI_IO_PROTOCOL_GUID },
+ { .efi_guid_name = "SCSI pass thru",
+ .efi_guid = EFI_SCSI_PASS_THRU_PROTOCOL_GUID },
+ { .efi_guid_name = "SCSI pass thru ext",
+ .efi_guid = EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID },
+ { .efi_guid_name = "Capsule arch",
+ .efi_guid = EFI_CAPSULE_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "monotonic counter arch",
+ .efi_guid = EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "realtime clock arch",
+ .efi_guid = EFI_REALTIME_CLOCK_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "variable arch",
+ .efi_guid = EFI_VARIABLE_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "variable write arch",
+ .efi_guid = EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "watchdog timer arch",
+ .efi_guid = EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "ACPI support",
+ .efi_guid = EFI_ACPI_SUPPORT_PROTOCOL_GUID },
+ { .efi_guid_name = "BDS arch", .efi_guid = EFI_BDS_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "metronome arch",
+ .efi_guid = EFI_METRONOME_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "timer arch",
+ .efi_guid = EFI_TIMER_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "DPC", .efi_guid = EFI_DPC_PROTOCOL_GUID },
+ { .efi_guid_name = "print2", .efi_guid = EFI_PRINT2_PROTOCOL_GUID },
+ { .efi_guid_name = "device path to text",
+ .efi_guid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID },
+ { .efi_guid_name = "reset arch",
+ .efi_guid = EFI_RESET_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "CPU arch", .efi_guid = EFI_CPU_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "CPU IO2", .efi_guid = EFI_CPU_IO2_PROTOCOL_GUID },
+ { .efi_guid_name = "Legacy 8259",
+ .efi_guid = EFI_LEGACY_8259_PROTOCOL_GUID },
+ { .efi_guid_name = "Security arch",
+ .efi_guid = EFI_SECURITY_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "Security2 arch",
+ .efi_guid = EFI_SECURITY2_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "Runtime arch",
+ .efi_guid = EFI_RUNTIME_ARCH_PROTOCOL_GUID },
+ { .efi_guid_name = "status code runtime",
+ .efi_guid = EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID },
+ { .efi_guid_name = "data hub", .efi_guid = EFI_DATA_HUB_PROTOCOL_GUID },
+ { .efi_guid_name = "PCD", .efi_guid = PCD_PROTOCOL_GUID },
+ { .efi_guid_name = "EFI PCD", .efi_guid = EFI_PCD_PROTOCOL_GUID },
+ { .efi_guid_name = "firmware volume block",
+ .efi_guid = EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID },
+ { .efi_guid_name = "firmware volume2",
+ .efi_guid = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID },
+ { .efi_guid_name = "firmware volume dispatch",
+ .efi_guid = EFI_FIRMWARE_VOLUME_DISPATCH_PROTOCOL_GUID },
+ { .efi_guid_name = "lzma compress", .efi_guid = LZMA_COMPRESS_GUID },
+ { .efi_guid_name = "MP services",
+ .efi_guid = EFI_MP_SERVICES_PROTOCOL_GUID },
+ { .efi_guid_name = MTC_VARIABLE_NAME, .efi_guid = MTC_VENDOR_GUID },
+ { .efi_guid_name = "RTC", .efi_guid = { 0x378D7B65, 0x8DA9, 0x4773,
+ { 0xB6, 0xE4, 0xA4, 0x78, 0x26, 0xA8, 0x33, 0xE1} } },
+ { .efi_guid_name = "Active EDID",
+ .efi_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID },
+ { .efi_guid_name = "Discovered EDID",
+ .efi_guid = EFI_EDID_DISCOVERED_PROTOCOL_GUID }
+};
+
+bool
+efi_guid_to_str(const EFI_GUID *guid, char **sp)
+{
+ uint32_t status;
+
+ uuid_to_string((const uuid_t *)guid, sp, &status);
+ return (status == uuid_s_ok ? true : false);
+}
+
+bool
+efi_str_to_guid(const char *s, EFI_GUID *guid)
+{
+ uint32_t status;
+
+ uuid_from_string(s, (uuid_t *)guid, &status);
+ return (status == uuid_s_ok ? true : false);
+}
+
+bool
+efi_name_to_guid(const char *name, EFI_GUID *guid)
+{
+ uint32_t i;
+
+ for (i = 0; i < nitems(efi_uuid_mapping); i++) {
+ if (strcasecmp(name, efi_uuid_mapping[i].efi_guid_name) == 0) {
+ *guid = efi_uuid_mapping[i].efi_guid;
+ return (true);
+ }
+ }
+ return (efi_str_to_guid(name, guid));
+}
+
+bool
+efi_guid_to_name(EFI_GUID *guid, char **name)
+{
+ uint32_t i;
+ int rv;
+
+ for (i = 0; i < nitems(efi_uuid_mapping); i++) {
+ rv = uuid_equal((uuid_t *)guid,
+ (uuid_t *)&efi_uuid_mapping[i].efi_guid, NULL);
+ if (rv != 0) {
+ *name = strdup(efi_uuid_mapping[i].efi_guid_name);
+ if (*name == NULL)
+ return (false);
+ return (true);
+ }
+ }
+ return (efi_guid_to_str(guid, name));
+}
+
+/*
+ * Simple wrappers to the underlying UEFI functions.
+ * See http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES
+ * for details.
+ */
+EFI_STATUS
+efi_get_next_variable_name(UINTN *variable_name_size, CHAR16 *variable_name,
+ EFI_GUID *vendor_guid)
+{
+ return (RS->GetNextVariableName(variable_name_size, variable_name,
+ vendor_guid));
+}
+
+EFI_STATUS
+efi_get_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid,
+ UINT32 *attributes, UINTN *data_size, void *data)
+{
+ return (RS->GetVariable(variable_name, vendor_guid, attributes,
+ data_size, data));
+}
+
+EFI_STATUS
+efi_set_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid,
+ UINT32 attributes, UINTN data_size, void *data)
+{
+ return (RS->SetVariable(variable_name, vendor_guid, attributes,
+ data_size, data));
+}
+
+void
+efi_init_environment(void)
+{
+ char var[128];
+
+ snprintf(var, sizeof(var), "%d.%02d", ST->Hdr.Revision >> 16,
+ ST->Hdr.Revision & 0xffff);
+ env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset);
+}
+
+COMMAND_SET(efishow, "efi-show", "print some or all EFI variables", command_efi_show);
+
+static int
+efi_print_other_value(uint8_t *data, UINTN datasz)
+{
+ UINTN i;
+ bool is_ascii = true;
+
+ printf(" = ");
+ for (i = 0; i < datasz - 1; i++) {
+ /*
+ * Quick hack to see if this ascii-ish string is printable
+ * range plus tab, cr and lf.
+ */
+ if ((data[i] < 32 || data[i] > 126)
+ && data[i] != 9 && data[i] != 10 && data[i] != 13) {
+ is_ascii = false;
+ break;
+ }
+ }
+ if (data[datasz - 1] != '\0')
+ is_ascii = false;
+ if (is_ascii == true) {
+ printf("%s", data);
+ if (pager_output("\n"))
+ return (CMD_WARN);
+ } else {
+ if (pager_output("\n"))
+ return (CMD_WARN);
+ /*
+ * Dump hex bytes grouped by 4.
+ */
+ for (i = 0; i < datasz; i++) {
+ printf("%02x ", data[i]);
+ if ((i + 1) % 4 == 0)
+ printf(" ");
+ if ((i + 1) % 20 == 0) {
+ if (pager_output("\n"))
+ return (CMD_WARN);
+ }
+ }
+ if (pager_output("\n"))
+ return (CMD_WARN);
+ }
+
+ return (CMD_OK);
+}
+
+/* This appears to be some sort of UEFI shell alias table. */
+static int
+efi_print_shell_str(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
+{
+ printf(" = %S", (CHAR16 *)data);
+ if (pager_output("\n"))
+ return (CMD_WARN);
+ return (CMD_OK);
+}
+
+const char *
+efi_memory_type(EFI_MEMORY_TYPE type)
+{
+ const char *types[] = {
+ "Reserved",
+ "LoaderCode",
+ "LoaderData",
+ "BootServicesCode",
+ "BootServicesData",
+ "RuntimeServicesCode",
+ "RuntimeServicesData",
+ "ConventionalMemory",
+ "UnusableMemory",
+ "ACPIReclaimMemory",
+ "ACPIMemoryNVS",
+ "MemoryMappedIO",
+ "MemoryMappedIOPortSpace",
+ "PalCode",
+ "PersistentMemory"
+ };
+ switch (type) {
+ case EfiReservedMemoryType:
+ case EfiLoaderCode:
+ case EfiLoaderData:
+ case EfiBootServicesCode:
+ case EfiBootServicesData:
+ case EfiRuntimeServicesCode:
+ case EfiRuntimeServicesData:
+ case EfiConventionalMemory:
+ case EfiUnusableMemory:
+ case EfiACPIReclaimMemory:
+ case EfiACPIMemoryNVS:
+ case EfiMemoryMappedIO:
+ case EfiMemoryMappedIOPortSpace:
+ case EfiPalCode:
+ case EfiPersistentMemory:
+ return (types[type]);
+ }
+ return ("Unknown");
+}
+
+/* Print memory type table. */
+static int
+efi_print_mem_type(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
+{
+ int i, n;
+ EFI_MEMORY_TYPE_INFORMATION *ti;
+
+ ti = (EFI_MEMORY_TYPE_INFORMATION *)data;
+ if (pager_output(" = \n"))
+ return (CMD_WARN);
+
+ n = datasz / sizeof (EFI_MEMORY_TYPE_INFORMATION);
+ for (i = 0; i < n && ti[i].NumberOfPages != 0; i++) {
+ printf("\t%23s pages: %u", efi_memory_type(ti[i].Type),
+ ti[i].NumberOfPages);
+ if (pager_output("\n"))
+ return (CMD_WARN);
+ }
+
+ return (CMD_OK);
+}
+
+/* Print global variables. */
+static int
+efi_print_global(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
+{
+ int len;
+ int rv = -1;
+ char *var;
+
+ for (len = 0; varnamearg[len] != 0; len++)
+ ;
+
+ if (len == 0)
+ return (CMD_OK);
+ len++;
+
+ if ((var = malloc(len)) == NULL)
+ return (CMD_ERROR);
+ cpy16to8(varnamearg, var, len);
+
+ if (strcmp("AuditMode", var) == 0) {
+ printf(" = ");
+ printf("0x%x", *data); /* 8-bit int */
+ goto done;
+ }
+
+ if (strcmp("BootOptionSupport", var) == 0) {
+ printf(" = ");
+ printf("0x%x", *((uint32_t *)data)); /* UINT32 */
+ goto done;
+ }
+
+ if (strcmp("BootCurrent", var) == 0 ||
+ strcmp("BootNext", var) == 0 ||
+ strcmp("Timeout", var) == 0) {
+ printf(" = ");
+ printf("%u", *((uint16_t *)data)); /* UINT16 */
+ goto done;
+ }
+
+ if (strcmp("BootOrder", var) == 0 ||
+ strcmp("DriverOrder", var) == 0) {
+ int i;
+ UINT16 *u16 = (UINT16 *)data;
+
+ printf(" =");
+ for (i = 0; i < datasz / sizeof (UINT16); i++)
+ printf(" %u", u16[i]);
+ goto done;
+ }
+ if (strncmp("Boot", var, 4) == 0 ||
+ strncmp("Driver", var, 5) == 0 ||
+ strncmp("SysPrep", var, 7) == 0 ||
+ strncmp("OsRecovery", var, 10) == 0) {
+ UINT32 attr;
+ UINT16 filepathlistlen;
+ CHAR16 *text;
+ int desclen;
+ EFI_DEVICE_PATH *dp;
+
+ attr = *(uint32_t *)data;
+ data += sizeof(UINT32);
+ filepathlistlen = *(uint16_t *)data;
+ data += sizeof (UINT16);
+ text = (CHAR16 *)data;
+
+ for (desclen = 0; text[desclen] != 0; desclen++)
+ ;
+ if (desclen != 0) {
+ /* Add terminating zero and we have CHAR16. */
+ desclen = (desclen + 1) * 2;
+ }
+
+ printf(" = ");
+ printf("%S", text);
+ if (filepathlistlen != 0) {
+ /* Output pathname from new line. */
+ if (pager_output("\n")) {
+ rv = CMD_WARN;
+ goto done;
+ }
+ dp = malloc(filepathlistlen);
+ if (dp == NULL)
+ goto done;
+
+ memcpy(dp, data + desclen, filepathlistlen);
+ text = efi_devpath_name(dp);
+ if (text != NULL) {
+ printf("\t%S", text);
+ efi_free_devpath_name(text);
+ }
+ free(dp);
+ }
+ goto done;
+ }
+
+ if (strcmp("ConIn", var) == 0 ||
+ strcmp("ConInDev", var) == 0 ||
+ strcmp("ConOut", var) == 0 ||
+ strcmp("ConOutDev", var) == 0 ||
+ strcmp("ErrOut", var) == 0 ||
+ strcmp("ErrOutDev", var) == 0) {
+ CHAR16 *text;
+
+ printf(" = ");
+ text = efi_devpath_name((EFI_DEVICE_PATH *)data);
+ if (text != NULL) {
+ printf("%S", text);
+ efi_free_devpath_name(text);
+ }
+ goto done;
+ }
+
+ if (strcmp("PlatformLang", var) == 0 ||
+ strcmp("PlatformLangCodes", var) == 0 ||
+ strcmp("LangCodes", var) == 0 ||
+ strcmp("Lang", var) == 0) {
+ printf(" = ");
+ printf("%s", data); /* ASCII string */
+ goto done;
+ }
+
+ /*
+ * Feature bitmap from firmware to OS.
+ * Older UEFI provides UINT32, newer UINT64.
+ */
+ if (strcmp("OsIndicationsSupported", var) == 0) {
+ printf(" = ");
+ if (datasz == 4)
+ printf("0x%x", *((uint32_t *)data));
+ else
+ printf("0x%jx", *((uint64_t *)data));
+ goto done;
+ }
+
+ /* Fallback for anything else. */
+ rv = efi_print_other_value(data, datasz);
+done:
+ if (rv == -1) {
+ if (pager_output("\n"))
+ rv = CMD_WARN;
+ else
+ rv = CMD_OK;
+ }
+ free(var);
+ return (rv);
+}
+
+static void
+efi_print_var_attr(UINT32 attr)
+{
+ bool comma = false;
+
+ if (attr & EFI_VARIABLE_NON_VOLATILE) {
+ printf("NV");
+ comma = true;
+ }
+ if (attr & EFI_VARIABLE_BOOTSERVICE_ACCESS) {
+ if (comma == true)
+ printf(",");
+ printf("BS");
+ comma = true;
+ }
+ if (attr & EFI_VARIABLE_RUNTIME_ACCESS) {
+ if (comma == true)
+ printf(",");
+ printf("RS");
+ comma = true;
+ }
+ if (attr & EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
+ if (comma == true)
+ printf(",");
+ printf("HR");
+ comma = true;
+ }
+ if (attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
+ if (comma == true)
+ printf(",");
+ printf("AT");
+ comma = true;
+ }
+}
+
+static int
+efi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag)
+{
+ UINTN datasz;
+ EFI_STATUS status;
+ UINT32 attr;
+ char *str, *data;
+ int rv = CMD_OK;
+
+ str = NULL;
+ datasz = 0;
+ status = efi_get_variable(varnamearg, matchguid, &attr, &datasz, NULL);
+ if (status != EFI_BUFFER_TOO_SMALL) {
+ printf("Can't get the variable: error %#lx\n",
+ EFI_ERROR_CODE(status));
+ return (CMD_ERROR);
+ }
+ data = malloc(datasz);
+ if (data == NULL) {
+ printf("Out of memory\n");
+ return (CMD_ERROR);
+ }
+
+ status = efi_get_variable(varnamearg, matchguid, &attr, &datasz, data);
+ if (status != EFI_SUCCESS) {
+ printf("Can't get the variable: error %#lx\n",
+ EFI_ERROR_CODE(status));
+ free(data);
+ return (CMD_ERROR);
+ }
+
+ if (efi_guid_to_name(matchguid, &str) == false) {
+ rv = CMD_ERROR;
+ goto done;
+ }
+ printf("%s ", str);
+ efi_print_var_attr(attr);
+ printf(" %S", varnamearg);
+
+ if (lflag == 0) {
+ if (strcmp(str, "global") == 0)
+ rv = efi_print_global(varnamearg, data, datasz);
+ else if (strcmp(str,
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME) == 0)
+ rv = efi_print_mem_type(varnamearg, data, datasz);
+ else if (strcmp(str,
+ "47c7b227-c42a-11d2-8e57-00a0c969723b") == 0)
+ rv = efi_print_shell_str(varnamearg, data, datasz);
+ else if (strcmp(str, MTC_VARIABLE_NAME) == 0) {
+ printf(" = ");
+ printf("%u", *((uint32_t *)data)); /* UINT32 */
+ rv = CMD_OK;
+ if (pager_output("\n"))
+ rv = CMD_WARN;
+ } else
+ rv = efi_print_other_value(data, datasz);
+ } else if (pager_output("\n"))
+ rv = CMD_WARN;
+
+done:
+ free(str);
+ free(data);
+ return (rv);
+}
+
+static int
+command_efi_show(int argc, char *argv[])
+{
+ /*
+ * efi-show [-a]
+ * print all the env
+ * efi-show -g UUID
+ * print all the env vars tagged with UUID
+ * efi-show -v var
+ * search all the env vars and print the ones matching var
+ * eif-show -g UUID -v var
+ * eif-show UUID var
+ * print all the env vars that match UUID and var
+ */
+ /* NB: We assume EFI_GUID is the same as uuid_t */
+ int aflag = 0, gflag = 0, lflag = 0, vflag = 0;
+ int ch, rv;
+ unsigned i;
+ EFI_STATUS status;
+ EFI_GUID varguid = ZERO_GUID;
+ EFI_GUID matchguid = ZERO_GUID;
+ CHAR16 *varname;
+ CHAR16 *newnm;
+ CHAR16 varnamearg[128];
+ UINTN varalloc;
+ UINTN varsz;
+
+ optind = 1;
+ optreset = 1;
+ opterr = 1;
+
+ while ((ch = getopt(argc, argv, "ag:lv:")) != -1) {
+ switch (ch) {
+ case 'a':
+ aflag = 1;
+ break;
+ case 'g':
+ gflag = 1;
+ if (efi_name_to_guid(optarg, &matchguid) == false) {
+ printf("uuid %s could not be parsed\n", optarg);
+ return (CMD_ERROR);
+ }
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ if (strlen(optarg) >= nitems(varnamearg)) {
+ printf("Variable %s is longer than %zd "
+ "characters\n", optarg, nitems(varnamearg));
+ return (CMD_ERROR);
+ }
+ cpy8to16(optarg, varnamearg, nitems(varnamearg));
+ break;
+ default:
+ return (CMD_ERROR);
+ }
+ }
+
+ if (argc == 1) /* default is -a */
+ aflag = 1;
+
+ if (aflag && (gflag || vflag)) {
+ printf("-a isn't compatible with -g or -v\n");
+ return (CMD_ERROR);
+ }
+
+ if (aflag && optind < argc) {
+ printf("-a doesn't take any args\n");
+ return (CMD_ERROR);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ pager_open();
+ if (vflag && gflag) {
+ rv = efi_print_var(varnamearg, &matchguid, lflag);
+ if (rv == CMD_WARN)
+ rv = CMD_OK;
+ pager_close();
+ return (rv);
+ }
+
+ if (argc == 2) {
+ optarg = argv[0];
+ if (strlen(optarg) >= nitems(varnamearg)) {
+ printf("Variable %s is longer than %zd characters\n",
+ optarg, nitems(varnamearg));
+ pager_close();
+ return (CMD_ERROR);
+ }
+ for (i = 0; i < strlen(optarg); i++)
+ varnamearg[i] = optarg[i];
+ varnamearg[i] = 0;
+ optarg = argv[1];
+ if (efi_name_to_guid(optarg, &matchguid) == false) {
+ printf("uuid %s could not be parsed\n", optarg);
+ pager_close();
+ return (CMD_ERROR);
+ }
+ rv = efi_print_var(varnamearg, &matchguid, lflag);
+ if (rv == CMD_WARN)
+ rv = CMD_OK;
+ pager_close();
+ return (rv);
+ }
+
+ if (argc > 0) {
+ printf("Too many args: %d\n", argc);
+ pager_close();
+ return (CMD_ERROR);
+ }
+
+ /*
+ * Initiate the search -- note the standard takes pain
+ * to specify the initial call must be a poiner to a NULL
+ * character.
+ */
+ varalloc = 1024;
+ varname = malloc(varalloc);
+ if (varname == NULL) {
+ printf("Can't allocate memory to get variables\n");
+ pager_close();
+ return (CMD_ERROR);
+ }
+ varname[0] = 0;
+ while (1) {
+ varsz = varalloc;
+ status = efi_get_next_variable_name(&varsz, varname, &varguid);
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ varalloc = varsz;
+ newnm = realloc(varname, varalloc);
+ if (newnm == NULL) {
+ printf("Can't allocate memory to get "
+ "variables\n");
+ rv = CMD_ERROR;
+ break;
+ }
+ varname = newnm;
+ continue; /* Try again with bigger buffer */
+ }
+ if (status == EFI_NOT_FOUND) {
+ rv = CMD_OK;
+ break;
+ }
+ if (status != EFI_SUCCESS) {
+ rv = CMD_ERROR;
+ break;
+ }
+
+ if (aflag) {
+ rv = efi_print_var(varname, &varguid, lflag);
+ if (rv != CMD_OK) {
+ if (rv == CMD_WARN)
+ rv = CMD_OK;
+ break;
+ }
+ continue;
+ }
+ if (vflag) {
+ if (wcscmp(varnamearg, varname) == 0) {
+ rv = efi_print_var(varname, &varguid, lflag);
+ if (rv != CMD_OK) {
+ if (rv == CMD_WARN)
+ rv = CMD_OK;
+ break;
+ }
+ continue;
+ }
+ }
+ if (gflag) {
+ rv = uuid_equal((uuid_t *)&varguid,
+ (uuid_t *)&matchguid, NULL);
+ if (rv != 0) {
+ rv = efi_print_var(varname, &varguid, lflag);
+ if (rv != CMD_OK) {
+ if (rv == CMD_WARN)
+ rv = CMD_OK;
+ break;
+ }
+ continue;
+ }
+ }
+ }
+ free(varname);
+ pager_close();
+
+ return (rv);
+}
+
+COMMAND_SET(efiset, "efi-set", "set EFI variables", command_efi_set);
+
+static int
+command_efi_set(int argc, char *argv[])
+{
+ char *uuid, *var, *val;
+ CHAR16 wvar[128];
+ EFI_GUID guid;
+ EFI_STATUS err;
+
+ if (argc != 4) {
+ printf("efi-set uuid var new-value\n");
+ return (CMD_ERROR);
+ }
+ uuid = argv[1];
+ var = argv[2];
+ val = argv[3];
+ if (efi_name_to_guid(uuid, &guid) == false) {
+ printf("Invalid uuid %s\n", uuid);
+ return (CMD_ERROR);
+ }
+ cpy8to16(var, wvar, nitems(wvar));
+#if 0
+ err = efi_set_variable(wvar, &guid, EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ strlen(val) + 1, val);
+ if (EFI_ERROR(err)) {
+ printf("Failed to set variable: error %lu\n",
+ EFI_ERROR_CODE(err));
+ return (CMD_ERROR);
+ }
+#else
+ printf("would set %s %s = %s\n", uuid, var, val);
+#endif
+ return (CMD_OK);
+}
+
+COMMAND_SET(efiunset, "efi-unset", "delete / unset EFI variables", command_efi_unset);
+
+static int
+command_efi_unset(int argc, char *argv[])
+{
+ char *uuid, *var;
+ CHAR16 wvar[128];
+ EFI_GUID guid;
+ EFI_STATUS err;
+
+ if (argc != 3) {
+ printf("efi-unset uuid var\n");
+ return (CMD_ERROR);
+ }
+ uuid = argv[1];
+ var = argv[2];
+ if (efi_name_to_guid(uuid, &guid) == false) {
+ printf("Invalid uuid %s\n", uuid);
+ return (CMD_ERROR);
+ }
+ cpy8to16(var, wvar, nitems(wvar));
+#if 0
+ err = efi_set_variable(wvar, &guid, 0, 0, NULL);
+ if (EFI_ERROR(err)) {
+ printf("Failed to unset variable: error %lu\n",
+ EFI_ERROR_CODE(err));
+ return (CMD_ERROR);
+ }
+#else
+ printf("would unset %s %s \n", uuid, var);
+#endif
+ return (CMD_OK);
+}
+
+/*
+ * Loader interaction words and extras
+ *
+ * efi-setenv ( value n name n guid n attr -- 0 | -1)
+ * efi-getenv ( guid n addr n -- addr' n' | -1 )
+ * efi-unsetenv ( name n guid n'' -- )
+ */
+
+/*
+ * efi-setenv
+ * efi-setenv ( value n name n guid n attr -- 0 | -1)
+ *
+ * Set environment variables using the SetVariable EFI runtime service.
+ *
+ * Value and guid are passed through in binary form (so guid needs to be
+ * converted to binary form from its string form). Name is converted from
+ * ASCII to CHAR16. Since ficl doesn't have support for internationalization,
+ * there's no native CHAR16 interface provided.
+ *
+ * attr is an int in the bitmask of the following attributes for this variable.
+ *
+ * 1 Non volatile
+ * 2 Boot service access
+ * 4 Run time access
+ * (corresponding to the same bits in the UEFI spec).
+ */
+static void
+ficlEfiSetenv(ficlVm *pVM)
+{
+ char *value = NULL, *guid = NULL;
+ CHAR16 *name = NULL;
+ int i;
+ char *namep, *valuep, *guidp;
+ int names, values, guids, attr;
+ EFI_STATUS status;
+ uuid_t u;
+ uint32_t ustatus;
+ char *error = NULL;
+ ficlStack *pStack = ficlVmGetDataStack(pVM);
+
+ FICL_STACK_CHECK(pStack, 6, 0);
+
+ attr = ficlStackPopInteger(pStack);
+ guids = ficlStackPopInteger(pStack);
+ guidp = (char*)ficlStackPopPointer(pStack);
+ names = ficlStackPopInteger(pStack);
+ namep = (char*)ficlStackPopPointer(pStack);
+ values = ficlStackPopInteger(pStack);
+ valuep = (char*)ficlStackPopPointer(pStack);
+
+ guid = ficlMalloc(guids);
+ if (guid == NULL)
+ goto out;
+ memcpy(guid, guidp, guids);
+ uuid_from_string(guid, &u, &ustatus);
+ if (ustatus != uuid_s_ok) {
+ switch (ustatus) {
+ case uuid_s_bad_version:
+ error = "uuid: bad string";
+ break;
+ case uuid_s_invalid_string_uuid:
+ error = "uuid: invalid string";
+ break;
+ case uuid_s_no_memory:
+ error = "Out of memory";
+ break;
+ default:
+ error = "uuid: Unknown error";
+ break;
+ }
+ ficlStackPushInteger(pStack, -1);
+ goto out;
+ }
+
+ name = ficlMalloc((names + 1) * sizeof (CHAR16));
+ if (name == NULL) {
+ error = "Out of memory";
+ goto out;
+ }
+ for (i = 0; i < names; i++)
+ name[i] = namep[i];
+ name[names] = 0;
+
+ value = ficlMalloc(values + 1);
+ if (value == NULL) {
+ error = "Out of memory";
+ goto out;
+ }
+ memcpy(value, valuep, values);
+
+ status = efi_set_variable(name, (EFI_GUID *)&u, attr, values, value);
+ if (status == EFI_SUCCESS) {
+ ficlStackPushInteger(pStack, 0);
+ } else {
+ ficlStackPushInteger(pStack, -1);
+ error = "Error: efi_set_variable failed";
+ }
+
+out:
+ ficlFree(name);
+ ficlFree(value);
+ ficlFree(guid);
+ if (error != NULL)
+ ficlVmThrowError(pVM, error);
+}
+
+static void
+ficlEfiGetenv(ficlVm *pVM)
+{
+ char *name, *value;
+ char *namep;
+ int names;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 2);
+
+ names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ namep = (char*)ficlStackPopPointer(ficlVmGetDataStack(pVM));
+
+ name = ficlMalloc(names+1);
+ if (name == NULL)
+ ficlVmThrowError(pVM, "Error: out of memory");
+ strncpy(name, namep, names);
+ name[names] = '\0';
+
+ value = getenv(name);
+ ficlFree(name);
+
+ if(value != NULL) {
+ ficlStackPushPointer(ficlVmGetDataStack(pVM), value);
+ ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(value));
+ } else {
+ ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
+ }
+}
+
+static void
+ficlEfiUnsetenv(ficlVm *pVM)
+{
+ char *name;
+ char *namep;
+ int names;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
+
+ names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ namep = (char*)ficlStackPopPointer(ficlVmGetDataStack(pVM));
+
+ name = ficlMalloc(names+1);
+ if (name == NULL)
+ ficlVmThrowError(pVM, "Error: out of memory");
+ strncpy(name, namep, names);
+ name[names] = '\0';
+
+ unsetenv(name);
+ ficlFree(name);
+}
+
+/*
+ * Build platform extensions into the system dictionary
+ */
+static void
+ficlEfiCompilePlatform(ficlSystem *pSys)
+{
+ ficlDictionary *dp = ficlSystemGetDictionary(pSys);
+
+ FICL_SYSTEM_ASSERT(pSys, dp);
+
+ ficlDictionarySetPrimitive(dp, "efi-setenv", ficlEfiSetenv,
+ FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dp, "efi-getenv", ficlEfiGetenv,
+ FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dp, "efi-unsetenv", ficlEfiUnsetenv,
+ FICL_WORD_DEFAULT);
+}
+
+FICL_COMPILE_SET(ficlEfiCompilePlatform);
diff --git a/usr/src/boot/sys/boot/efi/libefi/wchar.c b/usr/src/boot/sys/boot/efi/libefi/wchar.c
new file mode 100644
index 0000000000..c13922aa9f
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/libefi/wchar.c
@@ -0,0 +1,72 @@
+/*-
+ * Copyright 2016 Netflix, Inc. 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>
+
+#include <efi.h>
+#include <efilib.h>
+
+/*
+ * CHAR16 related functions moved from loader.
+ * Perhaps we should move those to libstand afterall, but they are
+ * needed only by UEFI.
+ */
+
+int
+wcscmp(CHAR16 *a, CHAR16 *b)
+{
+
+ while (*a && *b && *a == *b) {
+ a++;
+ b++;
+ }
+ return *a - *b;
+}
+
+/*
+ * cpy8to16 copies a traditional C string into a CHAR16 string and
+ * 0 terminates it. len is the size of *dst in bytes.
+ */
+void
+cpy8to16(const char *src, CHAR16 *dst, size_t len)
+{
+ len <<= 1; /* Assume CHAR16 is 2 bytes */
+ while (len > 0 && *src) {
+ *dst++ = *src++;
+ len--;
+ }
+ *dst++ = (CHAR16)0;
+}
+
+void
+cpy16to8(const CHAR16 *src, char *dst, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len && src[i]; i++)
+ dst[i] = (char)src[i];
+ if (i < len)
+ dst[i] = '\0';
+}
diff --git a/usr/src/boot/sys/boot/efi/loader/Makefile b/usr/src/boot/sys/boot/efi/loader/Makefile
index b82e0b6798..4823f7ccd8 100644
--- a/usr/src/boot/sys/boot/efi/loader/Makefile
+++ b/usr/src/boot/sys/boot/efi/loader/Makefile
@@ -114,6 +114,7 @@ loader.efi: loader.sym
${OBJCOPY} --readonly-text -j .peheader -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 \
+ -j set_Xficl_compile_set \
--output-target=${EFI_TARGET} --subsystem efi-app loader.sym $@
LIBEFI= ../libefi/libefi.a
diff --git a/usr/src/boot/sys/boot/efi/loader/arch/amd64/Makefile.inc b/usr/src/boot/sys/boot/efi/loader/arch/amd64/Makefile.inc
index 5ff8a8c714..4f6be8a2e2 100644
--- a/usr/src/boot/sys/boot/efi/loader/arch/amd64/Makefile.inc
+++ b/usr/src/boot/sys/boot/efi/loader/arch/amd64/Makefile.inc
@@ -2,12 +2,16 @@
SRCS += amd64_tramp.S \
start.S \
framebuffer.c \
- elf64_freebsd.c
+ elf64_freebsd.c \
+ trap.c \
+ exc.S
OBJS += amd64_tramp.o \
start.o \
framebuffer.o \
- elf64_freebsd.o
+ elf64_freebsd.o \
+ trap.o \
+ exc.o
SRCS += nullconsole.c \
spinconsole.c \
diff --git a/usr/src/boot/sys/boot/efi/loader/arch/amd64/exc.S b/usr/src/boot/sys/boot/efi/loader/arch/amd64/exc.S
new file mode 100644
index 0000000000..e52204bd96
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/loader/arch/amd64/exc.S
@@ -0,0 +1,163 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Konstantin Belousov 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.
+ */
+
+ .macro EH N, err=1
+ .align 8
+ .globl EXC\N\()_handler
+EXC\N\()_handler:
+ .if \err != 1
+ pushq $0
+ .endif
+ pushq %rax
+ pushq %rdx
+ pushq %rcx
+ movl $\N,%ecx
+ jmp all_handlers
+ .endm
+
+ .text
+ EH 0,0
+ EH 1,0
+ EH 2,0
+ EH 3,0
+ EH 4,0
+ EH 5,0
+ EH 6,0
+ EH 7,0
+ EH 8
+ EH 9,0
+ EH 10
+ EH 11
+ EH 12
+ EH 13
+ EH 14
+ EH 16,0
+ EH 17
+ EH 18,0
+ EH 19,0
+ EH 20,0
+
+ .globl exc_rsp
+all_handlers:
+ cmpq %rsp,exc_rsp(%rip)
+ je exception
+
+ /*
+ * Interrupt, not exception.
+ * First, copy the hardware interrupt frame to the previous stack.
+ * Our handler always has private IST stack.
+ */
+ movq (6*8)(%rsp),%rax /* saved %rsp value, AKA old stack */
+ subq (5*8),%rax
+ movq (3*8)(%rsp),%rdx /* copy %rip to old stack */
+ movq %rdx,(%rax)
+ movq (4*8)(%rsp),%rdx /* copy %cs */
+ movq %rdx,(1*8)(%rax)
+ movq (5*8)(%rsp),%rdx /* copy %rflags */
+ movq %rdx,(2*8)(%rax)
+ movq (6*8)(%rsp),%rdx /* copy %rsp */
+ movq %rdx,(3*8)(%rax)
+ movq (7*8)(%rsp),%rdx /* copy %ss */
+ movq %rdx,(4*8)(%rax)
+
+ /*
+ * Now simulate invocation of the original interrupt handler
+ * with retq. We switch stacks and execute retq from the old
+ * stack since there is no free registers at the last moment.
+ */
+ subq $16,%rax
+ leaq fw_intr_handlers(%rip),%rdx
+ movq (%rdx,%rcx,8),%rdx /* push intr handler address on old stack */
+ movq %rdx,8(%rax)
+ movq (2*8)(%rsp),%rcx /* saved %rax is put on top of old stack */
+ movq %rcx,(%rax)
+ movq (%rsp),%rcx
+ movq 8(%rsp),%rdx
+
+ movq 32(%rsp),%rsp /* switch to old stack */
+ popq %rax
+ retq
+
+exception:
+ /*
+ * Form the struct trapframe on our IST stack.
+ * Skip three words, which are currently busy with temporal
+ * saves.
+ */
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %r11
+ pushq %r10
+ pushq %rbp
+ pushq %rbx
+ pushq $0 /* %rax */
+ pushq %r9
+ pushq %r8
+ pushq $0 /* %rcx */
+ pushq $0 /* %rdx */
+ pushq %rsi
+ pushq %rdi
+
+ /*
+ * Move %rax, %rdx, %rcx values into the final location,
+ * from the three words which were skipped above.
+ */
+ movq 0x88(%rsp),%rax
+ movq %rax,0x30(%rsp) /* tf_rax */
+ movq 0x78(%rsp),%rax
+ movq %rax,0x18(%rsp) /* tf_rcx */
+ movq 0x80(%rsp),%rax
+ movq %rax,0x10(%rsp) /* tf_rdx */
+
+ /*
+ * And fill the three words themself.
+ */
+ movq %cr2,%rax
+ movq %rax,0x80(%rsp) /* tf_addr */
+ movl %ecx,0x78(%rsp) /* tf_trapno */
+ movw %ds,0x8e(%rsp)
+ movw %es,0x8c(%rsp)
+ movw %fs,0x7c(%rsp)
+ movw %gs,0x7e(%rsp)
+ movw $0,0x88(%rsp) /* tf_flags */
+
+ /*
+ * Call dump routine.
+ */
+ movq %rsp,%rdi
+ callq report_exc
+
+ /*
+ * Hang after reporting. Interrupts are already disabled.
+ */
+1:
+ hlt
+ jmp 1b
diff --git a/usr/src/boot/sys/boot/efi/loader/arch/amd64/ldscript.amd64 b/usr/src/boot/sys/boot/efi/loader/arch/amd64/ldscript.amd64
index f43f483808..a1f2bd1529 100644
--- a/usr/src/boot/sys/boot/efi/loader/arch/amd64/ldscript.amd64
+++ b/usr/src/boot/sys/boot/efi/loader/arch/amd64/ldscript.amd64
@@ -39,6 +39,11 @@ SECTIONS
*(set_Xcommand_set)
__stop_set_Xcommand_set = .;
}
+ set_Xficl_compile_set : {
+ __start_set_Xficl_compile_set = .;
+ *(set_Xficl_compile_set)
+ __stop_set_Xficl_compile_set = .;
+ }
. = ALIGN(4096);
__gp = .;
.sdata : {
diff --git a/usr/src/boot/sys/boot/efi/loader/arch/amd64/trap.c b/usr/src/boot/sys/boot/efi/loader/arch/amd64/trap.c
new file mode 100644
index 0000000000..76e13bb712
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/loader/arch/amd64/trap.c
@@ -0,0 +1,407 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Konstantin Belousov 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>
+
+#include <stand.h>
+#include <string.h>
+#include <sys/param.h>
+#include <machine/cpufunc.h>
+#include <machine/psl.h>
+#include <machine/segments.h>
+#include <machine/frame.h>
+#include <machine/tss.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+#include "loader_efi.h"
+
+#define NUM_IST 8
+#define NUM_EXC 32
+
+/*
+ * This code catches exceptions but forwards hardware interrupts to
+ * handlers installed by firmware. It differentiates exceptions
+ * vs. interrupts by presence of the error code on the stack, which
+ * causes different stack pointer value on trap handler entry.
+ *
+ * Use kernel layout for the trapframe just to not be original.
+ *
+ * Use free IST slot in existing TSS, or create our own TSS if
+ * firmware did not configured any, to have stack switched to
+ * IST-specified one, e.g. to handle #SS. If hand-off cannot find
+ * unused IST slot, or create a new descriptor in GDT, we bail out.
+ */
+
+static struct region_descriptor fw_idt; /* Descriptor for pristine fw IDT */
+static struct region_descriptor loader_idt;/* Descriptor for loader
+ shadow IDT */
+static EFI_PHYSICAL_ADDRESS lidt_pa; /* Address of loader shadow IDT */
+static EFI_PHYSICAL_ADDRESS tss_pa; /* Address of TSS */
+static EFI_PHYSICAL_ADDRESS exc_stack_pa;/* Address of IST stack for loader */
+EFI_PHYSICAL_ADDRESS exc_rsp; /* %rsp value on our IST stack when
+ exception happens */
+EFI_PHYSICAL_ADDRESS fw_intr_handlers[NUM_EXC]; /* fw handlers for < 32 IDT
+ vectors */
+static int intercepted[NUM_EXC];
+static int ist; /* IST for exception handlers */
+static uint32_t tss_fw_seg; /* Fw TSS segment */
+static uint32_t loader_tss; /* Loader TSS segment */
+static struct region_descriptor fw_gdt; /* Descriptor of pristine GDT */
+static EFI_PHYSICAL_ADDRESS loader_gdt_pa; /* Address of loader shadow GDT */
+
+void report_exc(struct trapframe *tf);
+void
+report_exc(struct trapframe *tf)
+{
+
+ /*
+ * printf() depends on loader runtime and UEFI firmware health
+ * to produce the console output, in case of exception, the
+ * loader or firmware runtime may fail to support the printf().
+ */
+ printf("===================================================="
+ "============================\n");
+ printf("Exception %u\n", tf->tf_trapno);
+ printf("ss 0x%04hx cs 0x%04hx ds 0x%04hx es 0x%04hx fs 0x%04hx "
+ "gs 0x%04hx\n",
+ (uint16_t)tf->tf_ss, (uint16_t)tf->tf_cs, (uint16_t)tf->tf_ds,
+ (uint16_t)tf->tf_es, (uint16_t)tf->tf_fs, (uint16_t)tf->tf_gs);
+ printf("err 0x%08x rfl 0x%08x addr 0x%016lx\n"
+ "rsp 0x%016lx rip 0x%016lx\n",
+ (uint32_t)tf->tf_err, (uint32_t)tf->tf_rflags, tf->tf_addr,
+ tf->tf_rsp, tf->tf_rip);
+ printf(
+ "rdi 0x%016lx rsi 0x%016lx rdx 0x%016lx\n"
+ "rcx 0x%016lx r8 0x%016lx r9 0x%016lx\n"
+ "rax 0x%016lx rbx 0x%016lx rbp 0x%016lx\n"
+ "r10 0x%016lx r11 0x%016lx r12 0x%016lx\n"
+ "r13 0x%016lx r14 0x%016lx r15 0x%016lx\n",
+ tf->tf_rdi, tf->tf_rsi, tf->tf_rdx, tf->tf_rcx, tf->tf_r8,
+ tf->tf_r9, tf->tf_rax, tf->tf_rbx, tf->tf_rbp, tf->tf_r10,
+ tf->tf_r11, tf->tf_r12, tf->tf_r13, tf->tf_r14, tf->tf_r15);
+ printf("Machine stopped.\n");
+}
+
+static void
+prepare_exception(unsigned idx, uint64_t my_handler,
+ int ist_use_table[static NUM_IST])
+{
+ struct gate_descriptor *fw_idt_e, *loader_idt_e;
+
+ fw_idt_e = &((struct gate_descriptor *)fw_idt.rd_base)[idx];
+ loader_idt_e = &((struct gate_descriptor *)loader_idt.rd_base)[idx];
+ fw_intr_handlers[idx] = fw_idt_e->gd_looffset +
+ (fw_idt_e->gd_hioffset << 16);
+ intercepted[idx] = 1;
+ ist_use_table[fw_idt_e->gd_ist]++;
+ loader_idt_e->gd_looffset = my_handler;
+ loader_idt_e->gd_hioffset = my_handler >> 16;
+ /*
+ * We reuse uefi selector for the code segment for the exception
+ * handler code, while the reason for the fault might be the
+ * corruption of that gdt entry. On the other hand, allocating
+ * our own descriptor might be not much better, if gdt is corrupted.
+ */
+ loader_idt_e->gd_selector = fw_idt_e->gd_selector;
+ loader_idt_e->gd_ist = 0;
+ loader_idt_e->gd_type = SDT_SYSIGT;
+ loader_idt_e->gd_dpl = 0;
+ loader_idt_e->gd_p = 1;
+ loader_idt_e->gd_xx = 0;
+ loader_idt_e->sd_xx1 = 0;
+}
+#define PREPARE_EXCEPTION(N) \
+ extern char EXC##N##_handler[]; \
+ prepare_exception(N, (uintptr_t)EXC##N##_handler, ist_use_table);
+
+static void
+free_tables(void)
+{
+
+ if (lidt_pa != 0) {
+ BS->FreePages(lidt_pa, EFI_SIZE_TO_PAGES(fw_idt.rd_limit));
+ lidt_pa = 0;
+ }
+ if (exc_stack_pa != 0) {
+ BS->FreePages(exc_stack_pa, 1);
+ exc_stack_pa = 0;
+ }
+ if (tss_pa != 0 && tss_fw_seg == 0) {
+ BS->FreePages(tss_pa, EFI_SIZE_TO_PAGES(sizeof(struct
+ amd64tss)));
+ tss_pa = 0;
+ }
+ if (loader_gdt_pa != 0) {
+ BS->FreePages(tss_pa, 2);
+ loader_gdt_pa = 0;
+ }
+ ist = 0;
+ loader_tss = 0;
+}
+
+static int
+efi_setup_tss(struct region_descriptor *gdt, uint32_t loader_tss_idx,
+ struct amd64tss **tss)
+{
+ EFI_STATUS status;
+ struct system_segment_descriptor *tss_desc;
+
+ tss_desc = (struct system_segment_descriptor *)(gdt->rd_base +
+ (loader_tss_idx << 3));
+ status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+ EFI_SIZE_TO_PAGES(sizeof(struct amd64tss)), &tss_pa);
+ if (EFI_ERROR(status)) {
+ printf("efi_setup_tss: AllocatePages tss error %lu\n",
+ EFI_ERROR_CODE(status));
+ return (0);
+ }
+ *tss = (struct amd64tss *)tss_pa;
+ bzero(*tss, sizeof(**tss));
+ tss_desc->sd_lolimit = sizeof(struct amd64tss);
+ tss_desc->sd_lobase = tss_pa;
+ tss_desc->sd_type = SDT_SYSTSS;
+ tss_desc->sd_dpl = 0;
+ tss_desc->sd_p = 1;
+ tss_desc->sd_hilimit = sizeof(struct amd64tss) >> 16;
+ tss_desc->sd_gran = 0;
+ tss_desc->sd_hibase = tss_pa >> 24;
+ tss_desc->sd_xx0 = 0;
+ tss_desc->sd_xx1 = 0;
+ tss_desc->sd_mbz = 0;
+ tss_desc->sd_xx2 = 0;
+ return (1);
+}
+
+static int
+efi_redirect_exceptions(void)
+{
+ int ist_use_table[NUM_IST];
+ struct gate_descriptor *loader_idt_e;
+ struct system_segment_descriptor *tss_desc, *gdt_desc;
+ struct amd64tss *tss;
+ struct region_descriptor *gdt_rd, loader_gdt;
+ uint32_t i;
+ EFI_STATUS status;
+ register_t rfl;
+
+ sidt(&fw_idt);
+ status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+ EFI_SIZE_TO_PAGES(fw_idt.rd_limit), &lidt_pa);
+ if (EFI_ERROR(status)) {
+ printf("efi_redirect_exceptions: AllocatePages IDT error %lu\n",
+ EFI_ERROR_CODE(status));
+ lidt_pa = 0;
+ return (0);
+ }
+ status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, 1,
+ &exc_stack_pa);
+ if (EFI_ERROR(status)) {
+ printf("efi_redirect_exceptions: AllocatePages stk error %lu\n",
+ EFI_ERROR_CODE(status));
+ exc_stack_pa = 0;
+ free_tables();
+ return (0);
+ }
+ loader_idt.rd_limit = fw_idt.rd_limit;
+ bcopy((void *)fw_idt.rd_base, (void *)loader_idt.rd_base,
+ loader_idt.rd_limit);
+ bzero(ist_use_table, sizeof(ist_use_table));
+ bzero(fw_intr_handlers, sizeof(fw_intr_handlers));
+ bzero(intercepted, sizeof(intercepted));
+
+ sgdt(&fw_gdt);
+ tss_fw_seg = read_tr();
+ gdt_rd = NULL;
+ if (tss_fw_seg == 0) {
+ for (i = 2; (i << 3) + sizeof(*gdt_desc) <= fw_gdt.rd_limit;
+ i += 2) {
+ gdt_desc = (struct system_segment_descriptor *)(
+ fw_gdt.rd_base + (i << 3));
+ if (gdt_desc->sd_type == 0 && gdt_desc->sd_mbz == 0) {
+ gdt_rd = &fw_gdt;
+ break;
+ }
+ }
+ if (gdt_rd == NULL) {
+ if (i >= 8190) {
+ printf("efi_redirect_exceptions: all slots "
+ "in gdt are used\n");
+ free_tables();
+ return (0);
+ }
+ loader_gdt.rd_limit = roundup2(fw_gdt.rd_limit +
+ sizeof(struct system_segment_descriptor),
+ sizeof(struct system_segment_descriptor)) - 1;
+ i = (loader_gdt.rd_limit + 1 -
+ sizeof(struct system_segment_descriptor)) /
+ sizeof(struct system_segment_descriptor) * 2;
+ status = BS->AllocatePages(AllocateAnyPages,
+ EfiLoaderData,
+ EFI_SIZE_TO_PAGES(loader_gdt.rd_limit),
+ &loader_gdt_pa);
+ if (EFI_ERROR(status)) {
+ printf("efi_setup_tss: AllocatePages gdt error "
+ "%lu\n", EFI_ERROR_CODE(status));
+ loader_gdt_pa = 0;
+ free_tables();
+ return (0);
+ }
+ loader_gdt.rd_base = loader_gdt_pa;
+ bzero((void *)loader_gdt.rd_base, loader_gdt.rd_limit);
+ bcopy((void *)fw_gdt.rd_base,
+ (void *)loader_gdt.rd_base, fw_gdt.rd_limit);
+ gdt_rd = &loader_gdt;
+ }
+ loader_tss = i << 3;
+ if (!efi_setup_tss(gdt_rd, i, &tss)) {
+ tss_pa = 0;
+ free_tables();
+ return (0);
+ }
+ } else {
+ tss_desc = (struct system_segment_descriptor *)((char *)
+ fw_gdt.rd_base + tss_fw_seg);
+ if (tss_desc->sd_type != SDT_SYSTSS &&
+ tss_desc->sd_type != SDT_SYSBSY) {
+ printf("LTR points to non-TSS descriptor\n");
+ free_tables();
+ return (0);
+ }
+ tss_pa = tss_desc->sd_lobase + (tss_desc->sd_hibase << 16);
+ tss = (struct amd64tss *)tss_pa;
+ tss_desc->sd_type = SDT_SYSTSS; /* unbusy */
+ }
+
+ PREPARE_EXCEPTION(0);
+ PREPARE_EXCEPTION(1);
+ PREPARE_EXCEPTION(2);
+ PREPARE_EXCEPTION(3);
+ PREPARE_EXCEPTION(4);
+ PREPARE_EXCEPTION(5);
+ PREPARE_EXCEPTION(6);
+ PREPARE_EXCEPTION(7);
+ PREPARE_EXCEPTION(8);
+ PREPARE_EXCEPTION(9);
+ PREPARE_EXCEPTION(10);
+ PREPARE_EXCEPTION(11);
+ PREPARE_EXCEPTION(12);
+ PREPARE_EXCEPTION(13);
+ PREPARE_EXCEPTION(14);
+ PREPARE_EXCEPTION(16);
+ PREPARE_EXCEPTION(17);
+ PREPARE_EXCEPTION(18);
+ PREPARE_EXCEPTION(19);
+ PREPARE_EXCEPTION(20);
+
+ exc_rsp = exc_stack_pa + PAGE_SIZE -
+ (6 /* hw exception frame */ + 3 /* scratch regs */) * 8;
+
+ /* Find free IST and use it */
+ for (ist = 1; ist < NUM_IST; ist++) {
+ if (ist_use_table[ist] == 0)
+ break;
+ }
+ if (ist == NUM_IST) {
+ printf("efi_redirect_exceptions: all ISTs used\n");
+ free_tables();
+ lidt_pa = 0;
+ return (0);
+ }
+ for (i = 0; i < NUM_EXC; i++) {
+ loader_idt_e = &((struct gate_descriptor *)loader_idt.
+ rd_base)[i];
+ if (intercepted[i])
+ loader_idt_e->gd_ist = ist;
+ }
+ (&(tss->tss_ist1))[ist - 1] = exc_stack_pa + PAGE_SIZE;
+
+ /* Switch to new IDT */
+ rfl = intr_disable();
+ if (loader_gdt_pa != 0)
+ bare_lgdt(&loader_gdt);
+ if (loader_tss != 0)
+ ltr(loader_tss);
+ lidt(&loader_idt);
+ intr_restore(rfl);
+ return (1);
+}
+
+static void
+efi_unredirect_exceptions(void)
+{
+ register_t rfl;
+
+ if (lidt_pa == 0)
+ return;
+
+ rfl = intr_disable();
+ if (ist != 0)
+ (&(((struct amd64tss *)tss_pa)->tss_ist1))[ist - 1] = 0;
+ if (loader_gdt_pa != 0)
+ bare_lgdt(&fw_gdt);
+ if (loader_tss != 0)
+ ltr(tss_fw_seg);
+ lidt(&fw_idt);
+ intr_restore(rfl);
+ free_tables();
+}
+
+static int
+command_grab_faults(int argc, char *argv[])
+{
+ int res;
+
+ res = efi_redirect_exceptions();
+ if (!res)
+ printf("failed\n");
+ return (CMD_OK);
+}
+COMMAND_SET(grap_faults, "grab_faults", "grab faults", command_grab_faults);
+
+static int
+command_ungrab_faults(int argc, char *argv[])
+{
+
+ efi_unredirect_exceptions();
+ return (CMD_OK);
+}
+COMMAND_SET(ungrab_faults, "ungrab_faults", "ungrab faults",
+ command_ungrab_faults);
+
+static int
+command_fault(int argc, char *argv[])
+{
+
+ __asm("ud2");
+ return (CMD_OK);
+}
+COMMAND_SET(fault, "fault", "generate fault", command_fault);
diff --git a/usr/src/boot/sys/boot/efi/loader/arch/arm/ldscript.arm b/usr/src/boot/sys/boot/efi/loader/arch/arm/ldscript.arm
index 8b4a6dc64b..a52af40884 100644
--- a/usr/src/boot/sys/boot/efi/loader/arch/arm/ldscript.arm
+++ b/usr/src/boot/sys/boot/efi/loader/arch/arm/ldscript.arm
@@ -47,6 +47,11 @@ SECTIONS
*(set_Xcommand_set)
__stop_set_Xcommand_set = .;
}
+ set_Xficl_compile_set : {
+ __start_set_Xficl_compile_set = .;
+ *(set_Xficl_compile_set)
+ __stop_set_Xficl_compile_set = .;
+ }
__gp = .;
.plt : { *(.plt) }
.dynamic : { *(.dynamic) }
diff --git a/usr/src/boot/sys/boot/efi/loader/arch/arm64/ldscript.arm64 b/usr/src/boot/sys/boot/efi/loader/arch/arm64/ldscript.arm64
index 29b807b250..96da9ba662 100644
--- a/usr/src/boot/sys/boot/efi/loader/arch/arm64/ldscript.arm64
+++ b/usr/src/boot/sys/boot/efi/loader/arch/arm64/ldscript.arm64
@@ -43,6 +43,11 @@ SECTIONS
*(set_Xcommand_set)
__stop_set_Xcommand_set = .;
}
+ set_Xficl_compile_set : {
+ __start_set_Xficl_compile_set = .;
+ *(set_Xficl_compile_set)
+ __stop_set_Xficl_compile_set = .;
+ }
. = ALIGN(16);
__gp = .;
.sdata : {
diff --git a/usr/src/boot/sys/boot/efi/loader/arch/i386/ldscript.i386 b/usr/src/boot/sys/boot/efi/loader/arch/i386/ldscript.i386
index 4b28c104a3..e17212a1bd 100644
--- a/usr/src/boot/sys/boot/efi/loader/arch/i386/ldscript.i386
+++ b/usr/src/boot/sys/boot/efi/loader/arch/i386/ldscript.i386
@@ -35,6 +35,11 @@ SECTIONS
*(set_Xcommand_set)
__stop_set_Xcommand_set = .;
}
+ set_Xficl_compile_set : {
+ __start_set_Xficl_compile_set = .;
+ *(set_Xficl_compile_set)
+ __stop_set_Xficl_compile_set = .;
+ }
. = ALIGN(4096);
__gp = .;
.sdata : {
diff --git a/usr/src/boot/sys/boot/efi/loader/main.c b/usr/src/boot/sys/boot/efi/loader/main.c
index cf689b8384..22fd9e9b62 100644
--- a/usr/src/boot/sys/boot/efi/loader/main.c
+++ b/usr/src/boot/sys/boot/efi/loader/main.c
@@ -32,6 +32,7 @@
#include <sys/reboot.h>
#include <sys/boot.h>
#include <stand.h>
+#include <inttypes.h>
#include <string.h>
#include <setjmp.h>
@@ -39,6 +40,9 @@
#include <efilib.h>
#include <efigpt.h>
+#include <uuid.h>
+#include <stdbool.h>
+
#include <bootstrap.h>
#include <smbios.h>
@@ -52,19 +56,10 @@ extern char bootprog_info[];
struct arch_switch archsw; /* MI/MD interface boundary */
-EFI_GUID acpi = ACPI_TABLE_GUID;
-EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
EFI_GUID devid = DEVICE_PATH_PROTOCOL;
EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
-EFI_GUID mps = MPS_TABLE_GUID;
-EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
EFI_GUID smbios = SMBIOS_TABLE_GUID;
EFI_GUID smbios3 = SMBIOS3_TABLE_GUID;
-EFI_GUID dxe = DXE_SERVICES_TABLE_GUID;
-EFI_GUID hoblist = HOB_LIST_TABLE_GUID;
-EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
-EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
-EFI_GUID fdtdtb = FDT_TABLE_GUID;
EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
EFI_GUID serial_io = SERIAL_IO_PROTOCOL;
@@ -74,29 +69,6 @@ void efi_serial_init(void);
static void efi_zfs_probe(void);
#endif
-/*
- * Need this because EFI uses UTF-16 unicode string constants, but we
- * use UTF-8. We can't use printf due to the possibility of \0 and we
- * don't support wide characters either.
- */
-static void
-print_str16(const CHAR16 *str)
-{
- int i;
-
- for (i = 0; str[i]; i++)
- printf("%c", (char)str[i]);
-}
-
-static void
-cp16to8(const CHAR16 *src, char *dst, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len && src[i]; i++)
- dst[i] = (char)src[i];
-}
-
static int
has_keyboard(void)
{
@@ -311,14 +283,14 @@ main(int argc, CHAR16 *argv[])
if (i + 1 == argc) {
setenv("comconsole_speed", "115200", 1);
} else {
- cp16to8(&argv[i + 1][0], var,
+ cpy16to8(&argv[i + 1][0], var,
sizeof(var));
setenv("comconsole_speedspeed", var, 1);
}
i++;
break;
} else {
- cp16to8(&argv[i][j + 1], var,
+ cpy16to8(&argv[i][j + 1], var,
sizeof(var));
setenv("comconsole_speed", var, 1);
break;
@@ -374,19 +346,15 @@ main(int argc, CHAR16 *argv[])
printf("Command line arguments:");
for (i = 0; i < argc; i++) {
- printf(" ");
- print_str16(argv[i]);
+ printf(" %S", argv[i]);
}
printf("\n");
printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
ST->Hdr.Revision & 0xffff);
- printf("EFI Firmware: ");
- /* printf doesn't understand EFI Unicode */
- ST->ConOut->OutputString(ST->ConOut, ST->FirmwareVendor);
- printf(" (rev %d.%02d)\n", ST->FirmwareRevision >> 16,
- ST->FirmwareRevision & 0xffff);
+ printf("EFI Firmware: %S (rev %d.%02d)\n", ST->FirmwareVendor,
+ ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
printf("\n%s", bootprog_info);
@@ -440,6 +408,7 @@ main(int argc, CHAR16 *argv[])
}
}
+ efi_init_environment();
setenv("LINES", "24", 1); /* optional */
setenv("COLUMNS", "80", 1); /* optional */
setenv("ISADIR", "amd64", 1); /* we only build 64bit */
@@ -487,22 +456,6 @@ command_memmap(int argc __attribute((unused)),
int i, ndesc;
int rv = 0;
char line[80];
- static const char *types[] = {
- "Reserved",
- "LoaderCode",
- "LoaderData",
- "BootServicesCode",
- "BootServicesData",
- "RuntimeServicesCode",
- "RuntimeServicesData",
- "ConventionalMemory",
- "UnusableMemory",
- "ACPIReclaimMemory",
- "ACPIMemoryNVS",
- "MemoryMappedIO",
- "MemoryMappedIOPortSpace",
- "PalCode"
- };
sz = 0;
status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
@@ -530,7 +483,7 @@ command_memmap(int argc __attribute((unused)),
for (i = 0, p = map; i < ndesc;
i++, p = NextMemoryDescriptor(p, dsz)) {
snprintf(line, 80, "%23s %012lx %012lx %08lx ",
- types[p->Type],
+ efi_memory_type(p->Type),
p->PhysicalStart,
p->VirtualStart,
p->NumberOfPages);
@@ -554,6 +507,12 @@ command_memmap(int argc __attribute((unused)),
printf("RP ");
if (p->Attribute & EFI_MEMORY_XP)
printf("XP ");
+ if (p->Attribute & EFI_MEMORY_NV)
+ printf("NV ");
+ if (p->Attribute & EFI_MEMORY_MORE_RELIABLE)
+ printf("MR ");
+ if (p->Attribute & EFI_MEMORY_RO)
+ printf("RO ");
rv = pager_output("\n");
if (rv)
break;
@@ -566,23 +525,12 @@ command_memmap(int argc __attribute((unused)),
COMMAND_SET(configuration, "configuration", "print configuration tables",
command_configuration);
-static const char *
-guid_to_string(EFI_GUID *guid)
-{
- static char buf[40];
-
- sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
- guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
- guid->Data4[5], guid->Data4[6], guid->Data4[7]);
- return (buf);
-}
-
static int
command_configuration(int argc __attribute((unused)),
char *argv[] __attribute((unused)))
{
UINTN i;
+ char *name;
printf("NumberOfTableEntries=%lu\n",
(unsigned long)ST->NumberOfTableEntries);
@@ -591,28 +539,13 @@ command_configuration(int argc __attribute((unused)),
printf(" ");
guid = &ST->ConfigurationTable[i].VendorGuid;
- if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
- printf("MPS Table");
- else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
- printf("ACPI Table");
- else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
- printf("ACPI 2.0 Table");
- else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
- printf("SMBIOS Table");
- else if (!memcmp(guid, &smbios3, sizeof(EFI_GUID)))
- printf("SMBIOS3 Table");
- else if (!memcmp(guid, &dxe, sizeof(EFI_GUID)))
- printf("DXE Table");
- else if (!memcmp(guid, &hoblist, sizeof(EFI_GUID)))
- printf("HOB List Table");
- else if (!memcmp(guid, &memtype, sizeof(EFI_GUID)))
- printf("Memory Type Information Table");
- else if (!memcmp(guid, &debugimg, sizeof(EFI_GUID)))
- printf("Debug Image Info Table");
- else if (!memcmp(guid, &fdtdtb, sizeof(EFI_GUID)))
- printf("FDT Table");
- else
- printf("Unknown Table (%s)", guid_to_string(guid));
+
+ if (efi_guid_to_name(guid, &name) == true) {
+ printf(name);
+ free(name);
+ } else {
+ printf("Error while translating UUID to name");
+ }
printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
}
@@ -675,209 +608,18 @@ command_mode(int argc, char *argv[])
return (CMD_OK);
}
-
-COMMAND_SET(nvram, "nvram", "get NVRAM variables", command_nvram);
-
-static int
-command_nvram(int argc __attribute((unused)),
- char *argv[] __attribute((unused)))
-{
- CHAR16 var[128];
- UINT8 *data; /* value is in bytes */
- EFI_STATUS status;
- EFI_GUID varguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
- UINTN varsz, datasz, i;
- UINT32 attr;
- SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
-
- conout = ST->ConOut;
-
- pager_open();
- var[0] = 0; /* Initiate the enumeration */
- varsz = 128;
-
- for (status = RS->GetNextVariableName(&varsz, var, &varguid);
- status != EFI_NOT_FOUND;
- status = RS->GetNextVariableName(&varsz, var, &varguid)) {
-
- /*
- * as term emu is keeping track on cursor, use putchar().
- */
- for (i = 0; var[i] != 0; i++)
- putchar(var[i]);
- varsz = 128; /* GetNextVariableName() did change it. */
-
- printf(": Attributes:");
- datasz = 0;
- status = RS->GetVariable(var, &varguid, &attr, &datasz, NULL);
- if ((data = malloc(datasz)) == NULL)
- break;
- status = RS->GetVariable(var, &varguid, &attr, &datasz, data);
- if (EFI_ERROR(status))
- printf("<error retrieving variable>");
- else {
- if (attr & EFI_VARIABLE_NON_VOLATILE)
- printf(" NV");
- if (attr & EFI_VARIABLE_BOOTSERVICE_ACCESS)
- printf(" BS");
- if (attr & EFI_VARIABLE_RUNTIME_ACCESS)
- printf(" RS");
- if (attr & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
- printf(" HR");
- if (attr & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
- printf(" AW");
- if (attr &
- EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
- printf(" TW");
-
- printf(": DataLength: %lld", (long long)datasz);
- }
- free(data);
- if (pager_output("\n"))
- break;
- }
-
- pager_close();
- return (CMD_OK);
-}
-
-struct protocol_name {
- EFI_GUID guid;
- const char *name;
-} proto_names[] = {
- { DEVICE_PATH_PROTOCOL, "device path" },
- { BLOCK_IO_PROTOCOL, "block io" },
- { DISK_IO_PROTOCOL, "disk io" },
- { EFI_DISK_INFO_PROTOCOL_GUID, "disk info" },
- { SIMPLE_FILE_SYSTEM_PROTOCOL, "simple fs" },
- { LOAD_FILE_PROTOCOL, "load file" },
- { DEVICE_IO_PROTOCOL, "device io" },
- { UNICODE_COLLATION_PROTOCOL, "unicode collation" },
- { EFI_UNICODE_COLLATION2_PROTOCOL_GUID, "unicode collation2" },
- { EFI_SIMPLE_NETWORK_PROTOCOL, "simple network" },
- { SIMPLE_TEXT_OUTPUT_PROTOCOL, "simple text output" },
- { SIMPLE_TEXT_INPUT_PROTOCOL, "simple text input" },
- { EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID, "simple text ex input" },
- { EFI_CONSOLE_CONTROL_PROTOCOL_GUID, "console control" },
- { EFI_CONSOLE_IN_DEVICE_GUID, "stdin" },
- { EFI_CONSOLE_OUT_DEVICE_GUID, "stdout" },
- { EFI_STANDARD_ERROR_DEVICE_GUID, "stderr" },
- { EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, "GOP" },
- { EFI_UGA_DRAW_PROTOCOL_GUID, "UGA draw" },
- { EFI_PXE_BASE_CODE_PROTOCOL, "PXE base code" },
- { EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL, "PXE base code callback" },
- { SERIAL_IO_PROTOCOL, "serial io" },
- { LOADED_IMAGE_PROTOCOL, "loaded image" },
- { EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID,
- "loaded image device path" },
- { EFI_ISA_IO_PROTOCOL_GUID, "ISA io" },
- { EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID, "IDE controller init" },
- { EFI_ISA_ACPI_PROTOCOL_GUID, "ISA ACPI" },
- { EFI_PCI_IO_PROTOCOL_GUID, "PCI" },
- { EFI_PCI_ROOT_IO_GUID, "PCI root" },
- { EFI_PCI_ENUMERATION_COMPLETE_GUID, "PCI enumeration" },
- { EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID, "Driver diagnostics" },
- { EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID, "Driver diagnostics2" },
- { EFI_SIMPLE_POINTER_PROTOCOL_GUID, "simple pointer" },
- { EFI_ABSOLUTE_POINTER_PROTOCOL_GUID, "absolute pointer" },
- { EFI_VLAN_CONFIG_PROTOCOL_GUID, "VLAN config" },
- { EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID, "ARP service binding" },
- { EFI_ARP_PROTOCOL_GUID, "ARP" },
- { EFI_IP4_SERVICE_BINDING_PROTOCOL, "IPv4 service binding" },
- { EFI_IP4_PROTOCOL, "IPv4" },
- { EFI_IP4_CONFIG_PROTOCOL_GUID, "IPv4 config" },
- { EFI_IP6_SERVICE_BINDING_PROTOCOL, "IPv6 service binding" },
- { EFI_IP6_PROTOCOL, "IPv6" },
- { EFI_IP6_CONFIG_PROTOCOL_GUID, "IPv6 config" },
- { EFI_UDP4_PROTOCOL, "UDPv4" },
- { EFI_UDP4_SERVICE_BINDING_PROTOCOL, "UDPv4 service binding" },
- { EFI_UDP6_PROTOCOL, "UDPv6" },
- { EFI_UDP6_SERVICE_BINDING_PROTOCOL, "UDPv6 service binding" },
- { EFI_TCP4_PROTOCOL, "TCPv4" },
- { EFI_TCP4_SERVICE_BINDING_PROTOCOL, "TCPv4 service binding" },
- { EFI_TCP6_PROTOCOL, "TCPv6" },
- { EFI_TCP6_SERVICE_BINDING_PROTOCOL, "TCPv6 service binding" },
- { EFI_PART_TYPE_EFI_SYSTEM_PART_GUID, "EFI System partition" },
- { EFI_PART_TYPE_LEGACY_MBR_GUID, "MBR legacy" },
- { EFI_DEVICE_TREE_GUID, "device tree" },
- { EFI_USB_IO_PROTOCOL_GUID, "USB io" },
- { EFI_USB2_HC_PROTOCOL_GUID, "USB2 HC" },
- { EFI_COMPONENT_NAME_PROTOCOL_GUID, "component name" },
- { EFI_COMPONENT_NAME2_PROTOCOL_GUID, "component name2" },
- { EFI_DRIVER_BINDING_PROTOCOL_GUID, "driver binding" },
- { EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID, "driver configuration" },
- { EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID, "driver configuration2" },
- { EFI_DECOMPRESS_PROTOCOL_GUID, "decompress" },
- { EFI_EBC_INTERPRETER_PROTOCOL_GUID, "ebc interpreter" },
- { EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL,
- "network interface identifier" },
- { EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_31,
- "network interface identifier_31" },
- { EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID,
- "managed network service binding" },
- { EFI_MANAGED_NETWORK_PROTOCOL_GUID, "managed network" },
- { EFI_FORM_BROWSER2_PROTOCOL_GUID, "form browser" },
- { EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID, "HII config routing" },
- { EFI_HII_DATABASE_PROTOCOL_GUID, "HII database" },
- { EFI_HII_STRING_PROTOCOL_GUID, "HII string" },
- { EFI_HII_IMAGE_PROTOCOL_GUID, "HII image" },
- { EFI_HII_FONT_PROTOCOL_GUID, "HII font" },
- { EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID, "HII config" },
- { EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID, "MTFTP4 service binding" },
- { EFI_MTFTP4_PROTOCOL_GUID, "MTFTP4" },
- { EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID, "MTFTP6 service binding" },
- { EFI_MTFTP6_PROTOCOL_GUID, "MTFTP6" },
- { EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID, "DHCP4 service binding" },
- { EFI_DHCP4_PROTOCOL_GUID, "DHCP4" },
- { EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID, "DHCP6 service binding" },
- { EFI_DHCP6_PROTOCOL_GUID, "DHCP6" },
- { EFI_SCSI_IO_PROTOCOL_GUID, "SCSI io" },
- { EFI_SCSI_PASS_THRU_PROTOCOL_GUID, "SCSI pass thru" },
- { EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID, "SCSI pass thru ext" },
- { EFI_CAPSULE_ARCH_PROTOCOL_GUID, "Capsule arch" },
- { EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID, "monotonic counter arch" },
- { EFI_REALTIME_CLOCK_ARCH_PROTOCOL_GUID, "realtime clock arch" },
- { EFI_VARIABLE_ARCH_PROTOCOL_GUID, "variable arch" },
- { EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID, "variable write arch" },
- { EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID, "watchdog timer arch" },
- { EFI_MP_SERVICES_PROTOCOL_GUID, "MP services" },
- { EFI_ACPI_SUPPORT_PROTOCOL_GUID, "ACPI support" },
- { EFI_BDS_ARCH_PROTOCOL_GUID, "BDS arch" },
- { EFI_METRONOME_ARCH_PROTOCOL_GUID, "metronome arch" },
- { EFI_TIMER_ARCH_PROTOCOL_GUID, "timer arch" },
- { EFI_DPC_PROTOCOL_GUID, "DPC" },
- { EFI_PRINT2_PROTOCOL_GUID, "print2" },
- { EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, "device path to text" },
- { EFI_RESET_ARCH_PROTOCOL_GUID, "reset arch" },
- { EFI_CPU_ARCH_PROTOCOL_GUID, "CPU arch" },
- { EFI_CPU_IO2_PROTOCOL_GUID, "CPU IO2" },
- { EFI_LEGACY_8259_PROTOCOL_GUID, "Legacy 8259" },
- { EFI_SECURITY_ARCH_PROTOCOL_GUID, "Security arch" },
- { EFI_SECURITY2_ARCH_PROTOCOL_GUID, "Security2 arch" },
- { EFI_RUNTIME_ARCH_PROTOCOL_GUID, "Runtime arch" },
- { EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID, "status code runtime" },
- { EFI_DATA_HUB_PROTOCOL_GUID, "data hub" },
- { PCD_PROTOCOL_GUID, "PCD" },
- { EFI_PCD_PROTOCOL_GUID, "EFI PCD" },
- { EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID, "firmware volume block" },
- { EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID, "firmware volume2" },
- { EFI_FIRMWARE_VOLUME_DISPATCH_PROTOCOL_GUID,
- "firmware volume dispatch" },
- { LZMA_COMPRESS_GUID, "lzma compress" },
- { { 0,0,0,{0,0,0,0,0,0,0,0} }, NULL } /* must be last entry */
-};
-
COMMAND_SET(lsefi, "lsefi", "list EFI handles", command_lsefi);
static int
command_lsefi(int argc __attribute((unused)),
char *argv[] __attribute((unused)))
{
+ char *name;
EFI_HANDLE *buffer = NULL;
EFI_HANDLE handle;
UINTN bufsz = 0, i, j;
EFI_STATUS status;
- int k, ret;
+ int ret;
status = BS->LocateHandle(AllHandles, NULL, NULL, &bufsz, buffer);
if (status != EFI_BUFFER_TOO_SMALL) {
@@ -916,21 +658,19 @@ command_lsefi(int argc __attribute((unused)),
(long long)status);
continue;
}
+
for (j = 0; j < nproto; j++) {
- for (k = 0; proto_names[k].name != NULL; k++)
- if (memcmp(protocols[j], &proto_names[k].guid,
- sizeof (proto_names[k].guid)) == 0)
- break;
- if (proto_names[k].name != NULL)
- printf(" %s", proto_names[k].name);
- else
- printf(" %s", guid_to_string(protocols[j]));
- ret = pager_output("\n");
- if (ret)
+ if (efi_guid_to_name(protocols[j], &name) == true) {
+ printf(" %s", name);
+ free(name);
+ } else {
+ printf("Error while translating UUID to name");
+ }
+ if ((ret = pager_output("\n")) != 0)
break;
}
BS->FreePool(protocols);
- if (ret)
+ if (ret != 0)
break;
}
pager_close();
@@ -938,7 +678,6 @@ command_lsefi(int argc __attribute((unused)),
return (CMD_OK);
}
-#ifdef EFI_ZFS_BOOT
COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
command_lszfs);
@@ -993,7 +732,6 @@ command_reloadbe(int argc, char *argv[])
return (CMD_OK);
}
#endif /* __FreeBSD__ */
-#endif
void
efi_serial_init(void)
diff --git a/usr/src/boot/sys/boot/forth/Makefile.inc b/usr/src/boot/sys/boot/forth/Makefile.inc
index eeab1a54eb..43c109a6da 100644
--- a/usr/src/boot/sys/boot/forth/Makefile.inc
+++ b/usr/src/boot/sys/boot/forth/Makefile.inc
@@ -7,6 +7,7 @@ FORTH += brand-illumos.4th
FORTH += check-password.4th
FORTH += color.4th
FORTH += delay.4th
+FORTH += efi.4th
FORTH += frames.4th
FORTH += loader.4th
DEFFILES = loader.conf
diff --git a/usr/src/boot/sys/boot/forth/efi.4th b/usr/src/boot/sys/boot/forth/efi.4th
new file mode 100644
index 0000000000..422a32d295
--- /dev/null
+++ b/usr/src/boot/sys/boot/forth/efi.4th
@@ -0,0 +1,29 @@
+\ Copyright (c) 2016 Netflix, Inc
+\ 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.
+\
+
+only forth definitions
+
+\ Place holder for more functions
+.( EFI boot environment) cr
diff --git a/usr/src/boot/sys/boot/forth/loader.4th b/usr/src/boot/sys/boot/forth/loader.4th
index b6955f1b98..cdcacc8231 100644
--- a/usr/src/boot/sys/boot/forth/loader.4th
+++ b/usr/src/boot/sys/boot/forth/loader.4th
@@ -43,6 +43,9 @@ include /boot/forth/support.4th
include /boot/forth/color.4th
include /boot/forth/delay.4th
include /boot/forth/check-password.4th
+s" efi-version" getenv? [if]
+ include /boot/forth/efi.4th
+[then]
only forth definitions
diff --git a/usr/src/boot/sys/boot/i386/libi386/Makefile b/usr/src/boot/sys/boot/i386/libi386/Makefile
index 6809e30898..f24ff36683 100644
--- a/usr/src/boot/sys/boot/i386/libi386/Makefile
+++ b/usr/src/boot/sys/boot/i386/libi386/Makefile
@@ -18,7 +18,7 @@ include $(SRC)/Makefile.master
CFLAGS= -O2 -I../../../../include -I../../..
CFLAGS += -DLOADER_ZFS_SUPPORT
-CPPFLAGS=
+CPPFLAGS= -DSTAND
all: libi386.a
@@ -75,7 +75,8 @@ CFLAGS += -DTERM_EMU
# XXX: make alloca() useable
CFLAGS += -Dalloca=__builtin_alloca
-CFLAGS += -I../../common -I../common \
+CFLAGS += -I$(SRC)/common/ficl -I../../ficl \
+ -I../../common -I../common \
-I../btx/lib \
-I$(SRC)/uts/intel/sys/acpi \
-I../../.. -I.
diff --git a/usr/src/boot/sys/boot/i386/libi386/biospci.c b/usr/src/boot/sys/boot/i386/libi386/biospci.c
index 196590e1bf..e143ba9746 100644
--- a/usr/src/boot/sys/boot/i386/libi386/biospci.c
+++ b/usr/src/boot/sys/boot/i386/libi386/biospci.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
+ * Copyright (c) 2016 Netflix, Inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,7 +26,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
/*
* PnP enumerator using the PCI BIOS.
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <isapnp.h>
#include <btxv86.h>
#include "libi386.h"
+#include "ficl.h"
/*
* Stupid PCI BIOS interface doesn't let you simply enumerate everything
@@ -338,7 +339,7 @@ biospci_find_devclass(uint32_t class, int index, uint32_t *locator)
return (0);
}
-int
+static int
biospci_find_device(uint32_t devid, int index, uint32_t *locator)
{
v86.ctl = V86_FLAGS;
@@ -407,7 +408,7 @@ biospci_locator(int8_t bus, uint8_t device, uint8_t function)
* Counts the number of instances of devid we have in the system, as least as
* far as the PCI BIOS is able to tell.
*/
-int
+static int
biospci_count_device_type(uint32_t devid)
{
int i;
@@ -426,3 +427,175 @@ biospci_count_device_type(uint32_t devid)
}
return i;
}
+
+/*
+ * pcibios-device-count (devid -- count)
+ *
+ * Returns the PCI BIOS' count of how many devices matching devid are
+ * in the system. devid is the 32-bit vendor + device.
+ */
+static void
+ficlPciBiosCountDevices(ficlVm *pVM)
+{
+ uint32_t devid;
+ int i;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1);
+
+ devid = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+
+ i = biospci_count_device_type(devid);
+
+ ficlStackPushInteger(ficlVmGetDataStack(pVM), i);
+}
+
+/*
+ * pcibios-write-config (locator offset width value -- )
+ *
+ * Writes the specified config register.
+ * Locator is bus << 8 | device << 3 | fuction
+ * offset is the pci config register
+ * width is 0 for byte, 1 for word, 2 for dword
+ * value is the value to write
+ */
+static void
+ficlPciBiosWriteConfig(ficlVm *pVM)
+{
+ uint32_t value, width, offset, locator;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 0);
+
+ value = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ width = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ offset = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ locator = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+
+ biospci_write_config(locator, offset, width, value);
+}
+
+/*
+ * pcibios-read-config (locator offset width -- value)
+ *
+ * Reads the specified config register.
+ * Locator is bus << 8 | device << 3 | fuction
+ * offset is the pci config register
+ * width is 0 for byte, 1 for word, 2 for dword
+ * value is the value to read from the register
+ */
+static void
+ficlPciBiosReadConfig(ficlVm *pVM)
+{
+ uint32_t value, width, offset, locator;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
+
+ width = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ offset = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ locator = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+
+ biospci_read_config(locator, offset, width, &value);
+
+ ficlStackPushInteger(ficlVmGetDataStack(pVM), value);
+}
+
+/*
+ * pcibios-find-devclass (class index -- locator)
+ *
+ * Finds the index'th instance of class in the pci tree.
+ * must be an exact match.
+ * class is the class to search for.
+ * index 0..N (set to 0, increment until error)
+ *
+ * Locator is bus << 8 | device << 3 | fuction (or -1 on error)
+ */
+static void
+ficlPciBiosFindDevclass(ficlVm *pVM)
+{
+ uint32_t index, class, locator;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 1);
+
+ index = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ class = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+
+ if (biospci_find_devclass(class, index, &locator))
+ locator = 0xffffffff;
+
+ ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
+}
+
+/*
+ * pcibios-find-device(devid index -- locator)
+ *
+ * Finds the index'th instance of devid in the pci tree.
+ * must be an exact match.
+ * class is the class to search for.
+ * index 0..N (set to 0, increment until error)
+ *
+ * Locator is bus << 8 | device << 3 | fuction (or -1 on error)
+ */
+static void
+ficlPciBiosFindDevice(ficlVm *pVM)
+{
+ uint32_t index, devid, locator;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 1);
+
+ index = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ devid = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+
+ if (biospci_find_device(devid, index, &locator))
+ locator = 0xffffffff;
+
+ ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
+}
+
+/*
+ * pcibios-locator(bus device function -- locator)
+ *
+ * converts bus, device, function to locator.
+ *
+ * Locator is bus << 8 | device << 3 | fuction
+ */
+static void
+ficlPciBiosLocator(ficlVm *pVM)
+{
+ uint32_t bus, device, function, locator;
+
+ FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
+
+ function = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ device = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+ bus = ficlStackPopInteger(ficlVmGetDataStack(pVM));
+
+ locator = biospci_locator(bus, device, function);
+
+ ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
+}
+
+/*
+ * Glue function to add the appropriate forth words to access pci bios
+ * functionality.
+ */
+static void
+ficlCompilePciBios(ficlSystem *pSys)
+{
+ ficlDictionary *dp = ficlSystemGetDictionary(pSys);
+
+ FICL_SYSTEM_ASSERT(pSys, dp);
+
+ ficlDictionarySetPrimitive(dp, "pcibios-device-count",
+ ficlPciBiosCountDevices, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dp, "pcibios-read-config",
+ ficlPciBiosReadConfig, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dp, "pcibios-write-config",
+ ficlPciBiosWriteConfig, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dp, "pcibios-find-devclass",
+ ficlPciBiosFindDevclass, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dp, "pcibios-find-device",
+ ficlPciBiosFindDevice, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dp, "pcibios-locator", ficlPciBiosLocator,
+ FICL_WORD_DEFAULT);
+}
+
+FICL_COMPILE_SET(ficlCompilePciBios);
diff --git a/usr/src/boot/sys/boot/i386/libi386/libi386.h b/usr/src/boot/sys/boot/i386/libi386/libi386.h
index 9574b15526..ac614ae2eb 100644
--- a/usr/src/boot/sys/boot/i386/libi386/libi386.h
+++ b/usr/src/boot/sys/boot/i386/libi386/libi386.h
@@ -135,12 +135,10 @@ extern uint32_t high_heap_size; /* extended memory region available */
extern vm_offset_t high_heap_base; /* for use as the heap */
void biospci_detect(void);
-int biospci_count_device_type(uint32_t devid);
int biospci_find_devclass(uint32_t class, int index, uint32_t *locator);
-int biospci_find_device(uint32_t devid, int index, uint32_t *locator);
-int biospci_write_config(uint32_t locator, int offset, int width, uint32_t val);
int biospci_read_config(uint32_t locator, int offset, int width, uint32_t *val);
uint32_t biospci_locator(int8_t bus, uint8_t device, uint8_t function);
+int biospci_write_config(uint32_t locator, int offset, int width, uint32_t val);
void biosacpi_detect(void);
diff --git a/usr/src/boot/sys/x86/include/frame.h b/usr/src/boot/sys/x86/include/frame.h
new file mode 100644
index 0000000000..fb2285f80f
--- /dev/null
+++ b/usr/src/boot/sys/x86/include/frame.h
@@ -0,0 +1,157 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 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.
+ *
+ * from: @(#)frame.h 5.2 (Berkeley) 1/18/91
+ */
+
+#ifndef _MACHINE_FRAME_H_
+#define _MACHINE_FRAME_H_ 1
+
+/*
+ * System stack frames.
+ */
+
+#ifdef __i386__
+/*
+ * Exception/Trap Stack Frame
+ */
+
+struct trapframe {
+ int tf_fs;
+ int tf_es;
+ int tf_ds;
+ int tf_edi;
+ int tf_esi;
+ int tf_ebp;
+ int tf_isp;
+ int tf_ebx;
+ int tf_edx;
+ int tf_ecx;
+ int tf_eax;
+ int tf_trapno;
+ /* below portion defined in 386 hardware */
+ int tf_err;
+ int tf_eip;
+ int tf_cs;
+ int tf_eflags;
+ /* below only when crossing rings (user to kernel) */
+ int tf_esp;
+ int tf_ss;
+};
+
+/* Superset of trap frame, for traps from virtual-8086 mode */
+
+struct trapframe_vm86 {
+ int tf_fs;
+ int tf_es;
+ int tf_ds;
+ int tf_edi;
+ int tf_esi;
+ int tf_ebp;
+ int tf_isp;
+ int tf_ebx;
+ int tf_edx;
+ int tf_ecx;
+ int tf_eax;
+ int tf_trapno;
+ /* below portion defined in 386 hardware */
+ int tf_err;
+ int tf_eip;
+ int tf_cs;
+ int tf_eflags;
+ /* below only when crossing rings (user (including vm86) to kernel) */
+ int tf_esp;
+ int tf_ss;
+ /* below only when crossing from vm86 mode to kernel */
+ int tf_vm86_es;
+ int tf_vm86_ds;
+ int tf_vm86_fs;
+ int tf_vm86_gs;
+};
+
+/*
+ * This alias for the MI TRAPF_USERMODE() should be used when we don't
+ * care about user mode itself, but need to know if a frame has stack
+ * registers. The difference is only logical, but on i386 the logic
+ * for using TRAPF_USERMODE() is complicated by sometimes treating vm86
+ * bioscall mode (which is a special ring 3 user mode) as kernel mode.
+ */
+#define TF_HAS_STACKREGS(tf) TRAPF_USERMODE(tf)
+#endif /* __i386__ */
+
+#ifdef __amd64__
+/*
+ * Exception/Trap Stack Frame
+ *
+ * The ordering of this is specifically so that we can take first 6
+ * the syscall arguments directly from the beginning of the frame.
+ */
+
+struct trapframe {
+ register_t tf_rdi;
+ register_t tf_rsi;
+ register_t tf_rdx;
+ register_t tf_rcx;
+ register_t tf_r8;
+ register_t tf_r9;
+ register_t tf_rax;
+ register_t tf_rbx;
+ register_t tf_rbp;
+ register_t tf_r10;
+ register_t tf_r11;
+ register_t tf_r12;
+ register_t tf_r13;
+ register_t tf_r14;
+ register_t tf_r15;
+ uint32_t tf_trapno;
+ uint16_t tf_fs;
+ uint16_t tf_gs;
+ register_t tf_addr;
+ uint32_t tf_flags;
+ uint16_t tf_es;
+ uint16_t tf_ds;
+ /* below portion defined in hardware */
+ register_t tf_err;
+ register_t tf_rip;
+ register_t tf_cs;
+ register_t tf_rflags;
+ /* the amd64 frame always has the stack registers */
+ register_t tf_rsp;
+ register_t tf_ss;
+};
+
+#define TF_HASSEGS 0x1
+#define TF_HASBASES 0x2
+#define TF_HASFPXSTATE 0x4
+#endif /* __amd64__ */
+
+#endif /* _MACHINE_FRAME_H_ */
diff --git a/usr/src/boot/sys/x86/include/segments.h b/usr/src/boot/sys/x86/include/segments.h
new file mode 100644
index 0000000000..10e03b722d
--- /dev/null
+++ b/usr/src/boot/sys/x86/include/segments.h
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 1989, 1990 William F. Jolitz
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 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.
+ *
+ * from: @(#)segments.h 7.1 (Berkeley) 5/9/91
+ */
+
+#ifndef _X86_SEGMENTS_H_
+#define _X86_SEGMENTS_H_
+
+/*
+ * X86 Segmentation Data Structures and definitions
+ */
+
+/*
+ * Selectors
+ */
+#define SEL_RPL_MASK 3 /* requester priv level */
+#define ISPL(s) ((s)&3) /* priority level of a selector */
+#define SEL_KPL 0 /* kernel priority level */
+#define SEL_UPL 3 /* user priority level */
+#define ISLDT(s) ((s)&SEL_LDT) /* is it local or global */
+#define SEL_LDT 4 /* local descriptor table */
+#define IDXSEL(s) (((s)>>3) & 0x1fff) /* index of selector */
+#define LSEL(s,r) (((s)<<3) | SEL_LDT | r) /* a local selector */
+#define GSEL(s,r) (((s)<<3) | r) /* a global selector */
+
+/*
+ * User segment descriptors (%cs, %ds etc for i386 apps. 64 bit wide)
+ * For long-mode apps, %cs only has the conforming bit in sd_type, the sd_dpl,
+ * sd_p, sd_l and sd_def32 which must be zero). %ds only has sd_p.
+ */
+struct segment_descriptor {
+ unsigned sd_lolimit:16; /* segment extent (lsb) */
+ unsigned sd_lobase:24; /* segment base address (lsb) */
+ unsigned sd_type:5; /* segment type */
+ unsigned sd_dpl:2; /* segment descriptor priority level */
+ unsigned sd_p:1; /* segment descriptor present */
+ unsigned sd_hilimit:4; /* segment extent (msb) */
+ unsigned sd_xx:2; /* unused */
+ unsigned sd_def32:1; /* default 32 vs 16 bit size */
+ unsigned sd_gran:1; /* limit granularity (byte/page units)*/
+ unsigned sd_hibase:8; /* segment base address (msb) */
+} __packed;
+
+struct user_segment_descriptor {
+ unsigned sd_lolimit:16; /* segment extent (lsb) */
+ unsigned sd_lobase:24; /* segment base address (lsb) */
+ unsigned sd_type:5; /* segment type */
+ unsigned sd_dpl:2; /* segment descriptor priority level */
+ unsigned sd_p:1; /* segment descriptor present */
+ unsigned sd_hilimit:4; /* segment extent (msb) */
+ unsigned sd_xx:1; /* unused */
+ unsigned sd_long:1; /* long mode (cs only) */
+ unsigned sd_def32:1; /* default 32 vs 16 bit size */
+ unsigned sd_gran:1; /* limit granularity (byte/page units)*/
+ unsigned sd_hibase:8; /* segment base address (msb) */
+} __packed;
+
+#define USD_GETBASE(sd) (((sd)->sd_lobase) | (sd)->sd_hibase << 24)
+#define USD_SETBASE(sd, b) (sd)->sd_lobase = (b); \
+ (sd)->sd_hibase = ((b) >> 24);
+#define USD_GETLIMIT(sd) (((sd)->sd_lolimit) | (sd)->sd_hilimit << 16)
+#define USD_SETLIMIT(sd, l) (sd)->sd_lolimit = (l); \
+ (sd)->sd_hilimit = ((l) >> 16);
+
+#ifdef __i386__
+/*
+ * Gate descriptors (e.g. indirect descriptors)
+ */
+struct gate_descriptor {
+ unsigned gd_looffset:16; /* gate offset (lsb) */
+ unsigned gd_selector:16; /* gate segment selector */
+ unsigned gd_stkcpy:5; /* number of stack wds to cpy */
+ unsigned gd_xx:3; /* unused */
+ unsigned gd_type:5; /* segment type */
+ unsigned gd_dpl:2; /* segment descriptor priority level */
+ unsigned gd_p:1; /* segment descriptor present */
+ unsigned gd_hioffset:16; /* gate offset (msb) */
+} __packed;
+
+/*
+ * Generic descriptor
+ */
+union descriptor {
+ struct segment_descriptor sd;
+ struct gate_descriptor gd;
+};
+#else
+/*
+ * Gate descriptors (e.g. indirect descriptors, trap, interrupt etc. 128 bit)
+ * Only interrupt and trap gates have gd_ist.
+ */
+struct gate_descriptor {
+ uint64_t gd_looffset:16; /* gate offset (lsb) */
+ uint64_t gd_selector:16; /* gate segment selector */
+ uint64_t gd_ist:3; /* IST table index */
+ uint64_t gd_xx:5; /* unused */
+ uint64_t gd_type:5; /* segment type */
+ uint64_t gd_dpl:2; /* segment descriptor priority level */
+ uint64_t gd_p:1; /* segment descriptor present */
+ uint64_t gd_hioffset:48; /* gate offset (msb) */
+ uint64_t sd_xx1:32;
+} __packed;
+
+/*
+ * Generic descriptor
+ */
+union descriptor {
+ struct user_segment_descriptor sd;
+ struct gate_descriptor gd;
+};
+#endif
+
+ /* system segments and gate types */
+#define SDT_SYSNULL 0 /* system null */
+#define SDT_SYS286TSS 1 /* system 286 TSS available */
+#define SDT_SYSLDT 2 /* system local descriptor table */
+#define SDT_SYS286BSY 3 /* system 286 TSS busy */
+#define SDT_SYS286CGT 4 /* system 286 call gate */
+#define SDT_SYSTASKGT 5 /* system task gate */
+#define SDT_SYS286IGT 6 /* system 286 interrupt gate */
+#define SDT_SYS286TGT 7 /* system 286 trap gate */
+#define SDT_SYSNULL2 8 /* system null again */
+#define SDT_SYS386TSS 9 /* system 386 TSS available */
+#define SDT_SYSTSS 9 /* system available 64 bit TSS */
+#define SDT_SYSNULL3 10 /* system null again */
+#define SDT_SYS386BSY 11 /* system 386 TSS busy */
+#define SDT_SYSBSY 11 /* system busy 64 bit TSS */
+#define SDT_SYS386CGT 12 /* system 386 call gate */
+#define SDT_SYSCGT 12 /* system 64 bit call gate */
+#define SDT_SYSNULL4 13 /* system null again */
+#define SDT_SYS386IGT 14 /* system 386 interrupt gate */
+#define SDT_SYSIGT 14 /* system 64 bit interrupt gate */
+#define SDT_SYS386TGT 15 /* system 386 trap gate */
+#define SDT_SYSTGT 15 /* system 64 bit trap gate */
+
+ /* memory segment types */
+#define SDT_MEMRO 16 /* memory read only */
+#define SDT_MEMROA 17 /* memory read only accessed */
+#define SDT_MEMRW 18 /* memory read write */
+#define SDT_MEMRWA 19 /* memory read write accessed */
+#define SDT_MEMROD 20 /* memory read only expand dwn limit */
+#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */
+#define SDT_MEMRWD 22 /* memory read write expand dwn limit */
+#define SDT_MEMRWDA 23 /* memory read write expand dwn limit accessed*/
+#define SDT_MEME 24 /* memory execute only */
+#define SDT_MEMEA 25 /* memory execute only accessed */
+#define SDT_MEMER 26 /* memory execute read */
+#define SDT_MEMERA 27 /* memory execute read accessed */
+#define SDT_MEMEC 28 /* memory execute only conforming */
+#define SDT_MEMEAC 29 /* memory execute only accessed conforming */
+#define SDT_MEMERC 30 /* memory execute read conforming */
+#define SDT_MEMERAC 31 /* memory execute read accessed conforming */
+
+/*
+ * Size of IDT table
+ */
+#define NIDT 256 /* 32 reserved, 0x80 syscall, most are h/w */
+#define NRSVIDT 32 /* reserved entries for cpu exceptions */
+
+/*
+ * Entries in the Interrupt Descriptor Table (IDT)
+ */
+#define IDT_DE 0 /* #DE: Divide Error */
+#define IDT_DB 1 /* #DB: Debug */
+#define IDT_NMI 2 /* Nonmaskable External Interrupt */
+#define IDT_BP 3 /* #BP: Breakpoint */
+#define IDT_OF 4 /* #OF: Overflow */
+#define IDT_BR 5 /* #BR: Bound Range Exceeded */
+#define IDT_UD 6 /* #UD: Undefined/Invalid Opcode */
+#define IDT_NM 7 /* #NM: No Math Coprocessor */
+#define IDT_DF 8 /* #DF: Double Fault */
+#define IDT_FPUGP 9 /* Coprocessor Segment Overrun */
+#define IDT_TS 10 /* #TS: Invalid TSS */
+#define IDT_NP 11 /* #NP: Segment Not Present */
+#define IDT_SS 12 /* #SS: Stack Segment Fault */
+#define IDT_GP 13 /* #GP: General Protection Fault */
+#define IDT_PF 14 /* #PF: Page Fault */
+#define IDT_MF 16 /* #MF: FPU Floating-Point Error */
+#define IDT_AC 17 /* #AC: Alignment Check */
+#define IDT_MC 18 /* #MC: Machine Check */
+#define IDT_XF 19 /* #XF: SIMD Floating-Point Exception */
+#define IDT_IO_INTS NRSVIDT /* Base of IDT entries for I/O interrupts. */
+#define IDT_SYSCALL 0x80 /* System Call Interrupt Vector */
+#define IDT_DTRACE_RET 0x92 /* DTrace pid provider Interrupt Vector */
+#define IDT_EVTCHN 0x93 /* Xen HVM Event Channel Interrupt Vector */
+
+#if defined(__i386__)
+/*
+ * Entries in the Global Descriptor Table (GDT)
+ * Note that each 4 entries share a single 32 byte L1 cache line.
+ * Some of the fast syscall instructions require a specific order here.
+ */
+#define GNULL_SEL 0 /* Null Descriptor */
+#define GPRIV_SEL 1 /* SMP Per-Processor Private Data */
+#define GUFS_SEL 2 /* User %fs Descriptor (order critical: 1) */
+#define GUGS_SEL 3 /* User %gs Descriptor (order critical: 2) */
+#define GCODE_SEL 4 /* Kernel Code Descriptor (order critical: 1) */
+#define GDATA_SEL 5 /* Kernel Data Descriptor (order critical: 2) */
+#define GUCODE_SEL 6 /* User Code Descriptor (order critical: 3) */
+#define GUDATA_SEL 7 /* User Data Descriptor (order critical: 4) */
+#define GBIOSLOWMEM_SEL 8 /* BIOS low memory access (must be entry 8) */
+#define GPROC0_SEL 9 /* Task state process slot zero and up */
+#define GLDT_SEL 10 /* Default User LDT */
+#define GUSERLDT_SEL 11 /* User LDT */
+#define GPANIC_SEL 12 /* Task state to consider panic from */
+#define GBIOSCODE32_SEL 13 /* BIOS interface (32bit Code) */
+#define GBIOSCODE16_SEL 14 /* BIOS interface (16bit Code) */
+#define GBIOSDATA_SEL 15 /* BIOS interface (Data) */
+#define GBIOSUTIL_SEL 16 /* BIOS interface (Utility) */
+#define GBIOSARGS_SEL 17 /* BIOS interface (Arguments) */
+#define GNDIS_SEL 18 /* For the NDIS layer */
+#define NGDT 19
+
+/*
+ * Entries in the Local Descriptor Table (LDT)
+ */
+#define LSYS5CALLS_SEL 0 /* forced by intel BCS */
+#define LSYS5SIGR_SEL 1
+#define LUCODE_SEL 3
+#define LUDATA_SEL 5
+#define NLDT (LUDATA_SEL + 1)
+
+#else /* !__i386__ */
+/*
+ * Entries in the Global Descriptor Table (GDT)
+ */
+#define GNULL_SEL 0 /* Null Descriptor */
+#define GNULL2_SEL 1 /* Null Descriptor */
+#define GUFS32_SEL 2 /* User 32 bit %fs Descriptor */
+#define GUGS32_SEL 3 /* User 32 bit %gs Descriptor */
+#define GCODE_SEL 4 /* Kernel Code Descriptor */
+#define GDATA_SEL 5 /* Kernel Data Descriptor */
+#define GUCODE32_SEL 6 /* User 32 bit code Descriptor */
+#define GUDATA_SEL 7 /* User 32/64 bit Data Descriptor */
+#define GUCODE_SEL 8 /* User 64 bit Code Descriptor */
+#define GPROC0_SEL 9 /* TSS for entering kernel etc */
+/* slot 10 is second half of GPROC0_SEL */
+#define GUSERLDT_SEL 11 /* LDT */
+/* slot 12 is second half of GUSERLDT_SEL */
+#define NGDT 13
+#endif /* __i386__ */
+
+#endif /* !_X86_SEGMENTS_H_ */
diff --git a/usr/src/common/ficl/ficl.h b/usr/src/common/ficl/ficl.h
index eb43250ec8..6db0c81833 100644
--- a/usr/src/common/ficl/ficl.h
+++ b/usr/src/common/ficl/ficl.h
@@ -143,6 +143,7 @@ extern "C" {
#ifdef STAND
#include <stand.h>
#include <sys/stdint.h>
+#include <sys/linker_set.h>
#else
#include <ctype.h>
#include <stdio.h>
@@ -1792,6 +1793,15 @@ FICL_PLATFORM_EXTERN int ficlFileStatus(char *filename, int *status);
FICL_PLATFORM_EXTERN long ficlFileSize(ficlFile *ff);
#endif
+/* Support for linker set inclusions. */
+#ifdef STAND
+typedef void ficlCompileFcn(ficlSystem *);
+
+#define FICL_COMPILE_SET(func) \
+ DATA_SET(Xficl_compile_set, func)
+SET_DECLARE(Xficl_compile_set, ficlCompileFcn);
+#endif /* STAND */
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/common/ficl/loader.c b/usr/src/common/ficl/loader.c
index 054beba91a..6726e1998e 100644
--- a/usr/src/common/ficl/loader.c
+++ b/usr/src/common/ficl/loader.c
@@ -56,13 +56,6 @@
#include <string.h>
#include "ficl.h"
-extern int biospci_count_device_type(uint32_t);
-extern int biospci_write_config(uint32_t, int, int, uint32_t);
-extern int biospci_read_config(uint32_t, int, int, uint32_t *);
-extern int biospci_find_devclass(uint32_t, int, uint32_t *);
-extern int biospci_find_device(uint32_t, int, uint32_t *);
-extern uint32_t biospci_locator(uint8_t, uint8_t, uint8_t);
-
/*
* FreeBSD's loader interaction words and extras
*
@@ -73,8 +66,6 @@ extern uint32_t biospci_locator(uint8_t, uint8_t, uint8_t);
* copyin ( addr addr' len -- )
* copyout ( addr addr' len -- )
* findfile ( name len type len' -- addr )
- * pnpdevices ( -- addr )
- * pnphandlers ( -- addr )
* ccall ( [[...[p10] p9] ... p1] n addr -- result )
* uuid-from-string ( addr n -- addr' )
* uuid-to-string ( addr' -- addr n | -1 )
@@ -279,35 +270,6 @@ ficlFindfile(ficlVm *pVM)
ficlStackPushPointer(ficlVmGetDataStack(pVM), fp);
}
-#ifdef STAND
-#ifdef HAVE_PNP
-
-void
-ficlPnpdevices(ficlVm *pVM)
-{
- static int pnp_devices_initted = 0;
-
- FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
-
- if (!pnp_devices_initted) {
- STAILQ_INIT(&pnp_devices);
- pnp_devices_initted = 1;
- }
-
- ficlStackPushPointer(ficlVmGetDataStack(pVM), &pnp_devices);
-}
-
-void
-ficlPnphandlers(ficlVm *pVM)
-{
- FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
-
- ficlStackPushPointer(ficlVmGetDataStack(pVM), pnphandlers);
-}
-
-#endif
-#endif /* ifdef STAND */
-
void
ficlCcall(ficlVm *pVM)
{
@@ -923,139 +885,6 @@ ficlInb(ficlVm *pVM)
c = inb(port);
ficlStackPushInteger(ficlVmGetDataStack(pVM), c);
}
-
-/*
- * pcibios-device-count (devid -- count)
- *
- * Returns the PCI BIOS' count of how many devices matching devid are
- * in the system. devid is the 32-bit vendor + device.
- */
-static void
-ficlPciBiosCountDevices(ficlVm *pVM)
-{
- uint32_t devid;
- int i;
-
- devid = ficlStackPopInteger(ficlVmGetDataStack(pVM));
-
- i = biospci_count_device_type(devid);
-
- ficlStackPushInteger(ficlVmGetDataStack(pVM), i);
-}
-
-/*
- * pcibios-write-config (locator offset width value -- )
- *
- * Writes the specified config register.
- * Locator is bus << 8 | device << 3 | fuction
- * offset is the pci config register
- * width is 0 for byte, 1 for word, 2 for dword
- * value is the value to write
- */
-static void
-ficlPciBiosWriteConfig(ficlVm *pVM)
-{
- uint32_t value, width, offset, locator;
-
- value = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- width = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- offset = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- locator = ficlStackPopInteger(ficlVmGetDataStack(pVM));
-
- biospci_write_config(locator, offset, width, value);
-}
-
-/*
- * pcibios-read-config (locator offset width -- value)
- *
- * Reads the specified config register.
- * Locator is bus << 8 | device << 3 | fuction
- * offset is the pci config register
- * width is 0 for byte, 1 for word, 2 for dword
- * value is the value to read from the register
- */
-static void
-ficlPciBiosReadConfig(ficlVm *pVM)
-{
- uint32_t value, width, offset, locator;
-
- width = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- offset = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- locator = ficlStackPopInteger(ficlVmGetDataStack(pVM));
-
- biospci_read_config(locator, offset, width, &value);
-
- ficlStackPushInteger(ficlVmGetDataStack(pVM), value);
-}
-
-/*
- * pcibios-find-devclass (class index -- locator)
- *
- * Finds the index'th instance of class in the pci tree.
- * must be an exact match.
- * class is the class to search for.
- * index 0..N (set to 0, increment until error)
- *
- * Locator is bus << 8 | device << 3 | fuction (or -1 on error)
- */
-static void
-ficlPciBiosFindDevclass(ficlVm *pVM)
-{
- uint32_t index, class, locator;
-
- index = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- class = ficlStackPopInteger(ficlVmGetDataStack(pVM));
-
- if (biospci_find_devclass(class, index, &locator))
- locator = 0xffffffff;
-
- ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
-}
-
-/*
- * pcibios-find-device(devid index -- locator)
- *
- * Finds the index'th instance of devid in the pci tree.
- * must be an exact match.
- * class is the class to search for.
- * index 0..N (set to 0, increment until error)
- *
- * Locator is bus << 8 | device << 3 | fuction (or -1 on error)
- */
-static void
-ficlPciBiosFindDevice(ficlVm *pVM)
-{
- uint32_t index, devid, locator;
-
- index = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- devid = ficlStackPopInteger(ficlVmGetDataStack(pVM));
-
- if (biospci_find_device(devid, index, &locator))
- locator = 0xffffffff;
-
- ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
-}
-
-/*
- * pcibios-find-device(bus device function -- locator)
- *
- * converts bus, device, function to locator.
- *
- * Locator is bus << 8 | device << 3 | fuction
- */
-static void
-ficlPciBiosLocator(ficlVm *pVM)
-{
- uint32_t bus, device, function, locator;
-
- function = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- device = ficlStackPopInteger(ficlVmGetDataStack(pVM));
- bus = ficlStackPopInteger(ficlVmGetDataStack(pVM));
-
- locator = biospci_locator(bus, device, function);
-
- ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
-}
#endif
#endif
@@ -1078,6 +907,9 @@ ficlSystemCompilePlatform(ficlSystem *pSys)
{
ficlDictionary *dp = ficlSystemGetDictionary(pSys);
ficlDictionary *env = ficlSystemGetEnvironment(pSys);
+#ifdef STAND
+ ficlCompileFcn **fnpp;
+#endif
FICL_SYSTEM_ASSERT(pSys, dp);
FICL_SYSTEM_ASSERT(pSys, env);
@@ -1126,26 +958,9 @@ ficlSystemCompilePlatform(ficlSystem *pSys)
ficlDictionarySetPrimitive(dp, "outb", ficlOutb, FICL_WORD_DEFAULT);
ficlDictionarySetPrimitive(dp, "inb", ficlInb, FICL_WORD_DEFAULT);
#endif
-#ifdef HAVE_PNP
- ficlDictionarySetPrimitive(dp, "pnpdevices", ficlPnpdevices,
- FICL_WORD_DEFAULT);
- ficlDictionarySetPrimitive(dp, "pnphandlers", ficlPnphandlers,
- FICL_WORD_DEFAULT);
-#endif
-#ifdef __i386__
- ficlDictionarySetPrimitive(dp, "pcibios-device-count",
- ficlPciBiosCountDevices, FICL_WORD_DEFAULT);
- ficlDictionarySetPrimitive(dp, "pcibios-read-config",
- ficlPciBiosReadConfig, FICL_WORD_DEFAULT);
- ficlDictionarySetPrimitive(dp, "pcibios-write-config",
- ficlPciBiosWriteConfig, FICL_WORD_DEFAULT);
- ficlDictionarySetPrimitive(dp, "pcibios-find-devclass",
- ficlPciBiosFindDevclass, FICL_WORD_DEFAULT);
- ficlDictionarySetPrimitive(dp, "pcibios-find-device",
- ficlPciBiosFindDevice, FICL_WORD_DEFAULT);
- ficlDictionarySetPrimitive(dp, "pcibios-locator", ficlPciBiosLocator,
- FICL_WORD_DEFAULT);
-#endif
+ /* Register words from linker set. */
+ SET_FOREACH(fnpp, Xficl_compile_set)
+ (*fnpp)(pSys);
#endif
#if defined(__i386__) || defined(__amd64__)
diff --git a/usr/src/pkg/manifests/system-boot-loader.mf b/usr/src/pkg/manifests/system-boot-loader.mf
index 03acd116ac..c9fcbe4a35 100644
--- a/usr/src/pkg/manifests/system-boot-loader.mf
+++ b/usr/src/pkg/manifests/system-boot-loader.mf
@@ -52,6 +52,7 @@ $(i386_ONLY)file path=boot/forth/brand.4th group=sys mode=0444
$(i386_ONLY)file path=boot/forth/check-password.4th group=sys mode=0444
$(i386_ONLY)file path=boot/forth/color.4th group=sys mode=0444
$(i386_ONLY)file path=boot/forth/delay.4th group=sys mode=0444
+$(i386_ONLY)file path=boot/forth/efi.4th group=sys mode=0444
$(i386_ONLY)file path=boot/forth/frames.4th group=sys mode=0444
$(i386_ONLY)file path=boot/forth/loader.4th group=sys mode=0444
$(i386_ONLY)file path=boot/forth/logo-beastie.4th group=sys mode=0444
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c
index 66beefb400..daaa56ff5e 100644
--- a/usr/src/uts/i86pc/os/cpuid.c
+++ b/usr/src/uts/i86pc/os/cpuid.c
@@ -975,12 +975,6 @@ setup_xfem(void)
if (is_x86_feature(x86_featureset, X86FSET_AVX))
flags |= XFEATURE_AVX;
- /*
- * TBD:
- * if (is_x86_feature(x86_featureset, X86FSET_MPX))
- * flags |= XFEATURE_MPX;
- */
-
if (is_x86_feature(x86_featureset, X86FSET_AVX512F))
flags |= XFEATURE_AVX512;
diff --git a/usr/src/uts/intel/ia32/ml/float.s b/usr/src/uts/intel/ia32/ml/float.s
index 4c45bce3d3..0d33365764 100644
--- a/usr/src/uts/intel/ia32/ml/float.s
+++ b/usr/src/uts/intel/ia32/ml/float.s
@@ -283,6 +283,11 @@ xsaveopt_ctxt(void *arg)
/*ARGSUSED*/
void
+xsaveopt_ctxt(void *arg)
+{}
+
+/*ARGSUSED*/
+void
fpxsave_ctxt(void *arg)
{}
diff --git a/usr/src/uts/intel/io/pci/pci_resource.c b/usr/src/uts/intel/io/pci/pci_resource.c
index fdaec100b8..4e5c7c051a 100644
--- a/usr/src/uts/intel/io/pci/pci_resource.c
+++ b/usr/src/uts/intel/io/pci/pci_resource.c
@@ -77,21 +77,31 @@ struct memlist *
find_bus_res(int bus, int type)
{
struct memlist *res = NULL;
+ boolean_t bios = B_TRUE;
+
+ /* if efi-systab property exist, there is no BIOS */
+ if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS,
+ "efi-systab")) {
+ bios = B_FALSE;
+ }
if (tbl_init == 0) {
tbl_init = 1;
acpi_pci_probe();
- hrt_probe();
- mps_probe();
+ if (bios) {
+ hrt_probe();
+ mps_probe();
+ }
}
if (acpi_find_bus_res(bus, type, &res) > 0)
return (res);
- if (hrt_find_bus_res(bus, type, &res) > 0)
+ if (bios && hrt_find_bus_res(bus, type, &res) > 0)
return (res);
- (void) mps_find_bus_res(bus, type, &res);
+ if (bios)
+ (void) mps_find_bus_res(bus, type, &res);
return (res);
}
diff --git a/usr/src/uts/sun4/os/machdep.c b/usr/src/uts/sun4/os/machdep.c
index 21d7af3dda..970d5a4125 100644
--- a/usr/src/uts/sun4/os/machdep.c
+++ b/usr/src/uts/sun4/os/machdep.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 201&, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2017, Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>