diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-08-17 11:55:46 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-08-17 11:55:46 +0000 |
commit | ca3ddfea61d5e35b3e017e8fdb707047e5c7a5da (patch) | |
tree | 415771b0b186e37335873005b43b63ff35962512 | |
parent | be5260f18b2d1b464c8281c9e98b8bbe9222af9e (diff) | |
parent | 088d69f878cf3fb57556357236ef8e1c8f9d893e (diff) | |
download | illumos-joyent-ca3ddfea61d5e35b3e017e8fdb707047e5c7a5da.tar.gz |
[illumos-gate merge]
commit 088d69f878cf3fb57556357236ef8e1c8f9d893e
8534 Want AVX-512 Support
8535 kernel cpuid support for new processors
8536 xsave area should size dynamically, based on CPU features
8537 rtld needs to learn about AVX512
8538 add support for xsaveopt for improved context switching
8539 better handling for AMD-specifc *save_ctxt FP exceptions
commit 9c8f3233f955a5f06cea88f930e5d8e131795867
8455 Simple post-mortem reporter for amd64 loader.efi
commit eee590482ee515262a7a144e0c12a96e67315e42
7846 loader: UEFI variable support development
commit d063f3351e94b843161a8f242217845487af0dca
8448 uts: pci_autoconfig should test for BIOS
Conflicts:
usr/src/uts/intel/ia32/ml/float.s
usr/src/uts/i86pc/os/cpuid.c
usr/src/uts/common/os/lwp.c
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> |