diff options
Diffstat (limited to 'usr/src')
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> |