diff --git a/Clover.dsc b/Clover.dsc
index 2609391155..c5ef8a7b2c 100644
--- a/Clover.dsc
+++ b/Clover.dsc
@@ -88,7 +88,7 @@
#EblCmdLib|EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
- UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+ UefiCpuLib|CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
!ifdef ENABLE_SECURE_BOOT
OpensslLib|Library/OpensslLib/openssl-$(OPENSSL_VERSION)/OpensslLib.inf
IntrinsicLib|Library/IntrinsicLib/IntrinsicLib.inf
@@ -135,10 +135,10 @@
#SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
#SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
- MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ MtrrLib|CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf
- LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
- #LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
+ LocalApicLib|CloverEFI/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+ #LocalApicLib|CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
#
# To save size, use NULL library for DebugLib and ReportStatusCodeLib.
@@ -595,7 +595,7 @@
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
}
MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
- UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+ CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
#UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
#UefiCpuPkg/CpuDxe/CpuDxe.inf
#UefiCpuPkg/CpuDxe/CpuDxe.inf
diff --git a/Clover.fdf b/Clover.fdf
index 940cd348c5..febb5fdf88 100644
--- a/Clover.fdf
+++ b/Clover.fdf
@@ -104,7 +104,7 @@ INF CloverEFI/OsxSmbiosGenDxe/SmbiosGen.inf
INF CloverEFI/OsxBdsDxe/BdsDxe.inf
INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
-#INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
#INF UefiCpuPkg/CpuDxe/CpuDxe.inf
#INF IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.c b/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.c
new file mode 100755
index 0000000000..c090211b5b
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.c
@@ -0,0 +1,1329 @@
+/** @file
+ CPU DXE Module.
+
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include "CpuDxe.h"
+
+#define USE_MTRR 0
+
+//
+// Global Variables
+//
+IA32_IDT_GATE_DESCRIPTOR gIdtTable[INTERRUPT_VECTOR_NUMBER] = { { { 0 } } };
+
+EFI_CPU_INTERRUPT_HANDLER ExternalVectorTable[0x100];
+BOOLEAN InterruptState = FALSE;
+EFI_HANDLE mCpuHandle = NULL;
+BOOLEAN mIsFlushingGCD;
+#if USE_MTRR
+UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
+UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;
+#endif
+IA32_IDT_GATE_DESCRIPTOR *mOrigIdtEntry = NULL;
+UINT16 mOrigIdtEntryCount = 0;
+#if USE_MTRR
+FIXED_MTRR mFixedMtrrTable[] = {
+ {
+ MTRR_LIB_IA32_MTRR_FIX64K_00000,
+ 0,
+ 0x10000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_80000,
+ 0x80000,
+ 0x4000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_A0000,
+ 0xA0000,
+ 0x4000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C0000,
+ 0xC0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C8000,
+ 0xC8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D0000,
+ 0xD0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D8000,
+ 0xD8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E0000,
+ 0xE0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E8000,
+ 0xE8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F0000,
+ 0xF0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F8000,
+ 0xF8000,
+ 0x1000
+ },
+};
+#endif
+
+EFI_CPU_ARCH_PROTOCOL gCpu = {
+ CpuFlushCpuDataCache,
+ CpuEnableInterrupt,
+ CpuDisableInterrupt,
+ CpuGetInterruptState,
+ CpuInit,
+ CpuRegisterInterruptHandler,
+ CpuGetTimerValue,
+ CpuSetMemoryAttributes,
+ 1, // NumberOfTimers
+ 4 // DmaBufferAlignment
+};
+
+//
+// Error code flag indicating whether or not an error code will be
+// pushed on the stack if an exception occurs.
+//
+// 1 means an error code will be pushed, otherwise 0
+//
+// bit 0 - exception 0
+// bit 1 - exception 1
+// etc.
+//
+UINT32 mErrorCodeFlag = 0x00027d00;
+EFI_EVENT IdleLoopEvent;
+
+//
+// Local function prototypes
+//
+
+/**
+ Set Interrupt Descriptor Table Handler Address.
+
+ @param Index The Index of the interrupt descriptor table handle.
+ @param Handler Handler address.
+
+**/
+VOID
+SetInterruptDescriptorTableHandlerAddress (
+ IN UINTN Index,
+ IN VOID *Handler OPTIONAL
+ );
+
+//
+// CPU Arch Protocol Functions
+//
+
+
+/**
+ Common exception handler.
+
+ @param InterruptType Exception type
+ @param SystemContext EFI_SYSTEM_CONTEXT
+
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+#if defined (MDE_CPU_IA32)
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! IA32 Exception Type - %08x !!!!\n",
+ InterruptType
+ ));
+ if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %08x\n",
+ SystemContext.SystemContextIa32->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "CS - %04x, EIP - %08x, EFL - %08x, SS - %04x\n",
+ SystemContext.SystemContextIa32->Cs,
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->Eflags,
+ SystemContext.SystemContextIa32->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DS - %04x, ES - %04x, FS - %04x, GS - %04x\n",
+ SystemContext.SystemContextIa32->Ds,
+ SystemContext.SystemContextIa32->Es,
+ SystemContext.SystemContextIa32->Fs,
+ SystemContext.SystemContextIa32->Gs
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "EAX - %08x, EBX - %08x, ECX - %08x, EDX - %08x\n",
+ SystemContext.SystemContextIa32->Eax,
+ SystemContext.SystemContextIa32->Ebx,
+ SystemContext.SystemContextIa32->Ecx,
+ SystemContext.SystemContextIa32->Edx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
+ SystemContext.SystemContextIa32->Esp,
+ SystemContext.SystemContextIa32->Ebp,
+ SystemContext.SystemContextIa32->Esi,
+ SystemContext.SystemContextIa32->Edi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDT - %08x LIM - %04x, IDT - %08x LIM - %04x\n",
+ SystemContext.SystemContextIa32->Gdtr[0],
+ SystemContext.SystemContextIa32->Gdtr[1],
+ SystemContext.SystemContextIa32->Idtr[0],
+ SystemContext.SystemContextIa32->Idtr[1]
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "LDT - %08x, TR - %08x\n",
+ SystemContext.SystemContextIa32->Ldtr,
+ SystemContext.SystemContextIa32->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
+ SystemContext.SystemContextIa32->Cr0,
+ SystemContext.SystemContextIa32->Cr2,
+ SystemContext.SystemContextIa32->Cr3,
+ SystemContext.SystemContextIa32->Cr4
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
+ SystemContext.SystemContextIa32->Dr0,
+ SystemContext.SystemContextIa32->Dr1,
+ SystemContext.SystemContextIa32->Dr2,
+ SystemContext.SystemContextIa32->Dr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR6 - %08x, DR7 - %08x\n",
+ SystemContext.SystemContextIa32->Dr6,
+ SystemContext.SystemContextIa32->Dr7
+ ));
+#elif defined (MDE_CPU_X64)
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! X64 Exception Type - %016lx !!!!\n",
+ (UINT64)InterruptType
+ ));
+ if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %016lx\n",
+ SystemContext.SystemContextX64->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "RIP - %016lx, RFL - %016lx\n",
+ SystemContext.SystemContextX64->Rip,
+ SystemContext.SystemContextX64->Rflags
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
+ SystemContext.SystemContextX64->Rax,
+ SystemContext.SystemContextX64->Rcx,
+ SystemContext.SystemContextX64->Rdx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
+ SystemContext.SystemContextX64->Rbx,
+ SystemContext.SystemContextX64->Rsp,
+ SystemContext.SystemContextX64->Rbp
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RSI - %016lx, RDI - %016lx\n",
+ SystemContext.SystemContextX64->Rsi,
+ SystemContext.SystemContextX64->Rdi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
+ SystemContext.SystemContextX64->R8,
+ SystemContext.SystemContextX64->R9,
+ SystemContext.SystemContextX64->R10
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
+ SystemContext.SystemContextX64->R11,
+ SystemContext.SystemContextX64->R12,
+ SystemContext.SystemContextX64->R13
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R14 - %016lx, R15 - %016lx\n",
+ SystemContext.SystemContextX64->R14,
+ SystemContext.SystemContextX64->R15
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CS - %04lx, DS - %04lx, ES - %04lx, FS - %04lx, GS - %04lx, SS - %04lx\n",
+ SystemContext.SystemContextX64->Cs,
+ SystemContext.SystemContextX64->Ds,
+ SystemContext.SystemContextX64->Es,
+ SystemContext.SystemContextX64->Fs,
+ SystemContext.SystemContextX64->Gs,
+ SystemContext.SystemContextX64->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDT - %016lx; %04lx, IDT - %016lx; %04lx\n",
+ SystemContext.SystemContextX64->Gdtr[0],
+ SystemContext.SystemContextX64->Gdtr[1],
+ SystemContext.SystemContextX64->Idtr[0],
+ SystemContext.SystemContextX64->Idtr[1]
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "LDT - %016lx, TR - %016lx\n",
+ SystemContext.SystemContextX64->Ldtr,
+ SystemContext.SystemContextX64->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
+ SystemContext.SystemContextX64->Cr0,
+ SystemContext.SystemContextX64->Cr2,
+ SystemContext.SystemContextX64->Cr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR4 - %016lx, CR8 - %016lx\n",
+ SystemContext.SystemContextX64->Cr4,
+ SystemContext.SystemContextX64->Cr8
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
+ SystemContext.SystemContextX64->Dr0,
+ SystemContext.SystemContextX64->Dr1,
+ SystemContext.SystemContextX64->Dr2
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
+ SystemContext.SystemContextX64->Dr3,
+ SystemContext.SystemContextX64->Dr6,
+ SystemContext.SystemContextX64->Dr7
+ ));
+//#else
+//#error CPU type not supported for exception information dump!
+#endif
+
+ //
+ // Hang the system with CpuSleep so the processor will enter a lower power
+ // state.
+ //
+ while (TRUE) {
+ CpuSleep ();
+ };
+}
+
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param This Protocol instance structure
+ @param Start Physical address to start flushing from.
+ @param Length Number of bytes to flush. Round up to chipset
+ granularity.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS If cache was flushed
+ @retval EFI_UNSUPPORTED If flush type is not supported.
+ @retval EFI_DEVICE_ERROR If requested range could not be flushed.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+/**
+ Enables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ EnableInterrupts ();
+
+ InterruptState = TRUE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Disables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ DisableInterrupts ();
+
+ InterruptState = FALSE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return the state of interrupts.
+
+ @param This Protocol instance structure
+ @param State Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = InterruptState;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Generates an INIT to the CPU.
+
+ @param This Protocol instance structure
+ @param InitType Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
+ seen.
+ @retval EFI_DEVICE_ERROR If CPU INIT failed.
+ @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param This Protocol instance structure
+ @param InterruptType Defines which interrupt to hook. IA-32
+ valid range is 0x00 through 0xFF
+ @param InterruptHandler A pointer to a function of type
+ EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. A null
+ pointer is an error condition.
+
+ @retval EFI_SUCCESS If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
+ for InterruptType was previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
+ is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType < 0 || InterruptType > 0xff) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (InterruptHandler == NULL && ExternalVectorTable[InterruptType] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterruptHandler != NULL && ExternalVectorTable[InterruptType] != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ if (InterruptHandler != NULL) {
+ SetInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType, NULL);
+ } else {
+ //
+ // Restore the original IDT handler address if InterruptHandler is NULL.
+ //
+ RestoreInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType);
+ }
+
+ ExternalVectorTable[InterruptType] = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param This - Protocol instance structure.
+ @param TimerIndex - Specifies which CPU timer is requested.
+ @param TimerValue - Pointer to the returned timer value.
+ @param TimerPeriod - A pointer to the amount of time that passes
+ in femtoseconds (10-15) for each increment
+ of TimerValue. If TimerValue does not
+ increment at a predictable rate, then 0 is
+ returned. The amount of time that has
+ passed between two calls to GetTimerValue()
+ can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod.
+ This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerValue = AsmReadTsc ();
+
+ if (TimerPeriod != NULL) {
+ //
+ // BugBug: Hard coded. Don't know how to do this generically
+ //
+ //Slice: Don't wonder. This value is for Tsc timer.
+ // using ACPI, HPET or TMR timer we will use other value for TimerPeriod.
+ // ;)
+ *TimerPeriod = 1000000000;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
+
+ This function modifies the attributes for the memory region specified by BaseAddress and
+ Length from their current attributes to the attributes specified by Attributes.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval EFI_SUCCESS The attributes were set for the memory region.
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ Attributes specified an illegal combination of attributes that
+ cannot be set together.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ return EFI_UNSUPPORTED;
+
+#if USE_MTRR /*this is extra bug, we need no it */
+ RETURN_STATUS Status;
+ MTRR_MEMORY_CACHE_TYPE CacheType;
+
+ if (!IsMtrrSupported ()) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If this function is called because GCD SetMemorySpaceAttributes () is called
+ // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory
+ // map with MTRR values. So there is no need to modify MTRRs, just return immediately
+ // to avoid unnecessary computing.
+ //
+ if (mIsFlushingGCD) {
+ DEBUG((EFI_D_ERROR, " Flushing GCD\n"));
+ return EFI_SUCCESS;
+ }
+
+ switch (Attributes) {
+ case EFI_MEMORY_UC:
+ CacheType = CacheUncacheable;
+ break;
+
+ case EFI_MEMORY_WC:
+ CacheType = CacheWriteCombining;
+ break;
+
+ case EFI_MEMORY_WT:
+ CacheType = CacheWriteThrough;
+ break;
+
+ case EFI_MEMORY_WP:
+ CacheType = CacheWriteProtected;
+ break;
+
+ case EFI_MEMORY_WB:
+ CacheType = CacheWriteBack;
+ break;
+
+ case EFI_MEMORY_UCE:
+ case EFI_MEMORY_RP:
+ case EFI_MEMORY_XP:
+ case EFI_MEMORY_RUNTIME:
+ return EFI_UNSUPPORTED;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // call MTRR libary function
+ //
+ Status = MtrrSetMemoryAttribute (
+ BaseAddress,
+ Length,
+ CacheType
+ );
+
+ return (EFI_STATUS) Status;
+#endif
+}
+
+/**
+ Initializes the valid bits mask and valid address mask for MTRRs.
+
+ This function initializes the valid bits mask and valid address mask for MTRRs.
+
+**/
+#if USE_MTRR
+VOID
+InitializeMtrrMask (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+
+ PhysicalAddressBits = (UINT8) RegEax;
+
+ mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
+ mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;
+ } else {
+ mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;
+ mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
+ }
+}
+#endif
+/**
+ Gets GCD Mem Space type from MTRR Type.
+
+ This function gets GCD Mem Space type from MTRR Type.
+
+ @param MtrrAttributes MTRR memory type
+
+ @return GCD Mem Space type
+
+**/
+#if USE_MTRR
+UINT64
+GetMemorySpaceAttributeFromMtrrType (
+ IN UINT8 MtrrAttributes
+ )
+{
+ switch (MtrrAttributes) {
+ case MTRR_CACHE_UNCACHEABLE:
+ return EFI_MEMORY_UC;
+ case MTRR_CACHE_WRITE_COMBINING:
+ return EFI_MEMORY_WC;
+ case MTRR_CACHE_WRITE_THROUGH:
+ return EFI_MEMORY_WT;
+ case MTRR_CACHE_WRITE_PROTECTED:
+ return EFI_MEMORY_WP;
+ case MTRR_CACHE_WRITE_BACK:
+ return EFI_MEMORY_WB;
+ default:
+ return 0;
+ }
+}
+#endif
+/**
+ Searches memory descriptors covered by given memory range.
+
+ This function searches into the Gcd Memory Space for descriptors
+ (from StartIndex to EndIndex) that contains the memory range
+ specified by BaseAddress and Length.
+
+ @param MemorySpaceMap Gcd Memory Space Map as array.
+ @param NumberOfDescriptors Number of descriptors in map.
+ @param BaseAddress BaseAddress for the requested range.
+ @param Length Length for the requested range.
+ @param StartIndex Start index into the Gcd Memory Space Map.
+ @param EndIndex End index into the Gcd Memory Space Map.
+
+ @retval EFI_SUCCESS Search successfully.
+ @retval EFI_NOT_FOUND The requested descriptors does not exist.
+
+**/
+EFI_STATUS
+SearchGcdMemorySpaces (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ OUT UINTN *StartIndex,
+ OUT UINTN *EndIndex
+ )
+{
+ UINTN Index;
+
+ *StartIndex = 0;
+ *EndIndex = 0;
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&
+ BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ *StartIndex = Index;
+ }
+ if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&
+ BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ *EndIndex = Index;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Sets the attributes for a specified range in Gcd Memory Space Map.
+
+ This function sets the attributes for a specified range in
+ Gcd Memory Space Map.
+
+ @param MemorySpaceMap Gcd Memory Space Map as array
+ @param NumberOfDescriptors Number of descriptors in map
+ @param BaseAddress BaseAddress for the range
+ @param Length Length for the range
+ @param Attributes Attributes to set
+
+ @retval EFI_SUCCESS Memory attributes set successfully
+ @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
+
+**/
+EFI_STATUS
+SetGcdMemorySpaceAttributes (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN StartIndex;
+ UINTN EndIndex;
+ EFI_PHYSICAL_ADDRESS RegionStart;
+ UINT64 RegionLength;
+
+ //
+ // Get all memory descriptors covered by the memory range
+ //
+ Status = SearchGcdMemorySpaces (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ &StartIndex,
+ &EndIndex
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Go through all related descriptors and set attributes accordingly
+ //
+ for (Index = StartIndex; Index <= EndIndex; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+ //
+ // Calculate the start and end address of the overlapping range
+ //
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
+ RegionStart = BaseAddress;
+ } else {
+ RegionStart = MemorySpaceMap[Index].BaseAddress;
+ }
+ if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ RegionLength = BaseAddress + Length - RegionStart;
+ } else {
+ RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
+ }
+ //
+ // Set memory attributes according to MTRR attribute and the original attribute of descriptor
+ //
+ gDS->SetMemorySpaceAttributes (
+ RegionStart,
+ RegionLength,
+ (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Refreshes the GCD Memory Space attributes according to MTRRs.
+
+ This function refreshes the GCD Memory Space attributes according to MTRRs.
+
+**/
+#if USE_MTRR
+VOID
+RefreshGcdMemoryAttributes (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN SubIndex;
+ UINT64 RegValue;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ UINT64 Attributes;
+ UINT64 CurrentAttributes;
+ UINT8 MtrrType;
+ UINTN NumberOfDescriptors;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ UINT64 DefaultAttributes;
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ MTRR_FIXED_SETTINGS MtrrFixedSettings;
+ UINT32 FirmwareVariableMtrrCount;
+ UINT8 DefaultMemoryType;
+
+ if (!IsMtrrSupported ()) {
+ return;
+ }
+
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
+ ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ mIsFlushingGCD = TRUE;
+ MemorySpaceMap = NULL;
+
+ //
+ // Initialize the valid bits mask and valid address mask for MTRRs
+ //
+ InitializeMtrrMask ();
+
+ //
+ // Get the memory attribute of variable MTRRs
+ //
+ MtrrGetMemoryAttributeInVariableMtrr (
+ mValidMtrrBitsMask,
+ mValidMtrrAddressMask,
+ VariableMtrr
+ );
+
+ //
+ // Get the memory space map from GCD
+ //
+ Status = gDS->GetMemorySpaceMap (
+ &NumberOfDescriptors,
+ &MemorySpaceMap
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DefaultMemoryType = (UINT8) MtrrGetDefaultMemoryType ();
+ DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);
+
+ //
+ // Set default attributes to all spaces.
+ //
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+ gDS->SetMemorySpaceAttributes (
+ MemorySpaceMap[Index].BaseAddress,
+ MemorySpaceMap[Index].Length,
+ (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |
+ (MemorySpaceMap[Index].Capabilities & DefaultAttributes)
+ );
+ }
+
+ //
+ // Go for variable MTRRs with WB attribute
+ //
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
+ if (VariableMtrr[Index].Valid &&
+ VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ VariableMtrr[Index].BaseAddress,
+ VariableMtrr[Index].Length,
+ EFI_MEMORY_WB
+ );
+ }
+ }
+
+ //
+ // Go for variable MTRRs with the attribute except for WB and UC attributes
+ //
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
+ if (VariableMtrr[Index].Valid &&
+ VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK &&
+ VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE) {
+ Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ VariableMtrr[Index].BaseAddress,
+ VariableMtrr[Index].Length,
+ Attributes
+ );
+ }
+ }
+
+ //
+ // Go for variable MTRRs with UC attribute
+ //
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
+ if (VariableMtrr[Index].Valid &&
+ VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ VariableMtrr[Index].BaseAddress,
+ VariableMtrr[Index].Length,
+ EFI_MEMORY_UC
+ );
+ }
+ }
+
+ //
+ // Go for fixed MTRRs
+ //
+ Attributes = 0;
+ BaseAddress = 0;
+ Length = 0;
+ MtrrGetFixedMtrr (&MtrrFixedSettings);
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ RegValue = MtrrFixedSettings.Mtrr[Index];
+ //
+ // Check for continuous fixed MTRR sections
+ //
+ for (SubIndex = 0; SubIndex < 8; SubIndex++) {
+ MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);
+ CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);
+ if (Length == 0) {
+ //
+ // A new MTRR attribute begins
+ //
+ Attributes = CurrentAttributes;
+ } else {
+ //
+ // If fixed MTRR attribute changed, then set memory attribute for previous atrribute
+ //
+ if (CurrentAttributes != Attributes) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;
+ Length = 0;
+ Attributes = CurrentAttributes;
+ }
+ }
+ Length += mFixedMtrrTable[Index].Length;
+ }
+ }
+ //
+ // Handle the last fixed MTRR region
+ //
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+
+ //
+ // Free memory space map allocated by GCD service GetMemorySpaceMap ()
+ //
+ if (MemorySpaceMap != NULL) {
+ FreePool (MemorySpaceMap);
+ }
+
+ mIsFlushingGCD = FALSE;
+}
+#endif
+/**
+ Set Interrupt Descriptor Table Handler Address.
+
+ @param Index The Index of the interrupt descriptor table handle.
+ @param Handler Handler address.
+
+**/
+VOID
+SetInterruptDescriptorTableHandlerAddress (
+ IN UINTN Index,
+ IN VOID *Handler OPTIONAL
+ )
+{
+ UINTN UintnHandler;
+
+ if (Handler != NULL) {
+ UintnHandler = (UINTN) Handler;
+ } else {
+ UintnHandler = ((UINTN) AsmIdtVector00) + (8 * Index);
+ }
+
+ gIdtTable[Index].Bits.OffsetLow = (UINT16)UintnHandler;
+ gIdtTable[Index].Bits.Reserved_0 = 0;
+ gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ gIdtTable[Index].Bits.OffsetHigh = (UINT16)(UintnHandler >> 16);
+#if defined (MDE_CPU_X64)
+ gIdtTable[Index].Bits.OffsetUpper = (UINT32)(UintnHandler >> 32);
+ gIdtTable[Index].Bits.Reserved_1 = 0;
+#endif
+}
+
+/**
+ Restore original Interrupt Descriptor Table Handler Address.
+
+ @param Index The Index of the interrupt descriptor table handle.
+
+**/
+VOID
+RestoreInterruptDescriptorTableHandlerAddress (
+ IN UINTN Index
+ )
+{
+ if (Index < mOrigIdtEntryCount) {
+ gIdtTable[Index].Bits.OffsetLow = mOrigIdtEntry[Index].Bits.OffsetLow;
+ gIdtTable[Index].Bits.OffsetHigh = mOrigIdtEntry[Index].Bits.OffsetHigh;
+#if defined (MDE_CPU_X64)
+ gIdtTable[Index].Bits.OffsetUpper = mOrigIdtEntry[Index].Bits.OffsetUpper;
+#endif
+ }
+ if (Index >= mOrigIdtEntryCount)
+ return;
+ CopyMem(gIdtTable + Index, mOrigIdtEntry + Index,
+ sizeof(gIdtTable[Index]));
+}
+
+/**
+ Initialize Interrupt Descriptor Table for interrupt handling.
+
+**/
+VOID
+InitInterruptDescriptorTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ IA32_DESCRIPTOR OldIdtPtr;
+ IA32_IDT_GATE_DESCRIPTOR *OldIdt;
+ UINTN OldIdtSize;
+ VOID *IdtPtrAlignmentBuffer;
+ IA32_DESCRIPTOR *IdtPtr;
+ UINTN Index;
+ UINT16 CurrentCs;
+ VOID *IntHandler;
+
+ SetMem (ExternalVectorTable, sizeof(ExternalVectorTable), 0);
+
+ //
+ // Get original IDT address and size.
+ //
+ AsmReadIdtr ((IA32_DESCRIPTOR *) &OldIdtPtr);
+
+ if ((OldIdtPtr.Base != 0) && ((OldIdtPtr.Limit & 7) == 7)) {
+ OldIdt = (IA32_IDT_GATE_DESCRIPTOR*) OldIdtPtr.Base;
+ OldIdtSize = (OldIdtPtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
+ //
+ // Save original IDT entry and IDT entry count.
+ //
+ mOrigIdtEntry = AllocateCopyPool (OldIdtPtr.Limit + 1, (VOID *) OldIdtPtr.Base);
+// ASSERT (mOrigIdtEntry != NULL);
+ mOrigIdtEntryCount = (UINT16) OldIdtSize;
+ } else {
+ OldIdt = NULL;
+ OldIdtSize = 0;
+ }
+
+ //
+ // Intialize IDT
+ //
+ CurrentCs = AsmReadCs();
+ for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++) {
+ //
+ // If the old IDT had a handler for this interrupt, then
+ // preserve it.
+ //
+ if (Index < OldIdtSize) {
+ IntHandler =
+ (VOID*) (
+ OldIdt[Index].Bits.OffsetLow +
+ (((UINTN) OldIdt[Index].Bits.OffsetHigh) << 16)
+#if defined (MDE_CPU_X64)
+ + (((UINTN) OldIdt[Index].Bits.OffsetUpper) << 32)
+#endif
+ );
+ } else {
+ IntHandler = NULL;
+ }
+#if 1 //patch by nms42 for AMD CPU
+ if (Index == 0x6F) {
+ IntHandler = NULL;
+ }
+#endif
+
+ gIdtTable[Index].Bits.Selector = CurrentCs;
+ gIdtTable[Index].Bits.Reserved_0 = 0;
+ gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ SetInterruptDescriptorTableHandlerAddress (Index, IntHandler);
+ }
+
+ //
+ // Load IDT Pointer
+ //
+ IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16);
+ IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16);
+// IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1));
+ IdtPtr->Base = (UINTN)(VOID*) gIdtTable;
+ IdtPtr->Limit = (UINT16) (sizeof (gIdtTable) - 1);
+ AsmWriteIdtr (IdtPtr);
+
+ FreePool (IdtPtrAlignmentBuffer);
+
+ //
+ // Initialize Exception Handlers
+ //
+ for (Index = OldIdtSize; Index < 32; Index++) {
+ Status = CpuRegisterInterruptHandler (&gCpu, Index, CommonExceptionHandler);
+// ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Set the pointer to the array of C based exception handling routines.
+ //
+ InitializeExternalVectorTablePtr (ExternalVectorTable);
+
+}
+
+
+/**
+ Callback function for idle events.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context The pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+IdleLoopEventCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ CpuSleep ();
+}
+
+
+/**
+ Initialize the state information for the CPU Architectural Protocol.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS Thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Cannot create the thread
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+
+// InitializeFloatingPointUnits (); //nah
+
+ //
+ // Make sure interrupts are disabled
+ //
+ DisableInterrupts ();
+
+ //
+ // Init GDT for DXE
+ //
+ InitGlobalDescriptorTable ();
+
+ //
+ // Setup IDT pointer, IDT and interrupt entry points
+ //
+ InitInterruptDescriptorTable ();
+
+ //
+ // Enable the local APIC for Virtual Wire Mode.
+ //
+ ProgramVirtualWireMode ();
+
+ //
+ // Install CPU Architectural Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mCpuHandle,
+ &gEfiCpuArchProtocolGuid, &gCpu,
+ NULL
+ );
+// ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Refresh GCD memory space map according to MTRR value.
+ //
+// RefreshGcdMemoryAttributes ();
+
+ //
+ // Setup a callback for idle events
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ IdleLoopEventCallback,
+ NULL,
+ &gIdleLoopEventGuid,
+ &IdleLoopEvent
+ );
+// ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.h b/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.h
new file mode 100755
index 0000000000..a75ec0593f
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.h
@@ -0,0 +1,292 @@
+/** @file
+ CPU DXE Module.
+
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ 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 _CPU_DXE_H_
+#define _CPU_DXE_H_
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//
+//
+//
+#define INTERRUPT_VECTOR_NUMBER 256
+
+#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | \
+ EFI_MEMORY_WC | \
+ EFI_MEMORY_WT | \
+ EFI_MEMORY_WB | \
+ EFI_MEMORY_UCE \
+ )
+
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param This Protocol instance structure
+ @param Start Physical address to start flushing from.
+ @param Length Number of bytes to flush. Round up to chipset
+ granularity.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS If cache was flushed
+ @retval EFI_UNSUPPORTED If flush type is not supported.
+ @retval EFI_DEVICE_ERROR If requested range could not be flushed.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+/**
+ Enables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ Disables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ Return the state of interrupts.
+
+ @param This Protocol instance structure
+ @param State Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+/**
+ Generates an INIT to the CPU.
+
+ @param This Protocol instance structure
+ @param InitType Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
+ seen.
+ @retval EFI_DEVICE_ERROR If CPU INIT failed.
+ @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param This Protocol instance structure
+ @param InterruptType Defines which interrupt to hook. IA-32
+ valid range is 0x00 through 0xFF
+ @param InterruptHandler A pointer to a function of type
+ EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. A null
+ pointer is an error condition.
+
+ @retval EFI_SUCCESS If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
+ for InterruptType was previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
+ is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param This - Protocol instance structure.
+ @param TimerIndex - Specifies which CPU timer is requested.
+ @param TimerValue - Pointer to the returned timer value.
+ @param TimerPeriod - A pointer to the amount of time that passes
+ in femtoseconds (10-15) for each increment
+ of TimerValue. If TimerValue does not
+ increment at a predictable rate, then 0 is
+ returned. The amount of time that has
+ passed between two calls to GetTimerValue()
+ can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod.
+ This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+/**
+ Set memory cacheability attributes for given range of memeory.
+
+ @param This Protocol instance structure
+ @param BaseAddress Specifies the start address of the
+ memory range
+ @param Length Specifies the length of the memory range
+ @param Attributes The memory cacheability for the memory range
+
+ @retval EFI_SUCCESS If the cacheability of that memory range is
+ set successfully
+ @retval EFI_UNSUPPORTED If the desired operation cannot be done
+ @retval EFI_INVALID_PARAMETER The input parameter is not correct,
+ such as Length = 0
+
+**/
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+/**
+ Label of base address of IDT vector 0.
+
+ This is just a label of base address of IDT vector 0.
+
+**/
+VOID
+EFIAPI
+AsmIdtVector00 (
+ VOID
+ );
+
+/**
+ Initializes the pointer to the external interrupt vector table.
+
+ @param VectorTable Address of the external interrupt vector table.
+
+**/
+VOID
+EFIAPI
+InitializeExternalVectorTablePtr (
+ EFI_CPU_INTERRUPT_HANDLER *VectorTable
+ );
+
+/**
+ Initialize Global Descriptor Table.
+
+**/
+VOID
+InitGlobalDescriptorTable (
+ VOID
+ );
+
+/**
+ Sets the code selector (CS).
+
+ @param Selector Value of code selector.
+
+**/
+VOID
+EFIAPI
+SetCodeSelector (
+ UINT16 Selector
+ );
+
+/**
+ Sets the data selector (DS).
+
+ @param Selector Value of data selector.
+
+**/
+VOID
+EFIAPI
+SetDataSelectors (
+ UINT16 Selector
+ );
+
+/**
+ Restore original Interrupt Descriptor Table Handler Address.
+
+ @param Index The Index of the interrupt descriptor table handle.
+
+**/
+VOID
+RestoreInterruptDescriptorTableHandlerAddress (
+ IN UINTN Index
+ );
+
+#endif
+
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.inf b/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.inf
new file mode 100755
index 0000000000..6fd981a7cd
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.inf
@@ -0,0 +1,70 @@
+## @file
+#
+# Component description file for simple CPU driver
+#
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuDxeClover
+ FILE_GUID = 1A1E4886-9517-440e-9FDE-3BE44CEE2136
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeCpu
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CpuLib
+ DebugLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ MtrrLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ LocalApicLib
+ UefiCpuLib
+
+[Sources]
+ CpuDxe.c
+ CpuDxe.h
+ CpuGdt.c
+
+ Ia32/IvtAsm.asm | MSFT
+ Ia32/IvtAsm.asm | INTEL
+ Ia32/IvtAsm.S | GCC
+
+[Sources.IA32]
+ Ia32/CpuAsm.asm | MSFT
+ Ia32/CpuAsm.asm | INTEL
+ Ia32/CpuAsm.S | GCC
+
+[Sources.X64]
+ X64/CpuAsm.asm | MSFT
+ X64/CpuAsm.asm | INTEL
+ X64/CpuAsm.S | GCC
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[Guids]
+ gIdleLoopEventGuid ## CONSUMES ## GUID
+
+[Depex]
+ TRUE
+
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/CpuGdt.c b/CloverEFI/UefiCpuPkg/CpuDxe/CpuGdt.c
new file mode 100755
index 0000000000..25d40735c3
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/CpuGdt.c
@@ -0,0 +1,201 @@
+/** @file
+ C based implemention of IA32 interrupt handling only
+ requiring a minimal assembly interrupt entry point.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include "CpuDxe.h"
+
+
+//
+// Local structure definitions
+//
+
+#pragma pack (1)
+
+//
+// Global Descriptor Entry structures
+//
+
+typedef struct _GDT_ENTRY {
+ UINT16 Limit15_0;
+ UINT16 Base15_0;
+ UINT8 Base23_16;
+ UINT8 Type;
+ UINT8 Limit19_16_and_flags;
+ UINT8 Base31_24;
+} GDT_ENTRY;
+
+typedef
+struct _GDT_ENTRIES {
+ GDT_ENTRY Null;
+ GDT_ENTRY Linear;
+ GDT_ENTRY LinearCode;
+ GDT_ENTRY SysData;
+ GDT_ENTRY SysCode;
+ GDT_ENTRY LinearCode64;
+ GDT_ENTRY Spare4;
+ GDT_ENTRY Spare5;
+} GDT_ENTRIES;
+
+#define NULL_SEL OFFSET_OF (GDT_ENTRIES, Null)
+#define LINEAR_SEL OFFSET_OF (GDT_ENTRIES, Linear)
+#define LINEAR_CODE_SEL OFFSET_OF (GDT_ENTRIES, LinearCode)
+#define SYS_DATA_SEL OFFSET_OF (GDT_ENTRIES, SysData)
+#define SYS_CODE_SEL OFFSET_OF (GDT_ENTRIES, SysCode)
+#define LINEAR_CODE64_SEL OFFSET_OF (GDT_ENTRIES, LinearCode64)
+#define SPARE4_SEL OFFSET_OF (GDT_ENTRIES, Spare4)
+#define SPARE5_SEL OFFSET_OF (GDT_ENTRIES, Spare5)
+
+#if defined (MDE_CPU_IA32)
+#define CPU_CODE_SEL LINEAR_CODE_SEL
+#define CPU_DATA_SEL LINEAR_SEL
+#elif defined (MDE_CPU_X64)
+#define CPU_CODE_SEL LINEAR_CODE64_SEL
+#define CPU_DATA_SEL LINEAR_SEL
+//#else
+//#error CPU type not supported for CPU GDT initialization!
+#endif
+
+//
+// Global descriptor table (GDT) Template
+//
+STATIC GDT_ENTRIES GdtTemplate = {
+ //
+ // NULL_SEL
+ //
+ {
+ 0x0, // limit 15:0
+ 0x0, // base 15:0
+ 0x0, // base 23:16
+ 0x0, // type
+ 0x0, // limit 19:16, flags
+ 0x0, // base 31:24
+ },
+ //
+ // LINEAR_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x092, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // LINEAR_CODE_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x09A, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // SYS_DATA_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x092, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // SYS_CODE_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x09A, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // LINEAR_CODE64_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x09B, // present, ring 0, code, expand-up, writable
+ 0x0AF, // LimitHigh (CS.L=1, CS.D=0)
+ 0x0, // base (high)
+ },
+ //
+ // SPARE4_SEL
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x0, // present, ring 0, data, expand-up, writable
+ 0x0, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // SPARE5_SEL
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x0, // present, ring 0, data, expand-up, writable
+ 0x0, // page-granular, 32-bit
+ 0x0,
+ },
+};
+
+/**
+ Initialize Global Descriptor Table.
+
+**/
+VOID
+InitGlobalDescriptorTable (
+ VOID
+ )
+{
+ GDT_ENTRIES *gdt;
+ IA32_DESCRIPTOR gdtPtr;
+
+ //
+ // Allocate Runtime Data for the GDT
+ //
+ gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
+ ASSERT (gdt != NULL);
+ gdt = ALIGN_POINTER (gdt, 8);
+
+ //
+ // Initialize all GDT entries
+ //
+ CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));
+
+ //
+ // Write GDT register
+ //
+ //gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt;
+ gdtPtr.Base = (UINTN)(VOID*) gdt;
+ gdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);
+ AsmWriteGdtr (&gdtPtr);
+
+ //
+ // Update selector (segment) registers base on new GDT
+ //
+ SetCodeSelector ((UINT16)CPU_CODE_SEL);
+ SetDataSelectors ((UINT16)CPU_DATA_SEL);
+}
+
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S b/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S
new file mode 100755
index 0000000000..3b43b6fd8b
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S
@@ -0,0 +1,365 @@
+#------------------------------------------------------------------------------
+#*
+#* Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+#* 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.
+#*
+#* CpuAsm.S
+#*
+#* Abstract:
+#*
+#------------------------------------------------------------------------------
+
+
+#.MMX
+#.XMM
+
+#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
+
+
+#
+# point to the external interrupt vector table
+#
+ExternalVectorTablePtr:
+ .byte 0, 0, 0, 0
+
+ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr)
+ASM_PFX(InitializeExternalVectorTablePtr):
+ movl 4(%esp), %eax
+ movl %eax, ExternalVectorTablePtr
+ ret
+
+#------------------------------------------------------------------------------
+# VOID
+# SetCodeSelector (
+# UINT16 Selector
+# );
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(SetCodeSelector)
+ASM_PFX(SetCodeSelector):
+ movl 4(%esp), %ecx
+ subl $0x10, %esp
+ leal setCodeSelectorLongJump, %eax
+ movl %eax, (%esp)
+ movw %cx, 4(%esp)
+ .byte 0xFF, 0x2C, 0x24 # jmp *(%esp) note:(FWORD jmp)
+setCodeSelectorLongJump:
+ addl $0x10, %esp
+ ret
+
+#------------------------------------------------------------------------------
+# VOID
+# SetDataSelectors (
+# UINT16 Selector
+# );
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(SetDataSelectors)
+ASM_PFX(SetDataSelectors):
+ movl 4(%esp), %ecx
+ movw %cx, %ss
+ movw %cx, %ds
+ movw %cx, %es
+ movw %cx, %fs
+ movw %cx, %gs
+ ret
+
+#---------------------------------------;
+# CommonInterruptEntry ;
+#---------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
+ASM_PFX(CommonInterruptEntry):
+ cli
+ #
+ # All interrupt handlers are invoked through interrupt gates, so
+ # IF flag automatically cleared at the entry point
+ #
+
+ #
+ # Calculate vector number
+ #
+ # Get the return address of call, actually, it is the
+ # address of vector number.
+ #
+ xchgl (%esp), %ecx
+ movw (%ecx), %cx
+ andl $0x0FFFF, %ecx
+ cmpl $32, %ecx # Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt %ecx, ASM_PFX(mErrorCodeFlag)
+ jc HasErrorCode
+
+NoErrorCode:
+
+ #
+ # Stack:
+ # +---------------------+
+ # + EFlags +
+ # +---------------------+
+ # + CS +
+ # +---------------------+
+ # + EIP +
+ # +---------------------+
+ # + ECX +
+ # +---------------------+ <-- ESP
+ #
+ # Registers:
+ # ECX - Vector Number
+ #
+
+ #
+ # Put Vector Number on stack
+ #
+ pushl %ecx
+
+ #
+ # Put 0 (dummy) error code on stack, and restore ECX
+ #
+ xorl %ecx, %ecx # ECX = 0
+ xchgl 4(%esp), %ecx
+
+ jmp ErrorCodeAndVectorOnStack
+
+HasErrorCode:
+
+ #
+ # Stack:
+ # +---------------------+
+ # + EFlags +
+ # +---------------------+
+ # + CS +
+ # +---------------------+
+ # + EIP +
+ # +---------------------+
+ # + Error Code +
+ # +---------------------+
+ # + ECX +
+ # +---------------------+ <-- ESP
+ #
+ # Registers:
+ # ECX - Vector Number
+ #
+
+ #
+ # Put Vector Number on stack and restore ECX
+ #
+ xchgl (%esp), %ecx
+
+ErrorCodeAndVectorOnStack:
+ pushl %ebp
+ movl %esp, %ebp
+
+ #
+ # Stack:
+ # +---------------------+
+ # + EFlags +
+ # +---------------------+
+ # + CS +
+ # +---------------------+
+ # + EIP +
+ # +---------------------+
+ # + Error Code +
+ # +---------------------+
+ # + Vector Number +
+ # +---------------------+
+ # + EBP +
+ # +---------------------+ <-- EBP
+ #
+
+ #
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ # is 16-byte aligned
+ #
+ andl $0x0fffffff0, %esp
+ subl $12, %esp
+
+#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushl %ebx
+ leal 24(%ebp), %ecx
+ pushl %ecx # ESP
+ pushl (%ebp) # EBP
+ pushl %esi
+ pushl %edi
+
+#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ movl %ss, %eax
+ pushl %eax
+ movzwl 16(%ebp), %eax
+ pushl %eax
+ movl %ds, %eax
+ pushl %eax
+ movl %es, %eax
+ pushl %eax
+ movl %fs, %eax
+ pushl %eax
+ movl %gs, %eax
+ pushl %eax
+
+#; UINT32 Eip;
+ movl 12(%ebp), %eax
+ pushl %eax
+
+#; UINT32 Gdtr[2], Idtr[2];
+ subl $8, %esp
+ sidt (%esp)
+ movl 2(%esp), %eax
+ xchgl (%esp), %eax
+ andl $0x0FFFF, %eax
+ movl %eax, 4(%esp)
+
+ subl $8, %esp
+ sgdt (%esp)
+ movl 2(%esp), %eax
+ xchgl (%esp), %eax
+ andl $0x0FFFF, %eax
+ movl %eax, 4(%esp)
+
+#; UINT32 Ldtr, Tr;
+ xorl %eax, %eax
+ str %ax
+ pushl %eax
+ sldt %ax
+ pushl %eax
+
+#; UINT32 EFlags;
+ movl 20(%ebp), %eax
+ pushl %eax
+
+#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ movl %cr4, %eax
+ orl $0x208, %eax
+ movl %eax, %cr4
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ xorl %eax, %eax
+ pushl %eax
+ movl %cr0, %eax
+ pushl %eax
+
+#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movl %dr7, %eax
+ pushl %eax
+ movl %dr6, %eax
+ pushl %eax
+ movl %dr3, %eax
+ pushl %eax
+ movl %dr2, %eax
+ pushl %eax
+ movl %dr1, %eax
+ pushl %eax
+ movl %dr0, %eax
+ pushl %eax
+
+#; FX_SAVE_STATE_IA32 FxSaveState;
+ subl $512, %esp
+ movl %esp, %edi
+ .byte 0x0f, 0x0ae, 0x07 #fxsave [edi]
+
+#; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+#; UINT32 ExceptionData;
+ pushl 8(%ebp)
+
+#; call into exception handler
+ movl ExternalVectorTablePtr, %eax # get the interrupt vectors base
+ orl %eax, %eax # NULL?
+ jz nullExternalExceptionHandler
+
+ mov 4(%ebp), %ecx
+ movl (%eax,%ecx,4), %eax
+ orl %eax, %eax # NULL?
+ jz nullExternalExceptionHandler
+
+#; Prepare parameter and call
+ movl %esp, %edx
+ pushl %edx
+ movl 4(%ebp), %edx
+ pushl %edx
+
+ #
+ # Call External Exception Handler
+ #
+ call *%eax
+ addl $8, %esp
+
+nullExternalExceptionHandler:
+
+ cli
+#; UINT32 ExceptionData;
+ addl $4, %esp
+
+#; FX_SAVE_STATE_IA32 FxSaveState;
+ movl %esp, %esi
+ .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi]
+ addl $512, %esp
+
+#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+#; Skip restoration of DRx registers to support in-circuit emualators
+#; or debuggers set breakpoint in interrupt/exception context
+ addl $24, %esp
+
+#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ popl %eax
+ movl %eax, %cr0
+ addl $4, %esp # not for Cr1
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, %cr3
+ popl %eax
+ movl %eax, %cr4
+
+#; UINT32 EFlags;
+ popl 20(%ebp)
+
+#; UINT32 Ldtr, Tr;
+#; UINT32 Gdtr[2], Idtr[2];
+#; Best not let anyone mess with these particular registers...
+ addl $24, %esp
+
+#; UINT32 Eip;
+ popl 12(%ebp)
+
+#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+#; NOTE - modified segment registers could hang the debugger... We
+#; could attempt to insulate ourselves against this possibility,
+#; but that poses risks as well.
+#;
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popl 16(%ebp)
+ popl %ss
+
+#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ popl %edi
+ popl %esi
+ addl $4, %esp # not for ebp
+ addl $4, %esp # not for esp
+ popl %ebx
+ popl %edx
+ popl %ecx
+ popl %eax
+
+ movl %ebp, %esp
+ popl %ebp
+ addl $8, %esp
+ iretl
+
+
+#END
+
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm b/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm
new file mode 100755
index 0000000000..0924dc5bb3
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm
@@ -0,0 +1,363 @@
+ TITLE CpuAsm.asm:
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+;* 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.
+;*
+;* CpuAsm.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .686
+ .model flat,C
+ .code
+
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+
+;
+; point to the external interrupt vector table
+;
+ExternalVectorTablePtr DWORD 0
+
+InitializeExternalVectorTablePtr PROC PUBLIC
+ mov eax, [esp+4]
+ mov ExternalVectorTablePtr, eax
+ ret
+InitializeExternalVectorTablePtr ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; SetCodeSelector (
+; UINT16 Selector
+; );
+;------------------------------------------------------------------------------
+SetCodeSelector PROC PUBLIC
+ mov ecx, [esp+4]
+ sub esp, 0x10
+ lea eax, setCodeSelectorLongJump
+ mov [esp], eax
+ mov [esp+4], cx
+ jmp fword ptr [esp]
+setCodeSelectorLongJump:
+ add esp, 0x10
+ ret
+SetCodeSelector ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; SetDataSelectors (
+; UINT16 Selector
+; );
+;------------------------------------------------------------------------------
+SetDataSelectors PROC PUBLIC
+ mov ecx, [esp+4]
+ mov ss, cx
+ mov ds, cx
+ mov es, cx
+ mov fs, cx
+ mov gs, cx
+ ret
+SetDataSelectors ENDP
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+
+CommonInterruptEntry PROC PUBLIC
+ cli
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+
+ ;
+ ; Calculate vector number
+ ;
+ ; Get the return address of call, actually, it is the
+ ; address of vector number.
+ ;
+ xchg ecx, [esp]
+ mov cx, [ecx]
+ and ecx, 0FFFFh
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt mErrorCodeFlag, ecx
+ jc HasErrorCode
+
+NoErrorCode:
+
+ ;
+ ; Stack:
+ ; +---------------------+
+ ; + EFlags +
+ ; +---------------------+
+ ; + CS +
+ ; +---------------------+
+ ; + EIP +
+ ; +---------------------+
+ ; + ECX +
+ ; +---------------------+ <-- ESP
+ ;
+ ; Registers:
+ ; ECX - Vector Number
+ ;
+
+ ;
+ ; Put Vector Number on stack
+ ;
+ push ecx
+
+ ;
+ ; Put 0 (dummy) error code on stack, and restore ECX
+ ;
+ xor ecx, ecx ; ECX = 0
+ xchg ecx, [esp+4]
+
+ jmp ErrorCodeAndVectorOnStack
+
+HasErrorCode:
+
+ ;
+ ; Stack:
+ ; +---------------------+
+ ; + EFlags +
+ ; +---------------------+
+ ; + CS +
+ ; +---------------------+
+ ; + EIP +
+ ; +---------------------+
+ ; + Error Code +
+ ; +---------------------+
+ ; + ECX +
+ ; +---------------------+ <-- ESP
+ ;
+ ; Registers:
+ ; ECX - Vector Number
+ ;
+
+ ;
+ ; Put Vector Number on stack and restore ECX
+ ;
+ xchg ecx, [esp]
+
+ErrorCodeAndVectorOnStack:
+ push ebp
+ mov ebp, esp
+
+ ;
+ ; Stack:
+ ; +---------------------+
+ ; + EFlags +
+ ; +---------------------+
+ ; + CS +
+ ; +---------------------+
+ ; + EIP +
+ ; +---------------------+
+ ; + Error Code +
+ ; +---------------------+
+ ; + Vector Number +
+ ; +---------------------+
+ ; + EBP +
+ ; +---------------------+ <-- EBP
+ ;
+
+ ;
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ ; is 16-byte aligned
+ ;
+ and esp, 0fffffff0h
+ sub esp, 12
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ push eax
+ push ecx
+ push edx
+ push ebx
+ lea ecx, [ebp + 6 * 4]
+ push ecx ; ESP
+ push dword ptr [ebp] ; EBP
+ push esi
+ push edi
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ mov eax, ss
+ push eax
+ movzx eax, word ptr [ebp + 4 * 4]
+ push eax
+ mov eax, ds
+ push eax
+ mov eax, es
+ push eax
+ mov eax, fs
+ push eax
+ mov eax, gs
+ push eax
+
+;; UINT32 Eip;
+ mov eax, [ebp + 3 * 4]
+ push eax
+
+;; UINT32 Gdtr[2], Idtr[2];
+ sub esp, 8
+ sidt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ mov [esp+4], eax
+
+ sub esp, 8
+ sgdt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ mov [esp+4], eax
+
+;; UINT32 Ldtr, Tr;
+ xor eax, eax
+ str ax
+ push eax
+ sldt ax
+ push eax
+
+;; UINT32 EFlags;
+ mov eax, [ebp + 5 * 4]
+ push eax
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ mov eax, cr4
+ or eax, 208h
+ mov cr4, eax
+ push eax
+ mov eax, cr3
+ push eax
+ mov eax, cr2
+ push eax
+ xor eax, eax
+ push eax
+ mov eax, cr0
+ push eax
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov eax, dr7
+ push eax
+ mov eax, dr6
+ push eax
+ mov eax, dr3
+ push eax
+ mov eax, dr2
+ push eax
+ mov eax, dr1
+ push eax
+ mov eax, dr0
+ push eax
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ sub esp, 512
+ mov edi, esp
+ db 0fh, 0aeh, 07h ;fxsave [edi]
+
+;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push dword ptr [ebp + 2 * 4]
+
+;; call into exception handler
+ mov eax, ExternalVectorTablePtr ; get the interrupt vectors base
+ or eax, eax ; NULL?
+ jz nullExternalExceptionHandler
+
+ mov ecx, [ebp + 4]
+ mov eax, [eax + ecx * 4]
+ or eax, eax ; NULL?
+ jz nullExternalExceptionHandler
+
+;; Prepare parameter and call
+ mov edx, esp
+ push edx
+ mov edx, dword ptr [ebp + 1 * 4]
+ push edx
+
+ ;
+ ; Call External Exception Handler
+ ;
+ call eax
+ add esp, 8
+
+nullExternalExceptionHandler:
+
+ cli
+;; UINT32 ExceptionData;
+ add esp, 4
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ mov esi, esp
+ db 0fh, 0aeh, 0eh ; fxrstor [esi]
+ add esp, 512
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add esp, 4 * 6
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop eax
+ mov cr0, eax
+ add esp, 4 ; not for Cr1
+ pop eax
+ mov cr2, eax
+ pop eax
+ mov cr3, eax
+ pop eax
+ mov cr4, eax
+
+;; UINT32 EFlags;
+ pop dword ptr [ebp + 5 * 4]
+
+;; UINT32 Ldtr, Tr;
+;; UINT32 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add esp, 24
+
+;; UINT32 Eip;
+ pop dword ptr [ebp + 3 * 4]
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+;; NOTE - modified segment registers could hang the debugger... We
+;; could attempt to insulate ourselves against this possibility,
+;; but that poses risks as well.
+;;
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ pop dword ptr [ebp + 4 * 4]
+ pop ss
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pop edi
+ pop esi
+ add esp, 4 ; not for ebp
+ add esp, 4 ; not for esp
+ pop ebx
+ pop edx
+ pop ecx
+ pop eax
+
+ mov esp, ebp
+ pop ebp
+ add esp, 8
+ iretd
+
+CommonInterruptEntry ENDP
+
+END
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S b/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S
new file mode 100755
index 0000000000..c38461dc9c
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S
@@ -0,0 +1,818 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# 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.
+#
+# Module Name:
+#
+# IvtAsm.S
+#
+# Abstract:
+#
+# Interrupt Vector Table
+#
+#------------------------------------------------------------------------------
+
+#
+# Interrupt Vector Table
+#
+
+
+ASM_GLOBAL ASM_PFX(AsmIdtVector00)
+.p2align 3
+ASM_PFX(AsmIdtVector00):
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x00
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x01
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x02
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x03
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x04
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x05
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x06
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x07
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x08
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x09
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x0a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x0b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x0c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x0d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x0e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x0f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x10
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x11
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x12
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x13
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x14
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x15
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x16
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x17
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x18
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x19
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x1a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x1b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x1c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x1d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x1e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x1f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x00
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x21
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x22
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x23
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x24
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x25
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x26
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x27
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x28
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x29
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x2a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x2b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x2c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x2d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x2e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x2f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x30
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x31
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x32
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x33
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x34
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x35
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x36
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x37
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x38
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x39
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x3a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x3b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x3c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x3d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x3e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x3f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x40
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x41
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x42
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x43
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x44
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x45
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x46
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x47
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x48
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x49
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x4a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x4b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x4c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x4d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x4e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x4f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x50
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x51
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x52
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x53
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x54
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x55
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x56
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x57
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x58
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x59
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x5a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x5b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x5c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x5d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x5e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x5f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x60
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x61
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x62
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x63
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x64
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x65
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x66
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x67
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x68
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x69
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x6a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x6b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x6c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x6d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x6e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x6f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x70
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x71
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x72
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x73
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x74
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x75
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x76
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x77
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x78
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x79
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x7a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x7b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x7c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x7d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x7e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x7f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x80
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x81
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x82
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x83
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x84
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x85
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x86
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x87
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x88
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x89
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x8a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x8b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x8c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x8d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x8e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x8f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x90
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x91
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x92
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x93
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x94
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x95
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x96
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x97
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x98
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x99
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x9a
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x9b
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x9c
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x9d
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x9e
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0x9f
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa0
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa1
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa2
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa3
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa4
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa5
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa6
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa7
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa8
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xa9
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xaa
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xab
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xac
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xad
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xae
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xaf
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb0
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb1
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb2
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb3
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb4
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb5
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb6
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb7
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb8
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xb9
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xba
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xbb
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xbc
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xbd
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xbe
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xbf
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc0
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc1
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc2
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc3
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc4
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc5
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc6
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc7
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc8
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xc9
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xca
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xcb
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xcc
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xcd
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xce
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xcf
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd0
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd1
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd2
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd3
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd4
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd5
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd6
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd7
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd8
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xd9
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xda
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xdb
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xdc
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xdd
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xde
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xdf
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe0
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe1
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe2
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe3
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe4
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe5
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe6
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe7
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe8
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xe9
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xea
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xeb
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xec
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xed
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xee
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xef
+ nop
+
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf0
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf1
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf2
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf3
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf4
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf5
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf6
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf7
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf8
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xf9
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xfa
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xfb
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xfc
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xfd
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xfe
+ nop
+ call ASM_PFX(CommonInterruptEntry)
+ .short 0xff
+ nop
+
+ASM_GLOBAL ASM_PFX(AsmCommonIdtEnd)
+ASM_PFX(AsmCommonIdtEnd):
+ .byte 0
+
+
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm b/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm
new file mode 100755
index 0000000000..02003c9fa5
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm
@@ -0,0 +1,51 @@
+ TITLE IvtAsm.asm:
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.
+;* 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.
+;*
+;* IvtAsm.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+#include
+
+#ifdef MDE_CPU_IA32
+ .686
+ .model flat,C
+#endif
+ .code
+
+;------------------------------------------------------------------------------
+; Generic IDT Vector Handlers for the Host. They are all the same so they
+; will compress really well.
+;
+; By knowing the return address for Vector 00 you can can calculate the
+; vector number by looking at the call CommonInterruptEntry return address.
+; (return address - (AsmIdtVector00 + 5))/8 == IDT index
+;
+;------------------------------------------------------------------------------
+
+EXTRN CommonInterruptEntry:PROC
+
+ALIGN 8
+
+PUBLIC AsmIdtVector00
+
+AsmIdtVector00 LABEL BYTE
+REPEAT 256
+ call CommonInterruptEntry
+ dw ($ - AsmIdtVector00 - 5) / 8 ; vector number
+ nop
+ENDM
+
+END
+
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/X64/CpuAsm.S b/CloverEFI/UefiCpuPkg/CpuDxe/X64/CpuAsm.S
new file mode 100755
index 0000000000..3ea54090eb
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/X64/CpuAsm.S
@@ -0,0 +1,346 @@
+# TITLE CpuAsm.S:
+
+#------------------------------------------------------------------------------
+#*
+#* Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+#* 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.
+#*
+#* CpuAsm.S
+#*
+#* Abstract:
+#*
+#------------------------------------------------------------------------------
+
+
+#text SEGMENT
+
+
+#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
+
+
+#
+# point to the external interrupt vector table
+#
+ExternalVectorTablePtr:
+ .byte 0, 0, 0, 0, 0, 0, 0, 0
+
+ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr)
+ASM_PFX(InitializeExternalVectorTablePtr):
+ leaq ExternalVectorTablePtr(%rip), %rax # save vector number
+ movq %rcx, (%rax)
+ ret
+
+
+#------------------------------------------------------------------------------
+# VOID
+# SetCodeSelector (
+# UINT16 Selector
+# );
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(SetCodeSelector)
+ASM_PFX(SetCodeSelector):
+ subq $0x14, %rsp
+ leaq L_setCodeSelectorLongJump(%rip), %rax
+ movq %rax, (%rsp)
+ movw %cx, 4(%rsp)
+ .byte 0x48, 0xFF, 0x2C, 0x24 # jmp (%rsp) note:fword jmp
+L_setCodeSelectorLongJump:
+ addq $0x14, %rsp
+ ret
+
+#------------------------------------------------------------------------------
+# VOID
+# SetDataSelectors (
+# UINT16 Selector
+# );
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(SetDataSelectors)
+ASM_PFX(SetDataSelectors):
+ movw %cx, %ss
+ movw %cx, %ds
+ movw %cx, %es
+ movw %cx, %fs
+ movw %cx, %gs
+ ret
+
+#---------------------------------------;
+# CommonInterruptEntry ;
+#---------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
+ASM_PFX(CommonInterruptEntry):
+ cli
+ #
+ # All interrupt handlers are invoked through interrupt gates, so
+ # IF flag automatically cleared at the entry point
+ #
+ #
+ # Calculate vector number
+ #
+ xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number.
+ movzwl (%rcx), %ecx
+ cmp $32, %ecx # Intel reserved vector for exceptions?
+ jae NoErrorCode
+ pushq %rax
+ leaq ASM_PFX(mErrorCodeFlag)(%rip), %rax
+ bt %ecx, (%rax)
+ popq %rax
+ jc CommonInterruptEntry_al_0000
+
+NoErrorCode:
+
+ #
+ # Push a dummy error code on the stack
+ # to maintain coherent stack map
+ #
+ pushq (%rsp)
+ movq $0, 8(%rsp)
+CommonInterruptEntry_al_0000:
+ pushq %rbp
+ movq %rsp, %rbp
+
+ #
+ # Stack:
+ # +---------------------+ <-- 16-byte aligned ensured by processor
+ # + Old SS +
+ # +---------------------+
+ # + Old RSP +
+ # +---------------------+
+ # + RFlags +
+ # +---------------------+
+ # + CS +
+ # +---------------------+
+ # + RIP +
+ # +---------------------+
+ # + Error Code +
+ # +---------------------+
+ # + RCX / Vector Number +
+ # +---------------------+
+ # + RBP +
+ # +---------------------+ <-- RBP, 16-byte aligned
+ #
+
+
+ #
+ # Since here the stack pointer is 16-byte aligned, so
+ # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+ # is 16-byte aligned
+ #
+
+#; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+#; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %r11
+ pushq %r10
+ pushq %r9
+ pushq %r8
+ pushq %rax
+ pushq 8(%rbp) # RCX
+ pushq %rdx
+ pushq %rbx
+ pushq 48(%rbp) # RSP
+ pushq (%rbp) # RBP
+ pushq %rsi
+ pushq %rdi
+
+#; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzwq 56(%rbp), %rax
+ pushq %rax # for ss
+ movzwq 32(%rbp), %rax
+ pushq %rax # for cs
+ movl %ds, %eax
+ pushq %rax
+ movl %es, %eax
+ pushq %rax
+ movl %fs, %eax
+ pushq %rax
+ movl %gs, %eax
+ pushq %rax
+
+ movq %rcx, 8(%rbp) # save vector number
+
+#; UINT64 Rip;
+ pushq 24(%rbp)
+
+#; UINT64 Gdtr[2], Idtr[2];
+ xorq %rax, %rax
+ pushq %rax
+ pushq %rax
+ sidt (%rsp)
+ xchgq 2(%rsp), %rax
+ xchgq (%rsp), %rax
+ xchgq 8(%rsp), %rax
+
+ xorq %rax, %rax
+ pushq %rax
+ pushq %rax
+ sgdt (%rsp)
+ xchgq 2(%rsp), %rax
+ xchgq (%rsp), %rax
+ xchgq 8(%rsp), %rax
+
+#; UINT64 Ldtr, Tr;
+ xorq %rax, %rax
+ str %ax
+ pushq %rax
+ sldt %ax
+ pushq %rax
+
+#; UINT64 RFlags;
+ pushq 40(%rbp)
+
+#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ movq %cr8, %rax
+ pushq %rax
+ movq %cr4, %rax
+ orq $0x208, %rax
+ movq %rax, %cr4
+ pushq %rax
+ mov %cr3, %rax
+ pushq %rax
+ mov %cr2, %rax
+ pushq %rax
+ xorq %rax, %rax
+ pushq %rax
+ mov %cr0, %rax
+ pushq %rax
+
+#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movq %dr7, %rax
+ pushq %rax
+ movq %dr6, %rax
+ pushq %rax
+ movq %dr3, %rax
+ pushq %rax
+ movq %dr2, %rax
+ pushq %rax
+ movq %dr1, %rax
+ pushq %rax
+ movq %dr0, %rax
+ pushq %rax
+
+#; FX_SAVE_STATE_X64 FxSaveState;
+ subq $512, %rsp
+ movq %rsp, %rdi
+ .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi]
+
+#; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
+ cld
+
+#; UINT32 ExceptionData;
+ pushq 16(%rbp)
+
+#; call into exception handler
+ movq 8(%rbp), %rcx
+ leaq ExternalVectorTablePtr(%rip), %rax
+# movl (%eax), %eax
+ movq (%rax), %rax
+ movq (%rax,%rcx,8), %rax
+ orq %rax, %rax # NULL?
+
+ je nonNullValue#
+
+#; Prepare parameter and call
+# mov rcx, [rbp + 8]
+ mov %rsp, %rdx
+ #
+ # Per X64 calling convention, allocate maximum parameter stack space
+ # and make sure RSP is 16-byte aligned
+ #
+ subq $40, %rsp
+ call *%rax
+ addq $40, %rsp
+
+nonNullValue:
+ cli
+#; UINT64 ExceptionData;
+ addq $8, %rsp
+
+#; FX_SAVE_STATE_X64 FxSaveState;
+
+ movq %rsp, %rsi
+ .byte 0x0f, 0x0ae, 0x0E # fxrstor [rsi]
+ addq $512, %rsp
+
+#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+#; Skip restoration of DRx registers to support in-circuit emualators
+#; or debuggers set breakpoint in interrupt/exception context
+ addq $48, %rsp
+
+#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ popq %rax
+ movq %rax, %cr0
+ addq $8, %rsp # not for Cr1
+ popq %rax
+ movq %rax, %cr2
+ popq %rax
+ movq %rax, %cr3
+ popq %rax
+ movq %rax, %cr4
+ popq %rax
+ movq %rax, %cr8
+
+#; UINT64 RFlags;
+ popq 40(%rbp)
+
+#; UINT64 Ldtr, Tr;
+#; UINT64 Gdtr[2], Idtr[2];
+#; Best not let anyone mess with these particular registers...
+ addq $48, %rsp
+
+#; UINT64 Rip;
+ popq 24(%rbp)
+
+#; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ popq %rax
+ # mov %rax, %gs ; not for gs
+ popq %rax
+ # mov %rax, %fs ; not for fs
+ # (X64 will not use fs and gs, so we do not restore it)
+ popq %rax
+ movl %eax, %es
+ popq %rax
+ movl %eax, %ds
+ popq 32(%rbp) # for cs
+ popq 56(%rbp) # for ss
+
+#; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+#; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ popq %rdi
+ popq %rsi
+ addq $8, %rsp # not for rbp
+ popq 48(%rbp) # for rsp
+ popq %rbx
+ popq %rdx
+ popq %rcx
+ popq %rax
+ popq %r8
+ popq %r9
+ popq %r10
+ popq %r11
+ popq %r12
+ popq %r13
+ popq %r14
+ popq %r15
+
+ movq %rbp, %rsp
+ popq %rbp
+ addq $16, %rsp
+ iretq
+
+
+#text ENDS
+
+#END
+
+
diff --git a/CloverEFI/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm b/CloverEFI/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm
new file mode 100755
index 0000000000..56955d37d5
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm
@@ -0,0 +1,337 @@
+ TITLE CpuAsm.asm:
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+;* 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.
+;*
+;* CpuAsm.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+.code
+
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+
+;
+; point to the external interrupt vector table
+;
+ExternalVectorTablePtr QWORD 0
+
+InitializeExternalVectorTablePtr PROC PUBLIC
+ mov ExternalVectorTablePtr, rcx
+ ret
+InitializeExternalVectorTablePtr ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; SetCodeSelector (
+; UINT16 Selector
+; );
+;------------------------------------------------------------------------------
+SetCodeSelector PROC PUBLIC
+ sub rsp, 0x14
+ lea rax, setCodeSelectorLongJump
+ mov [rsp], rax
+ mov [rsp+8], cx
+;* I'm not sure how to encode this. We need to jmp [esp], where in esp there is
+;* w16(selector):q64(address).
+;* in gcc version this is encoded as 48 ff 2c 24 [ rex.W ljmpq (%esp) ]
+;* but in VC jmp qword ptr [rsp] generates code ff 24 24 [ jmpq(%esp) ]
+;* so I've just inserted db 0x48 to emit REX.W and get original 48 ff 2c 24
+ db 0x48
+ jmp fword ptr [rsp]
+setCodeSelectorLongJump:
+ add rsp, 0x14
+ ret
+SetCodeSelector ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; SetDataSelectors (
+; UINT16 Selector
+; );
+;------------------------------------------------------------------------------
+SetDataSelectors PROC PUBLIC
+ mov ss, cx
+ mov ds, cx
+ mov es, cx
+ mov fs, cx
+ mov gs, cx
+ ret
+SetDataSelectors ENDP
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+
+CommonInterruptEntry PROC PUBLIC
+ cli
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+ ;
+ ; Calculate vector number
+ ;
+ xchg rcx, [rsp] ; get the return address of call, actually, it is the address of vector number.
+ movzx ecx, word ptr [rcx]
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt mErrorCodeFlag, ecx
+ jc @F
+
+NoErrorCode:
+
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push [rsp]
+ mov qword ptr [rsp + 8], 0
+@@:
+ push rbp
+ mov rbp, rsp
+
+ ;
+ ; Stack:
+ ; +---------------------+ <-- 16-byte aligned ensured by processor
+ ; + Old SS +
+ ; +---------------------+
+ ; + Old RSP +
+ ; +---------------------+
+ ; + RFlags +
+ ; +---------------------+
+ ; + CS +
+ ; +---------------------+
+ ; + RIP +
+ ; +---------------------+
+ ; + Error Code +
+ ; +---------------------+
+ ; + RCX / Vector Number +
+ ; +---------------------+
+ ; + RBP +
+ ; +---------------------+ <-- RBP, 16-byte aligned
+ ;
+
+
+ ;
+ ; Since here the stack pointer is 16-byte aligned, so
+ ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+ ; is 16-byte aligned
+ ;
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ push r15
+ push r14
+ push r13
+ push r12
+ push r11
+ push r10
+ push r9
+ push r8
+ push rax
+ push qword ptr [rbp + 8] ; RCX
+ push rdx
+ push rbx
+ push qword ptr [rbp + 48] ; RSP
+ push qword ptr [rbp] ; RBP
+ push rsi
+ push rdi
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzx rax, word ptr [rbp + 56]
+ push rax ; for ss
+ movzx rax, word ptr [rbp + 32]
+ push rax ; for cs
+ mov rax, ds
+ push rax
+ mov rax, es
+ push rax
+ mov rax, fs
+ push rax
+ mov rax, gs
+ push rax
+
+ mov [rbp + 8], rcx ; save vector number
+
+;; UINT64 Rip;
+ push qword ptr [rbp + 24]
+
+;; UINT64 Gdtr[2], Idtr[2];
+ xor rax, rax
+ push rax
+ push rax
+ sidt [rsp]
+ xchg rax, [rsp + 2]
+ xchg rax, [rsp]
+ xchg rax, [rsp + 8]
+
+ xor rax, rax
+ push rax
+ push rax
+ sgdt [rsp]
+ xchg rax, [rsp + 2]
+ xchg rax, [rsp]
+ xchg rax, [rsp + 8]
+
+;; UINT64 Ldtr, Tr;
+ xor rax, rax
+ str ax
+ push rax
+ sldt ax
+ push rax
+
+;; UINT64 RFlags;
+ push qword ptr [rbp + 40]
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ mov rax, cr8
+ push rax
+ mov rax, cr4
+ or rax, 208h
+ mov cr4, rax
+ push rax
+ mov rax, cr3
+ push rax
+ mov rax, cr2
+ push rax
+ xor rax, rax
+ push rax
+ mov rax, cr0
+ push rax
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov rax, dr7
+ push rax
+ mov rax, dr6
+ push rax
+ mov rax, dr3
+ push rax
+ mov rax, dr2
+ push rax
+ mov rax, dr1
+ push rax
+ mov rax, dr0
+ push rax
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+ sub rsp, 512
+ mov rdi, rsp
+ db 0fh, 0aeh, 07h ;fxsave [rdi]
+
+;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push qword ptr [rbp + 16]
+
+;; call into exception handler
+ mov rcx, [rbp + 8]
+ mov rax, ExternalVectorTablePtr ; get the interrupt vectors base
+ mov rax, [rax + rcx * 8]
+ or rax, rax ; NULL?
+
+ je nonNullValue;
+
+;; Prepare parameter and call
+; mov rcx, [rbp + 8]
+ mov rdx, rsp
+ ;
+ ; Per X64 calling convention, allocate maximum parameter stack space
+ ; and make sure RSP is 16-byte aligned
+ ;
+ sub rsp, 4 * 8 + 8
+ call rax
+ add rsp, 4 * 8 + 8
+
+nonNullValue:
+ cli
+;; UINT64 ExceptionData;
+ add rsp, 8
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ mov rsi, rsp
+ db 0fh, 0aeh, 0Eh ; fxrstor [rsi]
+ add rsp, 512
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add rsp, 8 * 6
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ pop rax
+ mov cr0, rax
+ add rsp, 8 ; not for Cr1
+ pop rax
+ mov cr2, rax
+ pop rax
+ mov cr3, rax
+ pop rax
+ mov cr4, rax
+ pop rax
+ mov cr8, rax
+
+;; UINT64 RFlags;
+ pop qword ptr [rbp + 40]
+
+;; UINT64 Ldtr, Tr;
+;; UINT64 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add rsp, 48
+
+;; UINT64 Rip;
+ pop qword ptr [rbp + 24]
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ pop rax
+ ; mov gs, rax ; not for gs
+ pop rax
+ ; mov fs, rax ; not for fs
+ ; (X64 will not use fs and gs, so we do not restore it)
+ pop rax
+ mov es, rax
+ pop rax
+ mov ds, rax
+ pop qword ptr [rbp + 32] ; for cs
+ pop qword ptr [rbp + 56] ; for ss
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ pop rdi
+ pop rsi
+ add rsp, 8 ; not for rbp
+ pop qword ptr [rbp + 48] ; for rsp
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rax
+ pop r8
+ pop r9
+ pop r10
+ pop r11
+ pop r12
+ pop r13
+ pop r14
+ pop r15
+
+ mov rsp, rbp
+ pop rbp
+ add rsp, 16
+ iretq
+
+CommonInterruptEntry ENDP
+
+END
+
diff --git a/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.c b/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.c
new file mode 100755
index 0000000000..f53606692b
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.c
@@ -0,0 +1,539 @@
+/** @file
+ Produces the CPU I/O 2 Protocol.
+
+Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
+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.
+
+**/
+
+#include "CpuIo2Dxe.h"
+
+//
+// Handle for the CPU I/O 2 Protocol
+//
+EFI_HANDLE mHandle = NULL;
+
+//
+// CPU I/O 2 Protocol instance
+//
+EFI_CPU_IO2_PROTOCOL mCpuIo2 = {
+ {
+ CpuMemoryServiceRead,
+ CpuMemoryServiceWrite
+ },
+ {
+ CpuIoServiceRead,
+ CpuIoServiceWrite
+ }
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mInStride[] = {
+ 1, // EfiCpuIoWidthUint8
+ 2, // EfiCpuIoWidthUint16
+ 4, // EfiCpuIoWidthUint32
+ 8, // EfiCpuIoWidthUint64
+ 0, // EfiCpuIoWidthFifoUint8
+ 0, // EfiCpuIoWidthFifoUint16
+ 0, // EfiCpuIoWidthFifoUint32
+ 0, // EfiCpuIoWidthFifoUint64
+ 1, // EfiCpuIoWidthFillUint8
+ 2, // EfiCpuIoWidthFillUint16
+ 4, // EfiCpuIoWidthFillUint32
+ 8 // EfiCpuIoWidthFillUint64
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mOutStride[] = {
+ 1, // EfiCpuIoWidthUint8
+ 2, // EfiCpuIoWidthUint16
+ 4, // EfiCpuIoWidthUint32
+ 8, // EfiCpuIoWidthUint64
+ 1, // EfiCpuIoWidthFifoUint8
+ 2, // EfiCpuIoWidthFifoUint16
+ 4, // EfiCpuIoWidthFifoUint32
+ 8, // EfiCpuIoWidthFifoUint64
+ 0, // EfiCpuIoWidthFillUint8
+ 0, // EfiCpuIoWidthFillUint16
+ 0, // EfiCpuIoWidthFillUint32
+ 0 // EfiCpuIoWidthFillUint64
+};
+
+/**
+ Check parameters to a CPU I/O 2 Protocol service request.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The parameters for this request pass the checks.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+CpuIoCheckParameter (
+ IN BOOLEAN MmioOperation,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ UINT64 MaxCount;
+ UINT64 Limit;
+
+ //
+ // Check to see if Buffer is NULL
+ //
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Width is in the valid range
+ //
+ if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For FIFO type, the target address won't increase during the access,
+ // so treat Count as 1
+ //
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ Count = 1;
+ }
+
+ //
+ // Check to see if Width is in the valid range for I/O Port operations
+ //
+ Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Address is aligned
+ //
+ if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check to see if any address associated with this transfer exceeds the maximum
+ // allowed address. The maximum address implied by the parameters passed in is
+ // Address + Size * Count. If the following condition is met, then the transfer
+ // is not supported.
+ //
+ // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
+ //
+ // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
+ // can also be the maximum integer value supported by the CPU, this range
+ // check must be adjusted to avoid all oveflow conditions.
+ //
+ // The following form of the range check is equivalent but assumes that
+ // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
+ //
+ Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
+ if (Count == 0) {
+ if (Address > Limit) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ MaxCount = RShiftU64 (Limit, Width);
+ if (MaxCount < (Count - 1)) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Check to see if Buffer is aligned
+/* // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.)
+ //
+ if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {
+ return EFI_UNSUPPORTED;
+ }*/
+ if (((UINTN)Buffer & (mInStride[Width] - 1)) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiCpuIoWidthUint8) {
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ } else if (OperationWidth == EfiCpuIoWidthUint64) {
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Writes memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiCpuIoWidthUint8) {
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ } else if (OperationWidth == EfiCpuIoWidthUint64) {
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiCpuIoWidthUint8) {
+ *Uint8Buffer = IoRead8 ((UINTN)Address);
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {
+ *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {
+ *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+
+ //
+ // Make sure the parameters are valid
+ //
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiCpuIoWidthUint8) {
+ IoWrite8 ((UINTN)Address, *Uint8Buffer);
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {
+ IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {
+ IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The user Entry Point for module CpuIo2Dxe. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIo2Initialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiCpuIo2ProtocolGuid, &mCpuIo2,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.h b/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.h
new file mode 100755
index 0000000000..7d00da16f4
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.h
@@ -0,0 +1,225 @@
+/** @file
+ Internal include file for the CPU I/O 2 Protocol.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+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 _CPU_IO2_DXE_H_
+#define _CPU_IO2_DXE_H_
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+
+#define MAX_IO_PORT_ADDRESS 0xFFFF
+
+/**
+ Reads memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Writes memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Reads I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+#endif
diff --git a/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf b/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
new file mode 100755
index 0000000000..3abf2677f7
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
@@ -0,0 +1,54 @@
+## @file
+# Produces the CPU I/O 2 Protocol.
+#
+# This DXE driver produces of the CPU I/O 2 Protocol, as introduced by PI 1.2.
+#
+# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuIo2Dxe
+ FILE_GUID = A19B1FE7-C1BC-49F8-875F-54A5D542443F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = CpuIo2Initialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CpuIo2Dxe.c
+ CpuIo2Dxe.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ BaseLib
+ DebugLib
+ IoLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiCpuIo2ProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
+
+[BuildOptions]
+ XCODE:*_*_*_CC_FLAGS = -Os -DMDEPKG_NDEBUG
+ GCC:*_*_*_CC_FLAGS = -O0 -DMDEPKG_NDEBUG
+ MSFT:*_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
diff --git a/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.c b/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.c
new file mode 100755
index 0000000000..1c172a096c
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.c
@@ -0,0 +1,413 @@
+/** @file
+ Produces the SMM CPU I/O Protocol.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+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.
+
+**/
+
+#include "CpuIo2Smm.h"
+
+//
+// Handle for the SMM CPU I/O Protocol
+//
+EFI_HANDLE mHandle = NULL;
+
+//
+// SMM CPU I/O Protocol instance
+//
+EFI_SMM_CPU_IO2_PROTOCOL mSmmCpuIo2 = {
+ {
+ CpuMemoryServiceRead,
+ CpuMemoryServiceWrite
+ },
+ {
+ CpuIoServiceRead,
+ CpuIoServiceWrite
+ }
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mStride[] = {
+ 1, // SMM_IO_UINT8
+ 2, // SMM_IO_UINT16
+ 4, // SMM_IO_UINT32
+ 8 // SMM_IO_UINT64
+};
+
+/**
+ Check parameters to a SMM CPU I/O Protocol service request.
+
+ @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+
+**/
+EFI_STATUS
+CpuIoCheckParameter (
+ IN BOOLEAN MmioOperation,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ UINT64 MaxCount;
+ UINT64 Limit;
+
+ //
+ // Check to see if Buffer is NULL
+ //
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Width is in the valid range
+ //
+ if (Width < 0 || Width > SMM_IO_UINT64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Width is in the valid range for I/O Port operations
+ //
+ if (!MmioOperation && (Width == SMM_IO_UINT64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if any address associated with this transfer exceeds the maximum
+ // allowed address. The maximum address implied by the parameters passed in is
+ // Address + Size * Count. If the following condition is met, then the transfer
+ // is not supported.
+ //
+ // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
+ //
+ // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
+ // can also be the maximum integer value supported by the CPU, this range
+ // check must be adjusted to avoid all overflow conditions.
+ //
+ // The following form of the range check is equivalent but assumes that
+ // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
+ //
+ Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
+ if (Count == 0) {
+ if (Address > Limit) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ MaxCount = RShiftU64 (Limit, Width);
+ if (MaxCount < (Count - 1)) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Check to see if Address is aligned
+ //
+ if ((Address & (UINT64)(mStride[Width] - 1)) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Stride;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ Stride = mStride[Width];
+ for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
+ if (Width == SMM_IO_UINT8) {
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT16) {
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT32) {
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT64) {
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Writes memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Stride;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ Stride = mStride[Width];
+ for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
+ if (Width == SMM_IO_UINT8) {
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ } else if (Width == SMM_IO_UINT16) {
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ } else if (Width == SMM_IO_UINT32) {
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ } else if (Width == SMM_IO_UINT64) {
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Stride;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ Stride = mStride[Width];
+ for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
+ if (Width == SMM_IO_UINT8) {
+ *Uint8Buffer = IoRead8 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT16) {
+ *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT32) {
+ *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Stride;
+ UINT8 *Uint8Buffer;
+
+ //
+ // Make sure the parameters are valid
+ //
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ Stride = mStride[Width];
+ for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
+ if (Width == SMM_IO_UINT8) {
+ IoWrite8 ((UINTN)Address, *Uint8Buffer);
+ } else if (Width == SMM_IO_UINT16) {
+ IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ } else if (Width == SMM_IO_UINT32) {
+ IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The module Entry Point SmmCpuIoProtocol driver
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuIo2Initialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Copy the SMM CPU I/O Protocol instance into the System Management System Table
+ //
+ CopyMem (&gSmst->SmmIo, &mSmmCpuIo2, sizeof (mSmmCpuIo2));
+
+ //
+ // Install the SMM CPU I/O Protocol into the SMM protocol database
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mHandle,
+ &gEfiSmmCpuIo2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mSmmCpuIo2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.h b/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.h
new file mode 100755
index 0000000000..5a092594d7
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.h
@@ -0,0 +1,162 @@
+/** @file
+ Internal include file for the SMM CPU I/O Protocol.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+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 _CPU_IO2_SMM_H_
+#define _CPU_IO2_SMM_H_
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define MAX_IO_PORT_ADDRESS 0xFFFF
+
+/**
+ Reads memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Writes memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Reads I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+#endif
diff --git a/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf b/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
new file mode 100755
index 0000000000..e77b61f655
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
@@ -0,0 +1,48 @@
+## @file
+# Module that produces the SMM CPU I/O 2 Protocol using the services of the I/O Library
+#
+# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuIo2Smm
+ FILE_GUID = A47EE2D8-F60E-42fd-8E58-7BD65EE4C29B
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SmmCpuIo2Initialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ CpuIo2Smm.c
+ CpuIo2Smm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ BaseLib
+ DebugLib
+ IoLib
+ SmmServicesTableLib
+ BaseMemoryLib
+
+[Protocols]
+ gEfiSmmCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Depex]
+ TRUE
diff --git a/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.c b/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.c
new file mode 100755
index 0000000000..8888000533
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.c
@@ -0,0 +1,864 @@
+/** @file
+ Produces the CPU I/O PPI.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+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.
+
+**/
+
+#include "CpuIoPei.h"
+
+//
+// Instance of CPU I/O PPI
+//
+EFI_PEI_CPU_IO_PPI gCpuIoPpi = {
+ {
+ CpuMemoryServiceRead,
+ CpuMemoryServiceWrite
+ },
+ {
+ CpuIoServiceRead,
+ CpuIoServiceWrite
+ },
+ CpuIoRead8,
+ CpuIoRead16,
+ CpuIoRead32,
+ CpuIoRead64,
+ CpuIoWrite8,
+ CpuIoWrite16,
+ CpuIoWrite32,
+ CpuIoWrite64,
+ CpuMemRead8,
+ CpuMemRead16,
+ CpuMemRead32,
+ CpuMemRead64,
+ CpuMemWrite8,
+ CpuMemWrite16,
+ CpuMemWrite32,
+ CpuMemWrite64
+};
+
+//
+// PPI Descriptor used to install the CPU I/O PPI
+//
+EFI_PEI_PPI_DESCRIPTOR gPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiCpuIoPpiInstalledGuid,
+ NULL
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mInStride[] = {
+ 1, // EfiPeiCpuIoWidthUint8
+ 2, // EfiPeiCpuIoWidthUint16
+ 4, // EfiPeiCpuIoWidthUint32
+ 8, // EfiPeiCpuIoWidthUint64
+ 0, // EfiPeiCpuIoWidthFifoUint8
+ 0, // EfiPeiCpuIoWidthFifoUint16
+ 0, // EfiPeiCpuIoWidthFifoUint32
+ 0, // EfiPeiCpuIoWidthFifoUint64
+ 1, // EfiPeiCpuIoWidthFillUint8
+ 2, // EfiPeiCpuIoWidthFillUint16
+ 4, // EfiPeiCpuIoWidthFillUint32
+ 8 // EfiPeiCpuIoWidthFillUint64
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mOutStride[] = {
+ 1, // EfiPeiCpuIoWidthUint8
+ 2, // EfiPeiCpuIoWidthUint16
+ 4, // EfiPeiCpuIoWidthUint32
+ 8, // EfiPeiCpuIoWidthUint64
+ 1, // EfiPeiCpuIoWidthFifoUint8
+ 2, // EfiPeiCpuIoWidthFifoUint16
+ 4, // EfiPeiCpuIoWidthFifoUint32
+ 8, // EfiPeiCpuIoWidthFifoUint64
+ 0, // EfiPeiCpuIoWidthFillUint8
+ 0, // EfiPeiCpuIoWidthFillUint16
+ 0, // EfiPeiCpuIoWidthFillUint32
+ 0 // EfiPeiCpuIoWidthFillUint64
+};
+
+/**
+ Check parameters to a CPU I/O PPI service request.
+
+ @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[in] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The parameters for this request pass the checks.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+CpuIoCheckParameter (
+ IN BOOLEAN MmioOperation,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ UINT64 MaxCount;
+ UINT64 Limit;
+
+ //
+ // Check to see if Buffer is NULL
+ //
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Width is in the valid range
+ //
+ if (Width < 0 || Width >= EfiPeiCpuIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For FIFO type, the target address won't increase during the access,
+ // so treat Count as 1
+ //
+ if (Width >= EfiPeiCpuIoWidthFifoUint8 && Width <= EfiPeiCpuIoWidthFifoUint64) {
+ Count = 1;
+ }
+
+ //
+ // Check to see if Width is in the valid range for I/O Port operations
+ //
+ Width = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
+ if (!MmioOperation && (Width == EfiPeiCpuIoWidthUint64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if any address associated with this transfer exceeds the maximum
+ // allowed address. The maximum address implied by the parameters passed in is
+ // Address + Size * Count. If the following condition is met, then the transfer
+ // is not supported.
+ //
+ // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
+ //
+ // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
+ // can also be the maximum integer value supported by the CPU, this range
+ // check must be adjusted to avoid all overflow conditions.
+ //
+ // The following form of the range check is equivalent but assumes that
+ // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
+ //
+ Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
+ if (Count == 0) {
+ if (Address > Limit) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ MaxCount = RShiftU64 (Limit, Width);
+ if (MaxCount < (Count - 1)) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads memory-mapped registers.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table
+ published by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[out] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
+ BOOLEAN Aligned;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
+ Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiPeiCpuIoWidthUint8) {
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
+ if (Aligned) {
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ } else {
+ WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
+ }
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
+ if (Aligned) {
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ } else {
+ WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
+ }
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
+ if (Aligned) {
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ } else {
+ WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Writes memory-mapped registers.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table
+ published by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[in] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
+ BOOLEAN Aligned;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
+ Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiPeiCpuIoWidthUint8) {
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
+ if (Aligned) {
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ } else {
+ MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
+ }
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
+ if (Aligned) {
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ } else {
+ MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
+ }
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
+ if (Aligned) {
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ } else {
+ MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer));
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads I/O registers.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table
+ published by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[out] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
+ BOOLEAN Aligned;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
+ Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiPeiCpuIoWidthUint8) {
+ *Uint8Buffer = IoRead8 ((UINTN)Address);
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
+ if (Aligned) {
+ *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
+ } else {
+ WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));
+ }
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
+ if (Aligned) {
+ *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
+ } else {
+ WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write I/O registers.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table
+ published by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[in] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
+ BOOLEAN Aligned;
+ UINT8 *Uint8Buffer;
+
+ //
+ // Make sure the parameters are valid
+ //
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
+ Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
+ for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiPeiCpuIoWidthUint8) {
+ IoWrite8 ((UINTN)Address, *Uint8Buffer);
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
+ if (Aligned) {
+ IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ } else {
+ IoWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
+ }
+ } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
+ if (Aligned) {
+ IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ } else {
+ IoWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 8-bit I/O read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return An 8-bit value returned from the I/O space.
+**/
+UINT8
+EFIAPI
+CpuIoRead8 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ )
+{
+ return IoRead8 ((UINTN)Address);
+}
+
+/**
+ 16-bit I/O read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 16-bit value returned from the I/O space.
+
+**/
+UINT16
+EFIAPI
+CpuIoRead16 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ )
+{
+ return IoRead16 ((UINTN)Address);
+}
+
+/**
+ 32-bit I/O read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 32-bit value returned from the I/O space.
+
+**/
+UINT32
+EFIAPI
+CpuIoRead32 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ )
+{
+ return IoRead32 ((UINTN)Address);
+}
+
+/**
+ 64-bit I/O read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 64-bit value returned from the I/O space.
+
+**/
+UINT64
+EFIAPI
+CpuIoRead64 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ )
+{
+ return IoRead64 ((UINTN)Address);
+}
+
+/**
+ 8-bit I/O write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuIoWrite8 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT8 Data
+ )
+{
+ IoWrite8 ((UINTN)Address, Data);
+}
+
+/**
+ 16-bit I/O write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuIoWrite16 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT16 Data
+ )
+{
+ IoWrite16 ((UINTN)Address, Data);
+}
+
+/**
+ 32-bit I/O write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuIoWrite32 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT32 Data
+ )
+{
+ IoWrite32 ((UINTN)Address, Data);
+}
+
+/**
+ 64-bit I/O write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuIoWrite64 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT64 Data
+ )
+{
+ IoWrite64 ((UINTN)Address, Data);
+}
+
+/**
+ 8-bit memory read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return An 8-bit value returned from the memory space.
+
+**/
+UINT8
+EFIAPI
+CpuMemRead8 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ )
+{
+ return MmioRead8 ((UINTN)Address);
+}
+
+/**
+ 16-bit memory read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 16-bit value returned from the memory space.
+
+**/
+UINT16
+EFIAPI
+CpuMemRead16 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ )
+{
+ return MmioRead16 ((UINTN)Address);
+}
+
+/**
+ 32-bit memory read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 32-bit value returned from the memory space.
+
+**/
+UINT32
+EFIAPI
+CpuMemRead32 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ )
+{
+ return MmioRead32 ((UINTN)Address);
+}
+
+/**
+ 64-bit memory read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 64-bit value returned from the memory space.
+
+**/
+UINT64
+EFIAPI
+CpuMemRead64 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ )
+{
+ return MmioRead64 ((UINTN)Address);
+}
+
+/**
+ 8-bit memory write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuMemWrite8 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT8 Data
+ )
+{
+ MmioWrite8 ((UINTN)Address, Data);
+}
+
+/**
+ 16-bit memory write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuMemWrite16 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT16 Data
+ )
+{
+ MmioWrite16 ((UINTN)Address, Data);
+}
+
+/**
+ 32-bit memory write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuMemWrite32 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT32 Data
+ )
+{
+ MmioWrite32 ((UINTN)Address, Data);
+}
+
+/**
+ 64-bit memory write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuMemWrite64 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT64 Data
+ )
+{
+ MmioWrite64 ((UINTN)Address, Data);
+}
+
+/**
+ The Entry point of the CPU I/O PEIM
+
+ This function is the Entry point of the CPU I/O PEIM which installs CpuIoPpi.
+
+ @param[in] FileHandle Pointer to image file handle.
+ @param[in] PeiServices Pointer to PEI Services Table
+
+ @retval EFI_SUCCESS CPU I/O PPI successfully installed
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoInitialize (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Register so it will be automatically shadowed to memory
+ //
+ Status = PeiServicesRegisterForShadow (FileHandle);
+
+ //
+ // Make CpuIo pointer in PeiService table point to gCpuIoPpi
+ //
+ (*((EFI_PEI_SERVICES **)PeiServices))->CpuIo = &gCpuIoPpi;
+
+ if (Status == EFI_ALREADY_STARTED) {
+ //
+ // Shadow completed and running from memory
+ //
+ // DEBUG ((EFI_D_INFO, "CpuIO PPI has been loaded into memory. Reinstalled PPI=0x%x\n", &gCpuIoPpi));
+ } else {
+ Status = PeiServicesInstallPpi (&gPpiList);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.h b/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.h
new file mode 100755
index 0000000000..052f0e3d0e
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.h
@@ -0,0 +1,448 @@
+/** @file
+ Internal include file for the CPU I/O PPI.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+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 _CPU_IO2_PEI_H_
+#define _CPU_IO2_PEI_H_
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+
+#define MAX_IO_PORT_ADDRESS 0xFFFF
+
+/**
+ Reads memory-mapped registers.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table
+ published by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[out] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Writes memory-mapped registers.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table
+ published by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[in] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Reads I/O registers.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table
+ published by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[out] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write I/O registers.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table
+ published by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Width The width of the access. Enumerated in bytes.
+ @param[in] Address The physical address of the access.
+ @param[in] Count The number of accesses to perform.
+ @param[in] Buffer A pointer to the buffer of data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this EFI system.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ 8-bit I/O read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return An 8-bit value returned from the I/O space.
+**/
+UINT8
+EFIAPI
+CpuIoRead8 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ );
+
+/**
+ 16-bit I/O read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 16-bit value returned from the I/O space.
+
+**/
+UINT16
+EFIAPI
+CpuIoRead16 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ );
+
+/**
+ 32-bit I/O read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 32-bit value returned from the I/O space.
+
+**/
+UINT32
+EFIAPI
+CpuIoRead32 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ );
+
+/**
+ 64-bit I/O read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 64-bit value returned from the I/O space.
+
+**/
+UINT64
+EFIAPI
+CpuIoRead64 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ );
+
+/**
+ 8-bit I/O write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuIoWrite8 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT8 Data
+ );
+
+/**
+ 16-bit I/O write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuIoWrite16 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT16 Data
+ );
+
+/**
+ 32-bit I/O write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuIoWrite32 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT32 Data
+ );
+
+/**
+ 64-bit I/O write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuIoWrite64 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT64 Data
+ );
+
+/**
+ 8-bit memory read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return An 8-bit value returned from the memory space.
+
+**/
+UINT8
+EFIAPI
+CpuMemRead8 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ );
+
+/**
+ 16-bit memory read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 16-bit value returned from the memory space.
+
+**/
+UINT16
+EFIAPI
+CpuMemRead16 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ );
+
+/**
+ 32-bit memory read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 32-bit value returned from the memory space.
+
+**/
+UINT32
+EFIAPI
+CpuMemRead32 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ );
+
+/**
+ 64-bit memory read operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+
+ @return A 64-bit value returned from the memory space.
+
+**/
+UINT64
+EFIAPI
+CpuMemRead64 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address
+ );
+
+/**
+ 8-bit memory write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuMemWrite8 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT8 Data
+ );
+
+/**
+ 16-bit memory write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuMemWrite16 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT16 Data
+ );
+
+/**
+ 32-bit memory write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuMemWrite32 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT32 Data
+ );
+
+/**
+ 64-bit memory write operations.
+
+ @param[in] PeiServices An indirect pointer to the PEI Services Table published
+ by the PEI Foundation.
+ @param[in] This Pointer to local data for the interface.
+ @param[in] Address The physical address of the access.
+ @param[in] Data The data to write.
+
+**/
+VOID
+EFIAPI
+CpuMemWrite64 (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_CPU_IO_PPI *This,
+ IN UINT64 Address,
+ IN UINT64 Data
+ );
+
+#endif
diff --git a/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.inf b/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.inf
new file mode 100755
index 0000000000..4ebd9e2fb1
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.inf
@@ -0,0 +1,49 @@
+## @file
+# Produces the CPU I/O PPI.
+#
+# This PEIM produces of the CPU I/O PPI.
+#
+# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuIoPei
+ FILE_GUID = AE265864-CF5D-41a8-913D-71C155E76442
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = CpuIoInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CpuIoPei.c
+ CpuIoPei.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ BaseLib
+ DebugLib
+ IoLib
+ PeiServicesLib
+
+[Ppis]
+ gEfiPeiCpuIoPpiInstalledGuid # PPI ALWAYS_PRODUCED
+
+[Depex]
+ TRUE
diff --git a/CloverEFI/UefiCpuPkg/Include/Library/LocalApicLib.h b/CloverEFI/UefiCpuPkg/Include/Library/LocalApicLib.h
new file mode 100755
index 0000000000..52914fa9bd
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Include/Library/LocalApicLib.h
@@ -0,0 +1,372 @@
+/** @file
+ Public include file for Local APIC library.
+
+ Local APIC library assumes local APIC is enabled. It does not
+ handles cases where local APIC is disabled.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ 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 __LOCAL_APIC_LIB_H__
+#define __LOCAL_APIC_LIB_H__
+
+#define LOCAL_APIC_MODE_XAPIC 0x1 ///< xAPIC mode.
+#define LOCAL_APIC_MODE_X2APIC 0x2 ///< x2APIC mode.
+
+/**
+ Get the current local APIC mode.
+
+ If local APIC is disabled, then ASSERT.
+
+ @retval LOCAL_APIC_MODE_XAPIC current APIC mode is xAPIC.
+ @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.
+**/
+UINTN
+EFIAPI
+GetApicMode (
+ VOID
+ );
+
+/**
+ Set the current local APIC mode.
+
+ If the specified local APIC mode is not valid, then ASSERT.
+ If the specified local APIC mode can't be set as current, then ASSERT.
+
+ @param ApicMode APIC mode to be set.
+**/
+VOID
+EFIAPI
+SetApicMode (
+ IN UINTN ApicMode
+ );
+
+/**
+ Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.
+
+ In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID.
+ In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case,
+ the 32-bit local APIC ID is returned as initial APIC ID.
+
+ @return 32-bit initial local APIC ID of the executing processor.
+**/
+UINT32
+EFIAPI
+GetInitialApicId (
+ VOID
+ );
+
+/**
+ Get the local APIC ID of the executing processor.
+
+ @return 32-bit local APIC ID of the executing processor.
+**/
+UINT32
+EFIAPI
+GetApicId (
+ VOID
+ );
+
+/**
+ Get the value of the local APIC version register.
+
+ @return the value of the local APIC version register.
+**/
+UINT32
+EFIAPI
+GetApicVersion (
+ VOID
+ );
+
+/**
+ Send a Fixed IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId The local APIC ID of the target processor.
+ @param Vector The vector number of the interrupt being sent.
+**/
+VOID
+EFIAPI
+SendFixedIpi (
+ IN UINT32 ApicId,
+ IN UINT8 Vector
+ );
+
+/**
+ Send a Fixed IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+
+ @param Vector The vector number of the interrupt being sent.
+**/
+VOID
+EFIAPI
+SendFixedIpiAllExcludingSelf (
+ IN UINT8 Vector
+ );
+
+/**
+ Send a SMI IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+**/
+VOID
+EFIAPI
+SendSmiIpi (
+ IN UINT32 ApicId
+ );
+
+/**
+ Send a SMI IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+**/
+VOID
+EFIAPI
+SendSmiIpiAllExcludingSelf (
+ VOID
+ );
+
+/**
+ Send an INIT IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+**/
+VOID
+EFIAPI
+SendInitIpi (
+ IN UINT32 ApicId
+ );
+
+/**
+ Send an INIT IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+**/
+VOID
+EFIAPI
+SendInitIpiAllExcludingSelf (
+ VOID
+ );
+
+/**
+ Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ if StartupRoutine >= 1M, then ASSERT.
+ if StartupRoutine is not multiple of 4K, then ASSERT.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+ @param StartupRoutine Points to a start-up routine which is below 1M physical
+ address and 4K aligned.
+**/
+VOID
+EFIAPI
+SendInitSipiSipi (
+ IN UINT32 ApicId,
+ IN UINT32 StartupRoutine
+ );
+
+/**
+ Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+
+ if StartupRoutine >= 1M, then ASSERT.
+ if StartupRoutine is not multiple of 4K, then ASSERT.
+
+ @param StartupRoutine Points to a start-up routine which is below 1M physical
+ address and 4K aligned.
+**/
+VOID
+EFIAPI
+SendInitSipiSipiAllExcludingSelf (
+ IN UINT32 StartupRoutine
+ );
+
+/**
+ Programming Virtual Wire Mode.
+
+ This function programs the local APIC for virtual wire mode following
+ the example described in chapter A.3 of the MP 1.4 spec.
+
+ IOxAPIC is not involved in this type of virtual wire mode.
+**/
+VOID
+EFIAPI
+ProgramVirtualWireMode (
+ VOID
+ );
+
+/**
+ Disable LINT0 & LINT1 interrupts.
+
+ This function sets the mask flag in the LVT LINT0 & LINT1 registers.
+**/
+VOID
+EFIAPI
+DisableLvtInterrupts (
+ VOID
+ );
+
+/**
+ Read the initial count value from the init-count register.
+
+ @return The initial count value read from the init-count register.
+**/
+UINT32
+EFIAPI
+GetApicTimerInitCount (
+ VOID
+ );
+
+/**
+ Read the current count value from the current-count register.
+
+ @return The current count value read from the current-count register.
+**/
+UINT32
+EFIAPI
+GetApicTimerCurrentCount (
+ VOID
+ );
+
+/**
+ Initialize the local APIC timer.
+
+ The local APIC timer is initialized and enabled.
+
+ @param DivideValue The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
+ If it is 0, then use the current divide value in the DCR.
+ @param InitCount The initial count value.
+ @param PeriodicMode If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
+ @param Vector The timer interrupt vector number.
+**/
+VOID
+EFIAPI
+InitializeApicTimer (
+ IN UINTN DivideValue,
+ IN UINT32 InitCount,
+ IN BOOLEAN PeriodicMode,
+ IN UINT8 Vector
+ );
+
+/**
+ Get the state of the local APIC timer.
+
+ @param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
+ @param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
+ @param Vector Return the timer interrupt vector number.
+**/
+VOID
+EFIAPI
+GetApicTimerState (
+ OUT UINTN *DivideValue OPTIONAL,
+ OUT BOOLEAN *PeriodicMode OPTIONAL,
+ OUT UINT8 *Vector OPTIONAL
+ );
+
+/**
+ Enable the local APIC timer interrupt.
+**/
+VOID
+EFIAPI
+EnableApicTimerInterrupt (
+ VOID
+ );
+
+/**
+ Disable the local APIC timer interrupt.
+**/
+VOID
+EFIAPI
+DisableApicTimerInterrupt (
+ VOID
+ );
+
+/**
+ Get the local APIC timer interrupt state.
+
+ @retval TRUE The local APIC timer interrupt is enabled.
+ @retval FALSE The local APIC timer interrupt is disabled.
+**/
+BOOLEAN
+EFIAPI
+GetApicTimerInterruptState (
+ VOID
+ );
+
+/**
+ Send EOI to the local APIC.
+**/
+VOID
+EFIAPI
+SendApicEoi (
+ VOID
+ );
+
+/**
+ Get the 32-bit address that a device should use to send a Message Signaled
+ Interrupt (MSI) to the Local APIC of the currently executing processor.
+
+ @return 32-bit address used to send an MSI to the Local APIC.
+**/
+UINT32
+EFIAPI
+GetApicMsiAddress (
+ VOID
+ );
+
+/**
+ Get the 64-bit data value that a device should use to send a Message Signaled
+ Interrupt (MSI) to the Local APIC of the currently executing processor.
+
+ If Vector is not in range 0x10..0xFE, then ASSERT().
+ If DeliveryMode is not supported, then ASSERT().
+
+ @param Vector The 8-bit interrupt vector associated with the MSI.
+ Must be in the range 0x10..0xFE
+ @param DeliveryMode A 3-bit value that specifies how the recept of the MSI
+ is handled. The only supported values are:
+ 0: LOCAL_APIC_DELIVERY_MODE_FIXED
+ 1: LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY
+ 2: LOCAL_APIC_DELIVERY_MODE_SMI
+ 4: LOCAL_APIC_DELIVERY_MODE_NMI
+ 5: LOCAL_APIC_DELIVERY_MODE_INIT
+ 7: LOCAL_APIC_DELIVERY_MODE_EXTINT
+
+ @param LevelTriggered TRUE specifies a level triggered interrupt.
+ FALSE specifies an edge triggered interrupt.
+ @param AssertionLevel Ignored if LevelTriggered is FALSE.
+ TRUE specifies a level triggered interrupt that active
+ when the interrupt line is asserted.
+ FALSE specifies a level triggered interrupt that active
+ when the interrupt line is deasserted.
+
+ @return 64-bit data value used to send an MSI to the Local APIC.
+**/
+UINT64
+EFIAPI
+GetApicMsiValue (
+ IN UINT8 Vector,
+ IN UINTN DeliveryMode,
+ IN BOOLEAN LevelTriggered,
+ IN BOOLEAN AssertionLevel
+ );
+
+#endif
+
diff --git a/CloverEFI/UefiCpuPkg/Include/Library/MtrrLib.h b/CloverEFI/UefiCpuPkg/Include/Library/MtrrLib.h
new file mode 100755
index 0000000000..d24f10f36b
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Include/Library/MtrrLib.h
@@ -0,0 +1,334 @@
+/** @file
+ MTRR setting library
+
+ Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.
+ 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 _MTRR_LIB_H_
+#define _MTRR_LIB_H_
+
+//
+// According to IA32 SDM, MTRRs number and msr offset are always consistent
+// for IA32 processor family
+//
+
+//
+// The semantics of below macro is MAX_MTRR_NUMBER_OF_VARIABLE_MTRR, the real number can be read out from MTRR_CAP register.
+//
+#define MTRR_NUMBER_OF_VARIABLE_MTRR 32
+//
+// Firmware need reserve 2 MTRR for OS
+//
+#define RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER 2
+
+#define MTRR_NUMBER_OF_FIXED_MTRR 11
+//
+// Below macro is deprecated, and should not be used.
+//
+#define FIRMWARE_VARIABLE_MTRR_NUMBER 6
+#define MTRR_LIB_IA32_MTRR_CAP 0x0FE
+#define MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK 0x0FF
+#define MTRR_LIB_IA32_MTRR_FIX64K_00000 0x250
+#define MTRR_LIB_IA32_MTRR_FIX16K_80000 0x258
+#define MTRR_LIB_IA32_MTRR_FIX16K_A0000 0x259
+#define MTRR_LIB_IA32_MTRR_FIX4K_C0000 0x268
+#define MTRR_LIB_IA32_MTRR_FIX4K_C8000 0x269
+#define MTRR_LIB_IA32_MTRR_FIX4K_D0000 0x26A
+#define MTRR_LIB_IA32_MTRR_FIX4K_D8000 0x26B
+#define MTRR_LIB_IA32_MTRR_FIX4K_E0000 0x26C
+#define MTRR_LIB_IA32_MTRR_FIX4K_E8000 0x26D
+#define MTRR_LIB_IA32_MTRR_FIX4K_F0000 0x26E
+#define MTRR_LIB_IA32_MTRR_FIX4K_F8000 0x26F
+#define MTRR_LIB_IA32_VARIABLE_MTRR_BASE 0x200
+//
+// Below macro is deprecated, and should not be used.
+//
+#define MTRR_LIB_IA32_VARIABLE_MTRR_END 0x20F
+#define MTRR_LIB_IA32_MTRR_DEF_TYPE 0x2FF
+#define MTRR_LIB_MSR_VALID_MASK 0xFFFFFFFFFULL
+#define MTRR_LIB_CACHE_VALID_ADDRESS 0xFFFFFF000ULL
+#define MTRR_LIB_CACHE_MTRR_ENABLED 0x800
+#define MTRR_LIB_CACHE_FIXED_MTRR_ENABLED 0x400
+
+//
+// Structure to describe a fixed MTRR
+//
+typedef struct {
+ UINT32 Msr;
+ UINT32 BaseAddress;
+ UINT32 Length;
+} FIXED_MTRR;
+
+//
+// Structure to describe a variable MTRR
+//
+typedef struct {
+ UINT64 BaseAddress;
+ UINT64 Length;
+ UINT64 Type;
+ UINT32 Msr;
+ BOOLEAN Valid;
+ BOOLEAN Used;
+} VARIABLE_MTRR;
+
+//
+// Structure to hold base and mask pair for variable MTRR register
+//
+typedef struct _MTRR_VARIABLE_SETTING_ {
+ UINT64 Base;
+ UINT64 Mask;
+} MTRR_VARIABLE_SETTING;
+
+//
+// Array for variable MTRRs
+//
+typedef struct _MTRR_VARIABLE_SETTINGS_ {
+ MTRR_VARIABLE_SETTING Mtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+} MTRR_VARIABLE_SETTINGS;
+
+//
+// Array for fixed mtrrs
+//
+typedef struct _MTRR_FIXED_SETTINGS_ {
+ UINT64 Mtrr[MTRR_NUMBER_OF_FIXED_MTRR];
+} MTRR_FIXED_SETTINGS;
+
+//
+// Structure to hold all MTRRs
+//
+typedef struct _MTRR_SETTINGS_ {
+ MTRR_FIXED_SETTINGS Fixed;
+ MTRR_VARIABLE_SETTINGS Variables;
+ UINT64 MtrrDefType;
+} MTRR_SETTINGS;
+
+//
+// Memory cache types
+//
+typedef enum {
+ CacheUncacheable = 0,
+ CacheWriteCombining = 1,
+ CacheWriteThrough = 4,
+ CacheWriteProtected = 5,
+ CacheWriteBack = 6
+} MTRR_MEMORY_CACHE_TYPE;
+
+#define MTRR_CACHE_UNCACHEABLE 0
+#define MTRR_CACHE_WRITE_COMBINING 1
+#define MTRR_CACHE_WRITE_THROUGH 4
+#define MTRR_CACHE_WRITE_PROTECTED 5
+#define MTRR_CACHE_WRITE_BACK 6
+#define MTRR_CACHE_INVALID_TYPE 7
+
+/**
+ Returns the variable MTRR count for the CPU.
+
+ @return Variable MTRR count
+
+**/
+UINT32
+EFIAPI
+GetVariableMtrrCount (
+ VOID
+ );
+
+/**
+ Returns the firmware usable variable MTRR count for the CPU.
+
+ @return Firmware usable variable MTRR count
+
+**/
+UINT32
+EFIAPI
+GetFirmwareVariableMtrrCount (
+ VOID
+ );
+
+/**
+ This function attempts to set the attributes for a memory range.
+
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval RETURN_SUCCESS The attributes were set for the memory region.
+ @retval RETURN_INVALID_PARAMETER Length is zero.
+ @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
+ memory resource range specified by BaseAddress and Length.
+ @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+ @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+
+**/
+RETURN_STATUS
+EFIAPI
+MtrrSetMemoryAttribute (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN MTRR_MEMORY_CACHE_TYPE Attribute
+ );
+
+
+/**
+ This function will get the memory cache type of the specific address.
+ This function is mainly for debugging purposes.
+
+ @param Address The specific address
+
+ @return The memory cache type of the specific address
+
+**/
+MTRR_MEMORY_CACHE_TYPE
+EFIAPI
+MtrrGetMemoryAttribute (
+ IN PHYSICAL_ADDRESS Address
+ );
+
+
+/**
+ This function will get the raw value in variable MTRRs
+
+ @param VariableSettings A buffer to hold variable MTRRs content.
+
+ @return The buffer point to MTRR_VARIABLE_SETTINGS in which holds the content of the variable mtrr
+
+**/
+MTRR_VARIABLE_SETTINGS*
+EFIAPI
+MtrrGetVariableMtrr (
+ OUT MTRR_VARIABLE_SETTINGS *VariableSettings
+ );
+
+
+/**
+ This function sets fixed MTRRs
+
+ @param VariableSettings A buffer to hold variable MTRRs content.
+
+ @return The pointer of VariableSettings
+
+**/
+MTRR_VARIABLE_SETTINGS*
+EFIAPI
+MtrrSetVariableMtrr (
+ IN MTRR_VARIABLE_SETTINGS *VariableSettings
+ );
+
+
+/**
+ This function gets the content in fixed MTRRs
+
+ @param FixedSettings A buffer to hold fixed MTRRs content.
+
+ @return The pointer of FixedSettings
+
+**/
+MTRR_FIXED_SETTINGS*
+EFIAPI
+MtrrGetFixedMtrr (
+ OUT MTRR_FIXED_SETTINGS *FixedSettings
+ );
+
+
+/**
+ This function sets fixed MTRRs
+
+ @param FixedSettings A buffer holding fixed MTRRs content.
+
+ @return The pointer of FixedSettings
+
+**/
+MTRR_FIXED_SETTINGS*
+EFIAPI
+MtrrSetFixedMtrr (
+ IN MTRR_FIXED_SETTINGS *FixedSettings
+ );
+
+
+/**
+ This function gets the content in all MTRRs (variable and fixed)
+
+ @param MtrrSetting A buffer to hold all MTRRs content.
+
+ @return The pointer of MtrrSetting
+
+**/
+MTRR_SETTINGS *
+EFIAPI
+MtrrGetAllMtrrs (
+ OUT MTRR_SETTINGS *MtrrSetting
+ );
+
+
+/**
+ This function sets all MTRRs (variable and fixed)
+
+ @param MtrrSetting A buffer to hold all MTRRs content.
+
+ @return The pointer of MtrrSetting
+
+**/
+MTRR_SETTINGS *
+EFIAPI
+MtrrSetAllMtrrs (
+ IN MTRR_SETTINGS *MtrrSetting
+ );
+
+
+/**
+ Get the attribute of variable MTRRs.
+
+ This function shadows the content of variable MTRRs into
+ an internal array: VariableMtrr
+
+ @param MtrrValidBitsMask The mask for the valid bit of the MTRR
+ @param MtrrValidAddressMask The valid address mask for MTRR since the base address in
+ MTRR must align to 4K, so valid address mask equal to
+ MtrrValidBitsMask & 0xfffffffffffff000ULL
+ @param VariableMtrr The array to shadow variable MTRRs content
+ @return The ruturn value of this paramter indicates the number of
+ MTRRs which has been used.
+**/
+UINT32
+EFIAPI
+MtrrGetMemoryAttributeInVariableMtrr (
+ IN UINT64 MtrrValidBitsMask,
+ IN UINT64 MtrrValidAddressMask,
+ OUT VARIABLE_MTRR *VariableMtrr
+ );
+
+
+/**
+ This function prints all MTRRs for debugging.
+**/
+VOID
+EFIAPI
+MtrrDebugPrintAllMtrrs (
+ VOID
+ );
+
+/**
+ Checks if MTRR is supported.
+
+ @retval TRUE MTRR is supported.
+ @retval FALSE MTRR is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+IsMtrrSupported (
+ VOID
+ );
+
+#endif // _MTRR_LIB_H_
diff --git a/CloverEFI/UefiCpuPkg/Include/Library/UefiCpuLib.h b/CloverEFI/UefiCpuPkg/Include/Library/UefiCpuLib.h
new file mode 100755
index 0000000000..561d579968
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Include/Library/UefiCpuLib.h
@@ -0,0 +1,38 @@
+/** @file
+ Public header file for UEFI CPU library class.
+
+ This library class defines some routines that are generic for IA32 family CPU
+ to be UEFI specification compliant.
+
+ Copyright (c) 2009, Intel Corporation. All rights reserved.
+ 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 __UEFI_CPU_LIB_H__
+#define __UEFI_CPU_LIB_H__
+
+
+
+/**
+ Initializes floating point units for requirement of UEFI specification.
+
+ This function initializes floating-point control word to 0x027F (all exceptions
+ masked,double-precision, round-to-nearest) and multimedia-extensions control word
+ (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+ for masked underflow).
+
+**/
+VOID
+EFIAPI
+InitializeFloatingPointUnits (
+ VOID
+ );
+
+#endif
diff --git a/CloverEFI/UefiCpuPkg/Include/Register/LocalApic.h b/CloverEFI/UefiCpuPkg/Include/Register/LocalApic.h
new file mode 100755
index 0000000000..bb0e211dc7
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Include/Register/LocalApic.h
@@ -0,0 +1,214 @@
+/** @file
+ IA32 Local APIC Definitions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ 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 __LOCAL_APIC_H__
+#define __LOCAL_APIC_H__
+
+//
+// Definitions for IA32 architectural MSRs
+//
+#define MSR_IA32_APIC_BASE_ADDRESS 0x1B
+
+//
+// Definitions for CPUID instruction
+//
+#define CPUID_VERSION_INFO 0x1
+#define CPUID_EXTENDED_FUNCTION 0x80000000
+#define CPUID_VIR_PHY_ADDRESS_SIZE 0x80000008
+
+//
+// Definition for Local APIC registers and related values
+//
+#define XAPIC_ID_OFFSET 0x20
+#define XAPIC_VERSION_OFFSET 0x30
+#define XAPIC_EOI_OFFSET 0x0b0
+#define XAPIC_ICR_DFR_OFFSET 0x0e0
+#define XAPIC_SPURIOUS_VECTOR_OFFSET 0x0f0
+#define XAPIC_ICR_LOW_OFFSET 0x300
+#define XAPIC_ICR_HIGH_OFFSET 0x310
+#define XAPIC_LVT_TIMER_OFFSET 0x320
+#define XAPIC_LVT_LINT0_OFFSET 0x350
+#define XAPIC_LVT_LINT1_OFFSET 0x360
+#define XAPIC_TIMER_INIT_COUNT_OFFSET 0x380
+#define XAPIC_TIMER_CURRENT_COUNT_OFFSET 0x390
+#define XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET 0x3E0
+
+#define X2APIC_MSR_BASE_ADDRESS 0x800
+#define X2APIC_MSR_ICR_ADDRESS 0x830
+
+#define LOCAL_APIC_DELIVERY_MODE_FIXED 0
+#define LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY 1
+#define LOCAL_APIC_DELIVERY_MODE_SMI 2
+#define LOCAL_APIC_DELIVERY_MODE_NMI 4
+#define LOCAL_APIC_DELIVERY_MODE_INIT 5
+#define LOCAL_APIC_DELIVERY_MODE_STARTUP 6
+#define LOCAL_APIC_DELIVERY_MODE_EXTINT 7
+
+#define LOCAL_APIC_DESTINATION_SHORTHAND_NO_SHORTHAND 0
+#define LOCAL_APIC_DESTINATION_SHORTHAND_SELF 1
+#define LOCAL_APIC_DESTINATION_SHORTHAND_ALL_INCLUDING_SELF 2
+#define LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF 3
+
+typedef union {
+ struct {
+ UINT32 Reserved0:8; ///< Reserved.
+ UINT32 Bsp:1; ///< Processor is BSP.
+ UINT32 Reserved1:1; ///< Reserved.
+ UINT32 Extd:1; ///< Enable x2APIC mode.
+ UINT32 En:1; ///< xAPIC global enable/disable.
+ UINT32 ApicBaseLow:20; ///< APIC Base physical address. The actual field width depends on physical address width.
+ UINT32 ApicBaseHigh:32;
+ } Bits;
+ UINT64 Uint64;
+} MSR_IA32_APIC_BASE;
+
+//
+// Local APIC Version Register.
+//
+typedef union {
+ struct {
+ UINT32 Version:8; ///< The version numbers of the local APIC.
+ UINT32 Reserved0:8; ///< Reserved.
+ UINT32 MaxLvtEntry:8; ///< Number of LVT entries minus 1.
+ UINT32 EoiBroadcastSuppression:1; ///< 1 if EOI-broadcast suppression supported.
+ UINT32 Reserved1:7; ///< Reserved.
+ } Bits;
+ UINT32 Uint32;
+} LOCAL_APIC_VERSION;
+
+//
+// Low half of Interrupt Command Register (ICR).
+//
+typedef union {
+ struct {
+ UINT32 Vector:8; ///< The vector number of the interrupt being sent.
+ UINT32 DeliveryMode:3; ///< Specifies the type of IPI to be sent.
+ UINT32 DestinationMode:1; ///< 0: physical destination mode, 1: logical destination mode.
+ UINT32 DeliveryStatus:1; ///< Indicates the IPI delivery status. This field is reserved in x2APIC mode.
+ UINT32 Reserved0:1; ///< Reserved.
+ UINT32 Level:1; ///< 0 for the INIT level de-assert delivery mode. Otherwise 1.
+ UINT32 TriggerMode:1; ///< 0: edge, 1: level when using the INIT level de-assert delivery mode.
+ UINT32 Reserved1:2; ///< Reserved.
+ UINT32 DestinationShorthand:2; ///< A shorthand notation to specify the destination of the interrupt.
+ UINT32 Reserved2:12; ///< Reserved.
+ } Bits;
+ UINT32 Uint32;
+} LOCAL_APIC_ICR_LOW;
+
+//
+// High half of Interrupt Command Register (ICR)
+//
+typedef union {
+ struct {
+ UINT32 Reserved0:24; ///< Reserved.
+ UINT32 Destination:8; ///< Specifies the target processor or processors in xAPIC mode.
+ } Bits;
+ UINT32 Uint32; ///< Destination field expanded to 32-bit in x2APIC mode.
+} LOCAL_APIC_ICR_HIGH;
+
+//
+// Spurious-Interrupt Vector Register (SVR)
+//
+typedef union {
+ struct {
+ UINT32 SpuriousVector:8; ///< Spurious Vector.
+ UINT32 SoftwareEnable:1; ///< APIC Software Enable/Disable.
+ UINT32 FocusProcessorChecking:1; ///< Focus Processor Checking.
+ UINT32 Reserved0:2; ///< Reserved.
+ UINT32 EoiBroadcastSuppression:1; ///< EOI-Broadcast Suppression.
+ UINT32 Reserved1:19; ///< Reserved.
+ } Bits;
+ UINT32 Uint32;
+} LOCAL_APIC_SVR;
+
+//
+// Divide Configuration Register (DCR)
+//
+typedef union {
+ struct {
+ UINT32 DivideValue1:2; ///< Low 2 bits of the divide value.
+ UINT32 Reserved0:1; ///< Always 0.
+ UINT32 DivideValue2:1; ///< Highest 1 bit of the divide value.
+ UINT32 Reserved1:28; ///< Reserved.
+ } Bits;
+ UINT32 Uint32;
+} LOCAL_APIC_DCR;
+
+//
+// LVT Timer Register
+//
+typedef union {
+ struct {
+ UINT32 Vector:8; ///< The vector number of the interrupt being sent.
+ UINT32 Reserved0:4; ///< Reserved.
+ UINT32 DeliveryStatus:1; ///< 0: Idle, 1: send pending.
+ UINT32 Reserved1:3; ///< Reserved.
+ UINT32 Mask:1; ///< 0: Not masked, 1: Masked.
+ UINT32 TimerMode:1; ///< 0: One-shot, 1: Periodic.
+ UINT32 Reserved2:14; ///< Reserved.
+ } Bits;
+ UINT32 Uint32;
+} LOCAL_APIC_LVT_TIMER;
+
+//
+// LVT LINT0/LINT1 Register
+//
+typedef union {
+ struct {
+ UINT32 Vector:8; ///< The vector number of the interrupt being sent.
+ UINT32 DeliveryMode:3; ///< Specifies the type of interrupt to be sent.
+ UINT32 Reserved0:1; ///< Reserved.
+ UINT32 DeliveryStatus:1; ///< 0: Idle, 1: send pending.
+ UINT32 InputPinPolarity:1; ///< Interrupt Input Pin Polarity.
+ UINT32 RemoteIrr:1; ///< RO. Set when the local APIC accepts the interrupt and reset when an EOI is received.
+ UINT32 TriggerMode:1; ///< 0:edge, 1:level.
+ UINT32 Mask:1; ///< 0: Not masked, 1: Masked.
+ UINT32 Reserved1:15; ///< Reserved.
+ } Bits;
+ UINT32 Uint32;
+} LOCAL_APIC_LVT_LINT;
+
+//
+// MSI Address Register
+//
+typedef union {
+ struct {
+ UINT32 Reserved0:2; ///< Reserved
+ UINT32 DestinationMode:1; ///< Specifies the Destination Mode.
+ UINT32 RedirectionHint:1; ///< Specifies the Redirection Hint.
+ UINT32 Reserved1:8; ///< Reserved.
+ UINT32 DestinationId:8; ///< Specifies the Destination ID.
+ UINT32 BaseAddress:12; ///< Must be 0FEEH
+ } Bits;
+ UINT32 Uint32;
+} LOCAL_APIC_MSI_ADDRESS;
+
+//
+// MSI Address Register
+//
+typedef union {
+ struct {
+ UINT32 Vector:8; ///< Interrupt vector in range 010h..0FEH
+ UINT32 DeliveryMode:3; ///< Specifies the type of interrupt to be sent.
+ UINT32 Reserved0:3; ///< Reserved.
+ UINT32 Level:1; ///< 0:Deassert, 1:Assert. Ignored for Edge triggered interrupts.
+ UINT32 TriggerMode:1; ///< 0:Edge, 1:Level.
+ UINT32 Reserved1:16; ///< Reserved.
+ UINT32 Reserved2:32; ///< Reserved.
+ } Bits;
+ UINT64 Uint64;
+} LOCAL_APIC_MSI_DATA;
+
+#endif
+
diff --git a/CloverEFI/UefiCpuPkg/Include/Register/Microcode.h b/CloverEFI/UefiCpuPkg/Include/Register/Microcode.h
new file mode 100755
index 0000000000..94529a1ca2
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Include/Register/Microcode.h
@@ -0,0 +1,200 @@
+/** @file
+ Microcode Definitions.
+
+ Microcode Definitions based on contents of the
+ Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ Volume 3A, Section 9.11 Microcode Definitions
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.
+ 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.
+
+ @par Specification Reference:
+ Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume 3A,
+ June 2016, Chapter 9 Processor Management and Initialization, Section 9-11.
+
+**/
+
+#ifndef __MICROCODE_H__
+#define __MICROCODE_H__
+
+///
+/// CPU Microcode Date in BCD format
+///
+typedef union {
+ struct {
+ UINT32 Year:16;
+ UINT32 Day:8;
+ UINT32 Month:8;
+ } Bits;
+ UINT32 Uint32;
+} CPU_MICROCODE_DATE;
+
+///
+/// CPU Microcode Processor Signature format
+///
+typedef union {
+ struct {
+ UINT32 Stepping:4;
+ UINT32 Model:4;
+ UINT32 Family:4;
+ UINT32 Type:2;
+ UINT32 Reserved1:2;
+ UINT32 ExtendedModel:4;
+ UINT32 ExtendedFamily:8;
+ UINT32 Reserved2:4;
+ } Bits;
+ UINT32 Uint32;
+} CPU_MICROCODE_PROCESSOR_SIGNATURE;
+
+#pragma pack (1)
+
+///
+/// Microcode Update Format definition
+///
+typedef struct {
+ ///
+ /// Version number of the update header
+ ///
+ UINT32 HeaderVersion;
+ ///
+ /// Unique version number for the update, the basis for the update
+ /// signature provided by the processor to indicate the current update
+ /// functioning within the processor. Used by the BIOS to authenticate
+ /// the update and verify that the processor loads successfully. The
+ /// value in this field cannot be used for processor stepping identification
+ /// alone. This is a signed 32-bit number.
+ ///
+ UINT32 UpdateRevision;
+ ///
+ /// Date of the update creation in binary format: mmddyyyy (e.g.
+ /// 07/18/98 is 07181998H).
+ ///
+ CPU_MICROCODE_DATE Date;
+ ///
+ /// Extended family, extended model, type, family, model, and stepping
+ /// of processor that requires this particular update revision (e.g.,
+ /// 00000650H). Each microcode update is designed specifically for a
+ /// given extended family, extended model, type, family, model, and
+ /// stepping of the processor.
+ /// The BIOS uses the processor signature field in conjunction with the
+ /// CPUID instruction to determine whether or not an update is
+ /// appropriate to load on a processor. The information encoded within
+ /// this field exactly corresponds to the bit representations returned by
+ /// the CPUID instruction.
+ ///
+ CPU_MICROCODE_PROCESSOR_SIGNATURE ProcessorSignature;
+ ///
+ /// Checksum of Update Data and Header. Used to verify the integrity of
+ /// the update header and data. Checksum is correct when the
+ /// summation of all the DWORDs (including the extended Processor
+ /// Signature Table) that comprise the microcode update result in
+ /// 00000000H.
+ ///
+ UINT32 Checksum;
+ ///
+ /// Version number of the loader program needed to correctly load this
+ /// update. The initial version is 00000001H
+ ///
+ UINT32 LoaderRevision;
+ ///
+ /// Platform type information is encoded in the lower 8 bits of this 4-
+ /// byte field. Each bit represents a particular platform type for a given
+ /// CPUID. The BIOS uses the processor flags field in conjunction with
+ /// the platform Id bits in MSR (17H) to determine whether or not an
+ /// update is appropriate to load on a processor. Multiple bits may be set
+ /// representing support for multiple platform IDs.
+ ///
+ UINT32 ProcessorFlags;
+ ///
+ /// Specifies the size of the encrypted data in bytes, and must be a
+ /// multiple of DWORDs. If this value is 00000000H, then the microcode
+ /// update encrypted data is 2000 bytes (or 500 DWORDs).
+ ///
+ UINT32 DataSize;
+ ///
+ /// Specifies the total size of the microcode update in bytes. It is the
+ /// summation of the header size, the encrypted data size and the size of
+ /// the optional extended signature table. This value is always a multiple
+ /// of 1024.
+ ///
+ UINT32 TotalSize;
+ ///
+ /// Reserved fields for future expansion.
+ ///
+ UINT8 Reserved[12];
+} CPU_MICROCODE_HEADER;
+
+///
+/// Extended Signature Table Header Field Definitions
+///
+typedef struct {
+ ///
+ /// Specifies the number of extended signature structures (Processor
+ /// Signature[n], processor flags[n] and checksum[n]) that exist in this
+ /// microcode update
+ ///
+ UINT32 ExtendedSignatureCount;
+ ///
+ /// Checksum of update extended processor signature table. Used to
+ /// verify the integrity of the extended processor signature table.
+ /// Checksum is correct when the summation of the DWORDs that
+ /// comprise the extended processor signature table results in
+ /// 00000000H.
+ ///
+ UINT32 ExtendedChecksum;
+ ///
+ /// Reserved fields.
+ ///
+ UINT8 Reserved[12];
+} CPU_MICROCODE_EXTENDED_TABLE_HEADER;
+
+///
+/// Extended Signature Table Field Definitions
+///
+typedef struct {
+ ///
+ /// Extended family, extended model, type, family, model, and stepping
+ /// of processor that requires this particular update revision (e.g.,
+ /// 00000650H). Each microcode update is designed specifically for a
+ /// given extended family, extended model, type, family, model, and
+ /// stepping of the processor.
+ /// The BIOS uses the processor signature field in conjunction with the
+ /// CPUID instruction to determine whether or not an update is
+ /// appropriate to load on a processor. The information encoded within
+ /// this field exactly corresponds to the bit representations returned by
+ /// the CPUID instruction.
+ ///
+ CPU_MICROCODE_PROCESSOR_SIGNATURE ProcessorSignature;
+ ///
+ /// Platform type information is encoded in the lower 8 bits of this 4-
+ /// byte field. Each bit represents a particular platform type for a given
+ /// CPUID. The BIOS uses the processor flags field in conjunction with
+ /// the platform Id bits in MSR (17H) to determine whether or not an
+ /// update is appropriate to load on a processor. Multiple bits may be set
+ /// representing support for multiple platform IDs.
+ ///
+ UINT32 ProcessorFlag;
+ ///
+ /// Used by utility software to decompose a microcode update into
+ /// multiple microcode updates where each of the new updates is
+ /// constructed without the optional Extended Processor Signature
+ /// Table.
+ /// To calculate the Checksum, substitute the Primary Processor
+ /// Signature entry and the Processor Flags entry with the
+ /// corresponding Extended Patch entry. Delete the Extended Processor
+ /// Signature Table entries. The Checksum is correct when the
+ /// summation of all DWORDs that comprise the created Extended
+ /// Processor Patch results in 00000000H.
+ ///
+ UINT32 Checksum;
+} CPU_MICROCODE_EXTENDED_TABLE;
+
+#pragma pack ()
+
+#endif
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
new file mode 100755
index 0000000000..442eb07e97
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
@@ -0,0 +1,44 @@
+## @file
+# This library defines some routines that are generic for IA32 family CPU
+# to be UEFI specification compliant.
+#
+# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseUefiCpuLib
+ FILE_GUID = 34C24FD7-7A90-45c2-89FD-946473D9CE98
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UefiCpuLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.IA32]
+ Ia32/InitializeFpu.asm
+ Ia32/InitializeFpu.S
+
+[Sources.X64]
+ X64/InitializeFpu.asm
+ X64/InitializeFpu.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ UefiCpuLib
+
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.S b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.S
new file mode 100755
index 0000000000..4972bc2e7f
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.S
@@ -0,0 +1,73 @@
+#------------------------------------------------------------------------------
+#*
+#* Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+#* 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.
+#*
+#*
+#------------------------------------------------------------------------------
+
+#
+# Float control word initial value:
+# all exceptions masked, double-precision, round-to-nearest
+#
+ASM_PFX(mFpuControlWord): .word 0x027F
+#
+# Multimedia-extensions control word:
+# all exceptions masked, round-to-nearest, flush to zero for masked underflow
+#
+ASM_PFX(mMmxControlWord): .long 0x01F80
+
+#
+# Initializes floating point units for requirement of UEFI specification.
+#
+# This function initializes floating-point control word to 0x027F (all exceptions
+# masked,double-precision, round-to-nearest) and multimedia-extensions control word
+# (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+# for masked underflow).
+#
+ASM_GLOBAL ASM_PFX(InitializeFloatingPointUnits)
+ASM_PFX(InitializeFloatingPointUnits):
+
+ pushl %ebx
+
+ #
+ # Initialize floating point units
+ #
+ finit
+ fldcw ASM_PFX(mFpuControlWord)
+
+ #
+ # Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test
+ # whether the processor supports SSE instruction.
+ #
+ movl $1, %eax
+ cpuid
+ btl $25, %edx
+ jnc Done
+
+ #
+ # Set OSFXSR bit 9 in CR4
+ #
+ movl %cr4, %eax
+ or $0x200, %eax
+ movl %eax, %cr4
+
+ #
+ # The processor should support SSE instruction and we can use
+ # ldmxcsr instruction
+ #
+ ldmxcsr ASM_PFX(mMmxControlWord)
+
+Done:
+ popl %ebx
+
+ ret
+
+#END
+
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.asm b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.asm
new file mode 100755
index 0000000000..3c31da98f6
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.asm
@@ -0,0 +1,79 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2009, Intel Corporation. All rights reserved.
+;* 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.
+;*
+;*
+;------------------------------------------------------------------------------
+
+
+ .686
+ .model flat,C
+ .const
+;
+; Float control word initial value:
+; all exceptions masked, double-precision, round-to-nearest
+;
+mFpuControlWord DW 027Fh
+;
+; Multimedia-extensions control word:
+; all exceptions masked, round-to-nearest, flush to zero for masked underflow
+;
+mMmxControlWord DD 01F80h
+
+ .xmm
+ .code
+
+;
+; Initializes floating point units for requirement of UEFI specification.
+;
+; This function initializes floating-point control word to 0x027F (all exceptions
+; masked,double-precision, round-to-nearest) and multimedia-extensions control word
+; (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+; for masked underflow).
+;
+InitializeFloatingPointUnits PROC PUBLIC
+
+ push ebx
+
+ ;
+ ; Initialize floating point units
+ ;
+ finit
+ fldcw mFpuControlWord
+
+ ;
+ ; Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test
+ ; whether the processor supports SSE instruction.
+ ;
+ mov eax, 1
+ cpuid
+ bt edx, 25
+ jnc Done
+
+ ;
+ ; Set OSFXSR bit 9 in CR4
+ ;
+ mov eax, cr4
+ or eax, BIT9
+ mov cr4, eax
+
+ ;
+ ; The processor should support SSE instruction and we can use
+ ; ldmxcsr instruction
+ ;
+ ldmxcsr mMmxControlWord
+Done:
+ pop ebx
+
+ ret
+
+InitializeFloatingPointUnits ENDP
+
+END
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.S b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.S
new file mode 100755
index 0000000000..64750afb85
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.S
@@ -0,0 +1,57 @@
+#------------------------------------------------------------------------------
+#*
+#* Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+#* 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.
+#*
+#*
+#------------------------------------------------------------------------------
+
+#
+# Initializes floating point units for requirement of UEFI specification.
+#
+# This function initializes floating-point control word to 0x027F (all exceptions
+# masked,double-precision, round-to-nearest) and multimedia-extensions control word
+# (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+# for masked underflow).
+#
+ASM_GLOBAL ASM_PFX(InitializeFloatingPointUnits)
+ASM_PFX(InitializeFloatingPointUnits):
+
+ #
+ # Initialize floating point units
+ #
+ finit
+
+ #
+ # Float control word initial value:
+ # all exceptions masked, double-precision, round-to-nearest
+ #
+ pushq $0x027F
+ lea (%rsp), %rax
+ fldcw (%rax)
+ popq %rax
+
+ #
+ # Set OSFXSR bit 9 in CR4
+ #
+ movq %cr4, %rax
+ or $0x200, %rax
+ movq %rax, %cr4
+
+ #
+ # Multimedia-extensions control word:
+ # all exceptions masked, round-to-nearest, flush to zero for masked underflow
+ #
+ pushq $0x01F80
+ lea (%rsp), %rax
+ ldmxcsr (%rax)
+ popq %rax
+
+ ret
+
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.asm b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.asm
new file mode 100755
index 0000000000..0a036b6ae3
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.asm
@@ -0,0 +1,62 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2009, Intel Corporation. All rights reserved.
+;* 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.
+;*
+;*
+;------------------------------------------------------------------------------
+
+
+.const
+;
+; Float control word initial value:
+; all exceptions masked, double-precision, round-to-nearest
+;
+mFpuControlWord DW 027Fh
+;
+; Multimedia-extensions control word:
+; all exceptions masked, round-to-nearest, flush to zero for masked underflow
+;
+mMmxControlWord DD 01F80h
+
+.code
+
+
+;
+; Initializes floating point units for requirement of UEFI specification.
+;
+; This function initializes floating-point control word to 0x027F (all exceptions
+; masked,double-precision, round-to-nearest) and multimedia-extensions control word
+; (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+; for masked underflow).
+;
+InitializeFloatingPointUnits PROC PUBLIC
+
+ ;
+ ; Initialize floating point units
+ ;
+ ; The following opcodes stand for instruction 'finit'
+ ; to be supported by some 64-bit assemblers
+ ;
+ DB 9Bh, 0DBh, 0E3h
+ fldcw mFpuControlWord
+
+ ;
+ ; Set OSFXSR bit 9 in CR4
+ ;
+ mov rax, cr4
+ or rax, BIT9
+ mov cr4, rax
+
+ ldmxcsr mMmxControlWord
+
+ ret
+InitializeFloatingPointUnits ENDP
+
+END
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/CloverEFI/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
new file mode 100755
index 0000000000..77c24deed0
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
@@ -0,0 +1,754 @@
+/** @file
+ Local APIC Library.
+
+ This local APIC library instance supports xAPIC mode only.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+//
+// Library internal functions
+//
+
+/**
+ Read from a local APIC register.
+
+ This function reads from a local APIC register either in xAPIC or x2APIC mode.
+ It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
+ accessed using multiple 32-bit loads or stores, so this function only performs
+ 32-bit read.
+
+ @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
+ It must be 16-byte aligned.
+
+ @return 32-bit Value read from the register.
+**/
+UINT32
+EFIAPI
+ReadLocalApicReg (
+ IN UINTN MmioOffset
+ )
+{
+ ASSERT ((MmioOffset & 0xf) == 0);
+ ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);
+
+ return MmioRead32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset);
+}
+
+/**
+ Write to a local APIC register.
+
+ This function writes to a local APIC register either in xAPIC or x2APIC mode.
+ It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
+ accessed using multiple 32-bit loads or stores, so this function only performs
+ 32-bit write.
+
+ if the register index is invalid or unsupported in current APIC mode, then ASSERT.
+
+ @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
+ It must be 16-byte aligned.
+ @param Value Value to be written to the register.
+**/
+VOID
+EFIAPI
+WriteLocalApicReg (
+ IN UINTN MmioOffset,
+ IN UINT32 Value
+ )
+{
+ ASSERT ((MmioOffset & 0xf) == 0);
+ ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);
+
+ MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset, Value);
+}
+
+/**
+ Send an IPI by writing to ICR.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param IcrLow 32-bit value to be written to the low half of ICR.
+ @param ApicId APIC ID of the target processor if this IPI is targeted for a specific processor.
+**/
+VOID
+SendIpi (
+ IN UINT32 IcrLow,
+ IN UINT32 ApicId
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLowReg;
+
+ ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);
+ ASSERT (ApicId <= 0xff);
+
+ //
+ // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.
+ //
+ WriteLocalApicReg (XAPIC_ICR_HIGH_OFFSET, ApicId << 24);
+ WriteLocalApicReg (XAPIC_ICR_LOW_OFFSET, IcrLow);
+ do {
+ IcrLowReg.Uint32 = ReadLocalApicReg (XAPIC_ICR_LOW_OFFSET);
+ } while (IcrLowReg.Bits.DeliveryStatus != 0);
+}
+
+//
+// Library API implementation functions
+//
+
+/**
+ Get the current local APIC mode.
+
+ If local APIC is disabled, then ASSERT.
+
+ @retval LOCAL_APIC_MODE_XAPIC current APIC mode is xAPIC.
+ @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.
+**/
+UINTN
+EFIAPI
+GetApicMode (
+ VOID
+ )
+{
+ DEBUG_CODE (
+ {
+ MSR_IA32_APIC_BASE ApicBaseMsr;
+
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
+ //
+ // Local APIC should have been enabled
+ //
+ ASSERT (ApicBaseMsr.Bits.En != 0);
+ ASSERT (ApicBaseMsr.Bits.Extd == 0);
+ }
+ );
+ return LOCAL_APIC_MODE_XAPIC;
+}
+
+/**
+ Set the current local APIC mode.
+
+ If the specified local APIC mode is not valid, then ASSERT.
+ If the specified local APIC mode can't be set as current, then ASSERT.
+
+ @param ApicMode APIC mode to be set.
+**/
+VOID
+EFIAPI
+SetApicMode (
+ IN UINTN ApicMode
+ )
+{
+ ASSERT (ApicMode == LOCAL_APIC_MODE_XAPIC);
+ ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);
+}
+
+/**
+ Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.
+
+ In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID.
+ In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case,
+ the 32-bit local APIC ID is returned as initial APIC ID.
+
+ @return 32-bit initial local APIC ID of the executing processor.
+**/
+UINT32
+EFIAPI
+GetInitialApicId (
+ VOID
+ )
+{
+ UINT32 RegEbx;
+
+ ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);
+
+ AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+ return RegEbx >> 24;
+}
+
+/**
+ Get the local APIC ID of the executing processor.
+
+ @return 32-bit local APIC ID of the executing processor.
+**/
+UINT32
+EFIAPI
+GetApicId (
+ VOID
+ )
+{
+ UINT32 ApicId;
+
+ ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);
+
+ ApicId = ReadLocalApicReg (XAPIC_ID_OFFSET);
+ ApicId >>= 24;
+ return ApicId;
+}
+
+/**
+ Get the value of the local APIC version register.
+
+ @return the value of the local APIC version register.
+**/
+UINT32
+EFIAPI
+GetApicVersion (
+ VOID
+ )
+{
+ return ReadLocalApicReg (XAPIC_VERSION_OFFSET);
+}
+
+/**
+ Send a Fixed IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId The local APIC ID of the target processor.
+ @param Vector The vector number of the interrupt being sent.
+**/
+VOID
+EFIAPI
+SendFixedIpi (
+ IN UINT32 ApicId,
+ IN UINT8 Vector
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.Vector = Vector;
+ SendIpi (IcrLow.Uint32, ApicId);
+}
+
+/**
+ Send a Fixed IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+
+ @param Vector The vector number of the interrupt being sent.
+**/
+VOID
+EFIAPI
+SendFixedIpiAllExcludingSelf (
+ IN UINT8 Vector
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
+ IcrLow.Bits.Vector = Vector;
+ SendIpi (IcrLow.Uint32, 0);
+}
+
+/**
+ Send a SMI IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+**/
+VOID
+EFIAPI
+SendSmiIpi (
+ IN UINT32 ApicId
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;
+ IcrLow.Bits.Level = 1;
+ SendIpi (IcrLow.Uint32, ApicId);
+}
+
+/**
+ Send a SMI IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+**/
+VOID
+EFIAPI
+SendSmiIpiAllExcludingSelf (
+ VOID
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
+ SendIpi (IcrLow.Uint32, 0);
+}
+
+/**
+ Send an INIT IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+**/
+VOID
+EFIAPI
+SendInitIpi (
+ IN UINT32 ApicId
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;
+ IcrLow.Bits.Level = 1;
+ SendIpi (IcrLow.Uint32, ApicId);
+}
+
+/**
+ Send an INIT IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+**/
+VOID
+EFIAPI
+SendInitIpiAllExcludingSelf (
+ VOID
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
+ SendIpi (IcrLow.Uint32, 0);
+}
+
+/**
+ Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ if StartupRoutine >= 1M, then ASSERT.
+ if StartupRoutine is not multiple of 4K, then ASSERT.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+ @param StartupRoutine Points to a start-up routine which is below 1M physical
+ address and 4K aligned.
+**/
+VOID
+EFIAPI
+SendInitSipiSipi (
+ IN UINT32 ApicId,
+ IN UINT32 StartupRoutine
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ ASSERT (StartupRoutine < 0x100000);
+ ASSERT ((StartupRoutine & 0xfff) == 0);
+
+ SendInitIpi (ApicId);
+ MicroSecondDelay (10);
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.Vector = (StartupRoutine >> 12);
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
+ IcrLow.Bits.Level = 1;
+ SendIpi (IcrLow.Uint32, ApicId);
+ MicroSecondDelay (200);
+ SendIpi (IcrLow.Uint32, ApicId);
+}
+
+/**
+ Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+
+ if StartupRoutine >= 1M, then ASSERT.
+ if StartupRoutine is not multiple of 4K, then ASSERT.
+
+ @param StartupRoutine Points to a start-up routine which is below 1M physical
+ address and 4K aligned.
+**/
+VOID
+EFIAPI
+SendInitSipiSipiAllExcludingSelf (
+ IN UINT32 StartupRoutine
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ ASSERT (StartupRoutine < 0x100000);
+ ASSERT ((StartupRoutine & 0xfff) == 0);
+
+ SendInitIpiAllExcludingSelf ();
+ MicroSecondDelay (10);
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.Vector = (StartupRoutine >> 12);
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
+ SendIpi (IcrLow.Uint32, 0);
+ MicroSecondDelay (200);
+ SendIpi (IcrLow.Uint32, 0);
+}
+
+/**
+ Programming Virtual Wire Mode.
+
+ This function programs the local APIC for virtual wire mode following
+ the example described in chapter A.3 of the MP 1.4 spec.
+
+ IOxAPIC is not involved in this type of virtual wire mode.
+**/
+VOID
+EFIAPI
+ProgramVirtualWireMode (
+ VOID
+ )
+{
+ LOCAL_APIC_SVR Svr;
+ LOCAL_APIC_LVT_LINT Lint;
+
+ //
+ // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.
+ //
+ Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);
+ Svr.Bits.SpuriousVector = 0xf;
+ Svr.Bits.SoftwareEnable = 1;
+ WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
+
+ //
+ // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
+ //
+ Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
+ Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;
+ Lint.Bits.InputPinPolarity = 0;
+ Lint.Bits.TriggerMode = 0;
+ Lint.Bits.Mask = 0;
+ WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, Lint.Uint32);
+
+ //
+ // Program the LINT0 vector entry as NMI. Not masked, edge, active high.
+ //
+ Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
+ Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;
+ Lint.Bits.InputPinPolarity = 0;
+ Lint.Bits.TriggerMode = 0;
+ Lint.Bits.Mask = 0;
+ WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32);
+}
+
+/**
+ Disable LINT0 & LINT1 interrupts.
+
+ This function sets the mask flag in the LVT LINT0 & LINT1 registers.
+**/
+VOID
+EFIAPI
+DisableLvtInterrupts (
+ VOID
+ )
+{
+ LOCAL_APIC_LVT_LINT LvtLint;
+
+ LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
+ LvtLint.Bits.Mask = 1;
+ WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, LvtLint.Uint32);
+
+ LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
+ LvtLint.Bits.Mask = 1;
+ WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, LvtLint.Uint32);
+}
+
+/**
+ Read the initial count value from the init-count register.
+
+ @return The initial count value read from the init-count register.
+**/
+UINT32
+EFIAPI
+GetApicTimerInitCount (
+ VOID
+ )
+{
+ return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET);
+}
+
+/**
+ Read the current count value from the current-count register.
+
+ @return The current count value read from the current-count register.
+**/
+UINT32
+EFIAPI
+GetApicTimerCurrentCount (
+ VOID
+ )
+{
+ return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET);
+}
+
+/**
+ Initialize the local APIC timer.
+
+ The local APIC timer is initialized and enabled.
+
+ @param DivideValue The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
+ If it is 0, then use the current divide value in the DCR.
+ @param InitCount The initial count value.
+ @param PeriodicMode If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
+ @param Vector The timer interrupt vector number.
+**/
+VOID
+EFIAPI
+InitializeApicTimer (
+ IN UINTN DivideValue,
+ IN UINT32 InitCount,
+ IN BOOLEAN PeriodicMode,
+ IN UINT8 Vector
+ )
+{
+ LOCAL_APIC_SVR Svr;
+ LOCAL_APIC_DCR Dcr;
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+ UINT32 Divisor;
+
+ //
+ // Ensure local APIC is in software-enabled state.
+ //
+ Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);
+ Svr.Bits.SoftwareEnable = 1;
+ WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
+
+ //
+ // Program init-count register.
+ //
+ WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET, InitCount);
+
+ if (DivideValue != 0) {
+ ASSERT (DivideValue <= 128);
+ ASSERT (DivideValue == GetPowerOfTwo32((UINT32)DivideValue));
+ Divisor = (UINT32)((HighBitSet32 ((UINT32)DivideValue) - 1) & 0x7);
+
+ Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
+ Dcr.Bits.DivideValue1 = (Divisor & 0x3);
+ Dcr.Bits.DivideValue2 = (Divisor >> 2);
+ WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET, Dcr.Uint32);
+ }
+
+ //
+ // Enable APIC timer interrupt with specified timer mode.
+ //
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ if (PeriodicMode) {
+ LvtTimer.Bits.TimerMode = 1;
+ } else {
+ LvtTimer.Bits.TimerMode = 0;
+ }
+ LvtTimer.Bits.Mask = 0;
+ LvtTimer.Bits.Vector = Vector;
+ WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
+}
+
+/**
+ Get the state of the local APIC timer.
+
+ @param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
+ @param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
+ @param Vector Return the timer interrupt vector number.
+**/
+VOID
+EFIAPI
+GetApicTimerState (
+ OUT UINTN *DivideValue OPTIONAL,
+ OUT BOOLEAN *PeriodicMode OPTIONAL,
+ OUT UINT8 *Vector OPTIONAL
+ )
+{
+ UINT32 Divisor;
+ LOCAL_APIC_DCR Dcr;
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+
+ if (DivideValue != NULL) {
+ Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
+ Divisor = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);
+ Divisor = (Divisor + 1) & 0x7;
+ *DivideValue = ((UINTN)1) << Divisor;
+ }
+
+ if (PeriodicMode != NULL || Vector != NULL) {
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ if (PeriodicMode != NULL) {
+ if (LvtTimer.Bits.TimerMode == 1) {
+ *PeriodicMode = TRUE;
+ } else {
+ *PeriodicMode = FALSE;
+ }
+ }
+ if (Vector != NULL) {
+ *Vector = (UINT8) LvtTimer.Bits.Vector;
+ }
+ }
+}
+
+/**
+ Enable the local APIC timer interrupt.
+**/
+VOID
+EFIAPI
+EnableApicTimerInterrupt (
+ VOID
+ )
+{
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ LvtTimer.Bits.Mask = 0;
+ WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
+}
+
+/**
+ Disable the local APIC timer interrupt.
+**/
+VOID
+EFIAPI
+DisableApicTimerInterrupt (
+ VOID
+ )
+{
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ LvtTimer.Bits.Mask = 1;
+ WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
+}
+
+/**
+ Get the local APIC timer interrupt state.
+
+ @retval TRUE The local APIC timer interrupt is enabled.
+ @retval FALSE The local APIC timer interrupt is disabled.
+**/
+BOOLEAN
+EFIAPI
+GetApicTimerInterruptState (
+ VOID
+ )
+{
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ return (BOOLEAN)(LvtTimer.Bits.Mask == 0);
+}
+
+/**
+ Send EOI to the local APIC.
+**/
+VOID
+EFIAPI
+SendApicEoi (
+ VOID
+ )
+{
+ WriteLocalApicReg (XAPIC_EOI_OFFSET, 0);
+}
+
+/**
+ Get the 32-bit address that a device should use to send a Message Signaled
+ Interrupt (MSI) to the Local APIC of the currently executing processor.
+
+ @return 32-bit address used to send an MSI to the Local APIC.
+**/
+UINT32
+EFIAPI
+GetApicMsiAddress (
+ VOID
+ )
+{
+ LOCAL_APIC_MSI_ADDRESS MsiAddress;
+
+ //
+ // Return address for an MSI interrupt to be delivered only to the APIC ID
+ // of the currently executing processor.
+ //
+ MsiAddress.Uint32 = 0;
+ MsiAddress.Bits.BaseAddress = 0xFEE;
+ MsiAddress.Bits.DestinationId = GetApicId ();
+ return MsiAddress.Uint32;
+}
+
+/**
+ Get the 64-bit data value that a device should use to send a Message Signaled
+ Interrupt (MSI) to the Local APIC of the currently executing processor.
+
+ If Vector is not in range 0x10..0xFE, then ASSERT().
+ If DeliveryMode is not supported, then ASSERT().
+
+ @param Vector The 8-bit interrupt vector associated with the MSI.
+ Must be in the range 0x10..0xFE
+ @param DeliveryMode A 3-bit value that specifies how the recept of the MSI
+ is handled. The only supported values are:
+ 0: LOCAL_APIC_DELIVERY_MODE_FIXED
+ 1: LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY
+ 2: LOCAL_APIC_DELIVERY_MODE_SMI
+ 4: LOCAL_APIC_DELIVERY_MODE_NMI
+ 5: LOCAL_APIC_DELIVERY_MODE_INIT
+ 7: LOCAL_APIC_DELIVERY_MODE_EXTINT
+
+ @param LevelTriggered TRUE specifies a level triggered interrupt.
+ FALSE specifies an edge triggered interrupt.
+ @param AssertionLevel Ignored if LevelTriggered is FALSE.
+ TRUE specifies a level triggered interrupt that active
+ when the interrupt line is asserted.
+ FALSE specifies a level triggered interrupt that active
+ when the interrupt line is deasserted.
+
+ @return 64-bit data value used to send an MSI to the Local APIC.
+**/
+UINT64
+EFIAPI
+GetApicMsiValue (
+ IN UINT8 Vector,
+ IN UINTN DeliveryMode,
+ IN BOOLEAN LevelTriggered,
+ IN BOOLEAN AssertionLevel
+ )
+{
+ LOCAL_APIC_MSI_DATA MsiData;
+
+ ASSERT (Vector >= 0x10 && Vector <= 0xFE);
+ ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3);
+
+ MsiData.Uint64 = 0;
+ MsiData.Bits.Vector = Vector;
+ MsiData.Bits.DeliveryMode = (UINT32)DeliveryMode;
+ if (LevelTriggered) {
+ MsiData.Bits.TriggerMode = 1;
+ if (AssertionLevel) {
+ MsiData.Bits.Level = 1;
+ }
+ }
+ return MsiData.Uint64;
+}
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf b/CloverEFI/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
new file mode 100755
index 0000000000..a86789b5f4
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for CPU Local APIC Library.
+#
+# This library instance supports xAPIC mode only.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseXApicLib
+ FILE_GUID = D87CA0A8-1AC2-439b-90F8-EF4A2AC88DAF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LocalApicLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ BaseXApicLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ TimerLib
+ IoLib
+
+[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
new file mode 100755
index 0000000000..62201cd240
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
@@ -0,0 +1,837 @@
+/** @file
+ Local APIC Library.
+
+ This local APIC library instance supports x2APIC capable processors
+ which have xAPIC and x2APIC modes.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+//
+// Library internal functions
+//
+
+/**
+ Read from a local APIC register.
+
+ This function reads from a local APIC register either in xAPIC or x2APIC mode.
+ It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
+ accessed using multiple 32-bit loads or stores, so this function only performs
+ 32-bit read.
+
+ @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
+ It must be 16-byte aligned.
+
+ @return 32-bit Value read from the register.
+**/
+UINT32
+EFIAPI
+ReadLocalApicReg (
+ IN UINTN MmioOffset
+ )
+{
+ UINT32 MsrIndex;
+
+ ASSERT ((MmioOffset & 0xf) == 0);
+
+ if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
+ return MmioRead32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset);
+ } else {
+ //
+ // DFR is not supported in x2APIC mode.
+ //
+ ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET);
+ //
+ // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It
+ // is not supported in this function for simplicity.
+ //
+ ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET);
+
+ MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS;
+ return AsmReadMsr32 (MsrIndex);
+ }
+}
+
+/**
+ Write to a local APIC register.
+
+ This function writes to a local APIC register either in xAPIC or x2APIC mode.
+ It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
+ accessed using multiple 32-bit loads or stores, so this function only performs
+ 32-bit write.
+
+ if the register index is invalid or unsupported in current APIC mode, then ASSERT.
+
+ @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
+ It must be 16-byte aligned.
+ @param Value Value to be written to the register.
+**/
+VOID
+EFIAPI
+WriteLocalApicReg (
+ IN UINTN MmioOffset,
+ IN UINT32 Value
+ )
+{
+ UINT32 MsrIndex;
+
+ ASSERT ((MmioOffset & 0xf) == 0);
+
+ if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
+ MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset, Value);
+ } else {
+ //
+ // DFR is not supported in x2APIC mode.
+ //
+ ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET);
+ //
+ // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It
+ // is not supported in this function for simplicity.
+ //
+ ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET);
+ ASSERT (MmioOffset != XAPIC_ICR_LOW_OFFSET);
+
+ MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS;
+ //
+ // The serializing semantics of WRMSR are relaxed when writing to the APIC registers.
+ // Use memory fence here to force the serializing semantics to be consisent with xAPIC mode.
+ //
+ MemoryFence ();
+ AsmWriteMsr32 (MsrIndex, Value);
+ }
+}
+
+/**
+ Send an IPI by writing to ICR.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param IcrLow 32-bit value to be written to the low half of ICR.
+ @param ApicId APIC ID of the target processor if this IPI is targeted for a specific processor.
+**/
+VOID
+SendIpi (
+ IN UINT32 IcrLow,
+ IN UINT32 ApicId
+ )
+{
+ UINT64 MsrValue;
+ LOCAL_APIC_ICR_LOW IcrLowReg;
+
+ if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
+ ASSERT (ApicId <= 0xff);
+
+ //
+ // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.
+ //
+ MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_HIGH_OFFSET, ApicId << 24);
+ MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_LOW_OFFSET, IcrLow);
+ do {
+ IcrLowReg.Uint32 = MmioRead32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_LOW_OFFSET);
+ } while (IcrLowReg.Bits.DeliveryStatus != 0);
+ } else {
+ //
+ // For x2APIC, A single MSR write to the Interrupt Command Register is required for dispatching an
+ // interrupt in x2APIC mode.
+ //
+ MsrValue = LShiftU64 ((UINT64) ApicId, 32) | IcrLow;
+ AsmWriteMsr64 (X2APIC_MSR_ICR_ADDRESS, MsrValue);
+ }
+}
+
+//
+// Library API implementation functions
+//
+
+/**
+ Get the current local APIC mode.
+
+ If local APIC is disabled, then ASSERT.
+
+ @retval LOCAL_APIC_MODE_XAPIC current APIC mode is xAPIC.
+ @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.
+**/
+UINTN
+EFIAPI
+GetApicMode (
+ VOID
+ )
+{
+ MSR_IA32_APIC_BASE ApicBaseMsr;
+
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
+ //
+ // Local APIC should have been enabled
+ //
+ ASSERT (ApicBaseMsr.Bits.En != 0);
+ if (ApicBaseMsr.Bits.Extd != 0) {
+ return LOCAL_APIC_MODE_X2APIC;
+ } else {
+ return LOCAL_APIC_MODE_XAPIC;
+ }
+}
+
+/**
+ Set the current local APIC mode.
+
+ If the specified local APIC mode is not valid, then ASSERT.
+ If the specified local APIC mode can't be set as current, then ASSERT.
+
+ @param ApicMode APIC mode to be set.
+**/
+VOID
+EFIAPI
+SetApicMode (
+ IN UINTN ApicMode
+ )
+{
+ UINTN CurrentMode;
+ MSR_IA32_APIC_BASE ApicBaseMsr;
+
+ CurrentMode = GetApicMode ();
+ if (CurrentMode == LOCAL_APIC_MODE_XAPIC) {
+ switch (ApicMode) {
+ case LOCAL_APIC_MODE_XAPIC:
+ break;
+ case LOCAL_APIC_MODE_X2APIC:
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
+ ApicBaseMsr.Bits.Extd = 1;
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ } else {
+ switch (ApicMode) {
+ case LOCAL_APIC_MODE_XAPIC:
+ //
+ // Transition from x2APIC mode to xAPIC mode is a two-step process:
+ // x2APIC -> Local APIC disabled -> xAPIC
+ //
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
+ ApicBaseMsr.Bits.Extd = 0;
+ ApicBaseMsr.Bits.En = 0;
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
+ ApicBaseMsr.Bits.En = 1;
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
+ break;
+ case LOCAL_APIC_MODE_X2APIC:
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ }
+}
+
+/**
+ Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.
+
+ In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID.
+ In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case,
+ the 32-bit local APIC ID is returned as initial APIC ID.
+
+ @return 32-bit initial local APIC ID of the executing processor.
+**/
+UINT32
+EFIAPI
+GetInitialApicId (
+ VOID
+ )
+{
+ UINT32 RegEbx;
+
+ if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
+ AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+ return RegEbx >> 24;
+ } else {
+ return GetApicId ();
+ }
+}
+
+/**
+ Get the local APIC ID of the executing processor.
+
+ @return 32-bit local APIC ID of the executing processor.
+**/
+UINT32
+EFIAPI
+GetApicId (
+ VOID
+ )
+{
+ UINT32 ApicId;
+
+ ApicId = ReadLocalApicReg (XAPIC_ID_OFFSET);
+ if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
+ ApicId >>= 24;
+ }
+ return ApicId;
+}
+
+/**
+ Get the value of the local APIC version register.
+
+ @return the value of the local APIC version register.
+**/
+UINT32
+EFIAPI
+GetApicVersion (
+ VOID
+ )
+{
+ return ReadLocalApicReg (XAPIC_VERSION_OFFSET);
+}
+
+/**
+ Send a Fixed IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId The local APIC ID of the target processor.
+ @param Vector The vector number of the interrupt being sent.
+**/
+VOID
+EFIAPI
+SendFixedIpi (
+ IN UINT32 ApicId,
+ IN UINT8 Vector
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.Vector = Vector;
+ SendIpi (IcrLow.Uint32, ApicId);
+}
+
+/**
+ Send a Fixed IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+
+ @param Vector The vector number of the interrupt being sent.
+**/
+VOID
+EFIAPI
+SendFixedIpiAllExcludingSelf (
+ IN UINT8 Vector
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
+ IcrLow.Bits.Vector = Vector;
+ SendIpi (IcrLow.Uint32, 0);
+}
+
+/**
+ Send a SMI IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+**/
+VOID
+EFIAPI
+SendSmiIpi (
+ IN UINT32 ApicId
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;
+ IcrLow.Bits.Level = 1;
+ SendIpi (IcrLow.Uint32, ApicId);
+}
+
+/**
+ Send a SMI IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+**/
+VOID
+EFIAPI
+SendSmiIpiAllExcludingSelf (
+ VOID
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
+ SendIpi (IcrLow.Uint32, 0);
+}
+
+/**
+ Send an INIT IPI to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+**/
+VOID
+EFIAPI
+SendInitIpi (
+ IN UINT32 ApicId
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;
+ IcrLow.Bits.Level = 1;
+ SendIpi (IcrLow.Uint32, ApicId);
+}
+
+/**
+ Send an INIT IPI to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+**/
+VOID
+EFIAPI
+SendInitIpiAllExcludingSelf (
+ VOID
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
+ SendIpi (IcrLow.Uint32, 0);
+}
+
+/**
+ Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.
+
+ This function returns after the IPI has been accepted by the target processor.
+
+ if StartupRoutine >= 1M, then ASSERT.
+ if StartupRoutine is not multiple of 4K, then ASSERT.
+
+ @param ApicId Specify the local APIC ID of the target processor.
+ @param StartupRoutine Points to a start-up routine which is below 1M physical
+ address and 4K aligned.
+**/
+VOID
+EFIAPI
+SendInitSipiSipi (
+ IN UINT32 ApicId,
+ IN UINT32 StartupRoutine
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ ASSERT (StartupRoutine < 0x100000);
+ ASSERT ((StartupRoutine & 0xfff) == 0);
+
+ SendInitIpi (ApicId);
+ MicroSecondDelay (10);
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.Vector = (StartupRoutine >> 12);
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
+ IcrLow.Bits.Level = 1;
+ SendIpi (IcrLow.Uint32, ApicId);
+ MicroSecondDelay (200);
+ SendIpi (IcrLow.Uint32, ApicId);
+}
+
+/**
+ Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.
+
+ This function returns after the IPI has been accepted by the target processors.
+
+ if StartupRoutine >= 1M, then ASSERT.
+ if StartupRoutine is not multiple of 4K, then ASSERT.
+
+ @param StartupRoutine Points to a start-up routine which is below 1M physical
+ address and 4K aligned.
+**/
+VOID
+EFIAPI
+SendInitSipiSipiAllExcludingSelf (
+ IN UINT32 StartupRoutine
+ )
+{
+ LOCAL_APIC_ICR_LOW IcrLow;
+
+ ASSERT (StartupRoutine < 0x100000);
+ ASSERT ((StartupRoutine & 0xfff) == 0);
+
+ SendInitIpiAllExcludingSelf ();
+ MicroSecondDelay (10);
+ IcrLow.Uint32 = 0;
+ IcrLow.Bits.Vector = (StartupRoutine >> 12);
+ IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
+ IcrLow.Bits.Level = 1;
+ IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
+ SendIpi (IcrLow.Uint32, 0);
+ MicroSecondDelay (200);
+ SendIpi (IcrLow.Uint32, 0);
+}
+
+/**
+ Programming Virtual Wire Mode.
+
+ This function programs the local APIC for virtual wire mode following
+ the example described in chapter A.3 of the MP 1.4 spec.
+
+ IOxAPIC is not involved in this type of virtual wire mode.
+**/
+VOID
+EFIAPI
+ProgramVirtualWireMode (
+ VOID
+ )
+{
+ LOCAL_APIC_SVR Svr;
+ LOCAL_APIC_LVT_LINT Lint;
+
+ //
+ // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.
+ //
+ Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);
+ Svr.Bits.SpuriousVector = 0xf;
+ Svr.Bits.SoftwareEnable = 1;
+ WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
+
+ //
+ // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
+ //
+ Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
+ Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;
+ Lint.Bits.InputPinPolarity = 0;
+ Lint.Bits.TriggerMode = 0;
+ Lint.Bits.Mask = 0;
+ WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, Lint.Uint32);
+
+ //
+ // Program the LINT0 vector entry as NMI. Not masked, edge, active high.
+ //
+ Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
+ Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;
+ Lint.Bits.InputPinPolarity = 0;
+ Lint.Bits.TriggerMode = 0;
+ Lint.Bits.Mask = 0;
+ WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32);
+}
+
+/**
+ Disable LINT0 & LINT1 interrupts.
+
+ This function sets the mask flag in the LVT LINT0 & LINT1 registers.
+**/
+VOID
+EFIAPI
+DisableLvtInterrupts (
+ VOID
+ )
+{
+ LOCAL_APIC_LVT_LINT LvtLint;
+
+ LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
+ LvtLint.Bits.Mask = 1;
+ WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, LvtLint.Uint32);
+
+ LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
+ LvtLint.Bits.Mask = 1;
+ WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, LvtLint.Uint32);
+}
+
+/**
+ Read the initial count value from the init-count register.
+
+ @return The initial count value read from the init-count register.
+**/
+UINT32
+EFIAPI
+GetApicTimerInitCount (
+ VOID
+ )
+{
+ return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET);
+}
+
+/**
+ Read the current count value from the current-count register.
+
+ @return The current count value read from the current-count register.
+**/
+UINT32
+EFIAPI
+GetApicTimerCurrentCount (
+ VOID
+ )
+{
+ return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET);
+}
+
+/**
+ Initialize the local APIC timer.
+
+ The local APIC timer is initialized and enabled.
+
+ @param DivideValue The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
+ If it is 0, then use the current divide value in the DCR.
+ @param InitCount The initial count value.
+ @param PeriodicMode If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
+ @param Vector The timer interrupt vector number.
+**/
+VOID
+EFIAPI
+InitializeApicTimer (
+ IN UINTN DivideValue,
+ IN UINT32 InitCount,
+ IN BOOLEAN PeriodicMode,
+ IN UINT8 Vector
+ )
+{
+ LOCAL_APIC_SVR Svr;
+ LOCAL_APIC_DCR Dcr;
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+ UINT32 Divisor;
+
+ //
+ // Ensure local APIC is in software-enabled state.
+ //
+ Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);
+ Svr.Bits.SoftwareEnable = 1;
+ WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
+
+ //
+ // Program init-count register.
+ //
+ WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET, InitCount);
+
+ if (DivideValue != 0) {
+ ASSERT (DivideValue <= 128);
+ ASSERT (DivideValue == GetPowerOfTwo32((UINT32)DivideValue));
+ Divisor = (UINT32)((HighBitSet32 ((UINT32)DivideValue) - 1) & 0x7);
+
+ Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
+ Dcr.Bits.DivideValue1 = (Divisor & 0x3);
+ Dcr.Bits.DivideValue2 = (Divisor >> 2);
+ WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET, Dcr.Uint32);
+ }
+
+ //
+ // Enable APIC timer interrupt with specified timer mode.
+ //
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ if (PeriodicMode) {
+ LvtTimer.Bits.TimerMode = 1;
+ } else {
+ LvtTimer.Bits.TimerMode = 0;
+ }
+ LvtTimer.Bits.Mask = 0;
+ LvtTimer.Bits.Vector = Vector;
+ WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
+}
+
+/**
+ Get the state of the local APIC timer.
+
+ @param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
+ @param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
+ @param Vector Return the timer interrupt vector number.
+**/
+VOID
+EFIAPI
+GetApicTimerState (
+ OUT UINTN *DivideValue OPTIONAL,
+ OUT BOOLEAN *PeriodicMode OPTIONAL,
+ OUT UINT8 *Vector OPTIONAL
+ )
+{
+ UINT32 Divisor;
+ LOCAL_APIC_DCR Dcr;
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+
+ if (DivideValue != NULL) {
+ Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
+ Divisor = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);
+ Divisor = (Divisor + 1) & 0x7;
+ *DivideValue = ((UINTN)1) << Divisor;
+ }
+
+ if (PeriodicMode != NULL || Vector != NULL) {
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ if (PeriodicMode != NULL) {
+ if (LvtTimer.Bits.TimerMode == 1) {
+ *PeriodicMode = TRUE;
+ } else {
+ *PeriodicMode = FALSE;
+ }
+ }
+ if (Vector != NULL) {
+ *Vector = (UINT8) LvtTimer.Bits.Vector;
+ }
+ }
+}
+
+/**
+ Enable the local APIC timer interrupt.
+**/
+VOID
+EFIAPI
+EnableApicTimerInterrupt (
+ VOID
+ )
+{
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ LvtTimer.Bits.Mask = 0;
+ WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
+}
+
+/**
+ Disable the local APIC timer interrupt.
+**/
+VOID
+EFIAPI
+DisableApicTimerInterrupt (
+ VOID
+ )
+{
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ LvtTimer.Bits.Mask = 1;
+ WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
+}
+
+/**
+ Get the local APIC timer interrupt state.
+
+ @retval TRUE The local APIC timer interrupt is enabled.
+ @retval FALSE The local APIC timer interrupt is disabled.
+**/
+BOOLEAN
+EFIAPI
+GetApicTimerInterruptState (
+ VOID
+ )
+{
+ LOCAL_APIC_LVT_TIMER LvtTimer;
+
+ LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
+ return (BOOLEAN)(LvtTimer.Bits.Mask == 0);
+}
+
+/**
+ Send EOI to the local APIC.
+**/
+VOID
+EFIAPI
+SendApicEoi (
+ VOID
+ )
+{
+ WriteLocalApicReg (XAPIC_EOI_OFFSET, 0);
+}
+
+/**
+ Get the 32-bit address that a device should use to send a Message Signaled
+ Interrupt (MSI) to the Local APIC of the currently executing processor.
+
+ @return 32-bit address used to send an MSI to the Local APIC.
+**/
+UINT32
+EFIAPI
+GetApicMsiAddress (
+ VOID
+ )
+{
+ LOCAL_APIC_MSI_ADDRESS MsiAddress;
+
+ //
+ // Return address for an MSI interrupt to be delivered only to the APIC ID
+ // of the currently executing processor.
+ //
+ MsiAddress.Uint32 = 0;
+ MsiAddress.Bits.BaseAddress = 0xFEE;
+ MsiAddress.Bits.DestinationId = GetApicId ();
+ return MsiAddress.Uint32;
+}
+
+/**
+ Get the 64-bit data value that a device should use to send a Message Signaled
+ Interrupt (MSI) to the Local APIC of the currently executing processor.
+
+ If Vector is not in range 0x10..0xFE, then ASSERT().
+ If DeliveryMode is not supported, then ASSERT().
+
+ @param Vector The 8-bit interrupt vector associated with the MSI.
+ Must be in the range 0x10..0xFE
+ @param DeliveryMode A 3-bit value that specifies how the recept of the MSI
+ is handled. The only supported values are:
+ 0: LOCAL_APIC_DELIVERY_MODE_FIXED
+ 1: LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY
+ 2: LOCAL_APIC_DELIVERY_MODE_SMI
+ 4: LOCAL_APIC_DELIVERY_MODE_NMI
+ 5: LOCAL_APIC_DELIVERY_MODE_INIT
+ 7: LOCAL_APIC_DELIVERY_MODE_EXTINT
+
+ @param LevelTriggered TRUE specifies a level triggered interrupt.
+ FALSE specifies an edge triggered interrupt.
+ @param AssertionLevel Ignored if LevelTriggered is FALSE.
+ TRUE specifies a level triggered interrupt that active
+ when the interrupt line is asserted.
+ FALSE specifies a level triggered interrupt that active
+ when the interrupt line is deasserted.
+
+ @return 64-bit data value used to send an MSI to the Local APIC.
+**/
+UINT64
+EFIAPI
+GetApicMsiValue (
+ IN UINT8 Vector,
+ IN UINTN DeliveryMode,
+ IN BOOLEAN LevelTriggered,
+ IN BOOLEAN AssertionLevel
+ )
+{
+ LOCAL_APIC_MSI_DATA MsiData;
+
+ ASSERT (Vector >= 0x10 && Vector <= 0xFE);
+ ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3);
+
+ MsiData.Uint64 = 0;
+ MsiData.Bits.Vector = Vector;
+ MsiData.Bits.DeliveryMode = (UINT32)DeliveryMode;
+ if (LevelTriggered) {
+ MsiData.Bits.TriggerMode = 1;
+ if (AssertionLevel) {
+ MsiData.Bits.Level = 1;
+ }
+ }
+ return MsiData.Uint64;
+}
diff --git a/CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf b/CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
new file mode 100755
index 0000000000..9fa2f0950b
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
@@ -0,0 +1,47 @@
+## @file
+# Component description file for CPU Local APIC Library.
+#
+# This library instance supports x2APIC capable processors
+# which have xAPIC and x2APIC modes.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseXApicX2ApicLib
+ FILE_GUID = 967B6E05-F10D-4c10-8BF7-365291CA143F
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LocalApicLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ BaseXApicX2ApicLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ TimerLib
+ IoLib
+
+[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
new file mode 100755
index 0000000000..f8cbcf080d
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
@@ -0,0 +1,173 @@
+/** @file
+ CPU Exception Handler Library common functions.
+
+ Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include "CpuExceptionCommon.h"
+
+//
+// Error code flag indicating whether or not an error code will be
+// pushed on the stack if an exception occurs.
+//
+// 1 means an error code will be pushed, otherwise 0
+//
+CONST UINT32 mErrorCodeFlag = 0x00027d00;
+RESERVED_VECTORS_DATA *mReservedVectors = NULL;
+
+//
+// Define the maximum message length
+//
+#define MAX_DEBUG_MESSAGE_LENGTH 0x100
+
+/**
+ Prints a message to the serial port.
+
+ @param Format Format string for the message to print.
+ @param ... Variable argument list whose contents are accessed
+ based on the format string specified by Format.
+
+**/
+VOID
+EFIAPI
+InternalPrintMessage (
+ IN CONST CHAR8 *Format,
+ ...
+ )
+{
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
+ VA_LIST Marker;
+
+ //
+ // Convert the message to an ASCII String
+ //
+ VA_START (Marker, Format);
+ AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
+ VA_END (Marker);
+
+ //
+ // Send the print string to a Serial Port
+ //
+ SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
+}
+
+/**
+ Find and display image base address and return image base and its entry point.
+
+ @param CurrentEip Current instruction pointer.
+ @param EntryPoint Return module entry point if module header is found.
+
+ @return !0 Image base address.
+ @return 0 Image header cannot be found.
+**/
+UINTN
+FindModuleImageBase (
+ IN UINTN CurrentEip,
+ OUT UINTN *EntryPoint
+ )
+{
+ UINTN Pe32Data;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
+ VOID *PdbPointer;
+
+ //
+ // Find Image Base
+ //
+ Pe32Data = CurrentEip & ~(mImageAlignSize - 1);
+ while (Pe32Data != 0) {
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present, so read the PE header after the DOS image header.
+ //
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
+ //
+ // Make sure PE header address does not overflow and is less than the initial address.
+ //
+ if (((UINTN)Hdr.Pe32 > Pe32Data) && ((UINTN)Hdr.Pe32 < CurrentEip)) {
+ if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
+ //
+ // It's PE image.
+ //
+ InternalPrintMessage ("!!!! Find PE image ");
+ *EntryPoint = (UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff);
+ break;
+ }
+ }
+ } else {
+ //
+ // DOS image header is not present, TE header is at the image base.
+ //
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
+ if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&
+ ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {
+ //
+ // It's TE image, it TE header and Machine type match
+ //
+ InternalPrintMessage ("!!!! Find TE image ");
+ *EntryPoint = (UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
+ break;
+ }
+ }
+
+ //
+ // Not found the image base, check the previous aligned address
+ //
+ Pe32Data -= mImageAlignSize;
+ }
+
+ if (Pe32Data != 0) {
+ PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data);
+ if (PdbPointer != NULL) {
+ InternalPrintMessage ("%a", PdbPointer);
+ } else {
+ InternalPrintMessage ("(No PDB) " );
+ }
+ } else {
+ InternalPrintMessage ("!!!! Can't find image information. !!!!\n");
+ }
+
+ return Pe32Data;
+}
+
+/**
+ Read and save reserved vector information
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+ @param[out] ReservedVector Pointer to reserved vector data buffer.
+ @param[in] VectorCount Vector number to be updated.
+
+ @return EFI_SUCCESS Read and save vector info successfully.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+
+**/
+EFI_STATUS
+ReadAndVerifyVectorInfo (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo,
+ OUT RESERVED_VECTORS_DATA *ReservedVector,
+ IN UINTN VectorCount
+ )
+{
+ while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
+ if (VectorInfo->Attribute > EFI_VECTOR_HANDOFF_HOOK_AFTER) {
+ //
+ // If vector attrubute is invalid
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ if (VectorInfo->VectorNumber < VectorCount) {
+ ReservedVector[VectorInfo->VectorNumber].Attribute = VectorInfo->Attribute;
+ }
+ VectorInfo ++;
+ }
+ return EFI_SUCCESS;
+}
\ No newline at end of file
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
new file mode 100755
index 0000000000..d72ecb6927
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
@@ -0,0 +1,242 @@
+/** @file
+ Common header file for CPU Exception Handler Library.
+
+ Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.
+ 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 _CPU_EXCEPTION_COMMON_H_
+#define _CPU_EXCEPTION_COMMON_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define CPU_EXCEPTION_NUM 32
+#define CPU_INTERRUPT_NUM 256
+#define HOOKAFTER_STUB_SIZE 16
+
+#include "ArchInterruptDefs.h"
+
+//
+// Record exception handler information
+//
+typedef struct {
+ UINTN ExceptionStart;
+ UINTN ExceptionStubHeaderSize;
+ UINTN HookAfterStubHeaderStart;
+} EXCEPTION_HANDLER_TEMPLATE_MAP;
+
+extern CONST UINT32 mErrorCodeFlag;
+extern CONST UINTN mImageAlignSize;
+extern CONST UINTN mDoFarReturnFlag;
+extern RESERVED_VECTORS_DATA *mReservedVectors;
+
+/**
+ Return address map of exception handler template so that C code can generate
+ exception tables.
+
+ @param AddressMap Pointer to a buffer where the address map is returned.
+**/
+VOID
+EFIAPI
+AsmGetTemplateAddressMap (
+ OUT EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
+ );
+
+/**
+ Return address map of exception handler template so that C code can generate
+ exception tables.
+
+ @param IdtEntry Pointer to IDT entry to be updated.
+ @param InterruptHandler IDT handler value.
+
+**/
+VOID
+ArchUpdateIdtEntry (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
+ IN UINTN InterruptHandler
+ );
+
+/**
+ Read IDT handler value from IDT entry.
+
+ @param IdtEntry Pointer to IDT entry to be read.
+
+**/
+UINTN
+ArchGetIdtHandler (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
+ );
+
+/**
+ Prints a message to the serial port.
+
+ @param Format Format string for the message to print.
+ @param ... Variable argument list whose contents are accessed
+ based on the format string specified by Format.
+
+**/
+VOID
+EFIAPI
+InternalPrintMessage (
+ IN CONST CHAR8 *Format,
+ ...
+ );
+
+/**
+ Find and display image base address and return image base and its entry point.
+
+ @param CurrentEip Current instruction pointer.
+ @param EntryPoint Return module entry point if module header is found.
+
+ @return !0 Image base address.
+ @return 0 Image header cannot be found.
+**/
+UINTN
+FindModuleImageBase (
+ IN UINTN CurrentEip,
+ OUT UINTN *EntryPoint
+ );
+
+/**
+ Display CPU information.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+DumpCpuContent (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Internal worker function to initialize exception handler.
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized
+ with default exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+InitializeCpuExceptionHandlersWorker (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ );
+
+/**
+ Registers a function to be called from the processor interrupt handler.
+
+ @param[in] InterruptType Defines which interrupt or exception to hook.
+ @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported,
+ or this function is not supported.
+**/
+EFI_STATUS
+RegisterCpuInterruptHandlerWorker (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+/**
+ Internal worker function to update IDT entries accordling to vector attributes.
+
+ @param[in] IdtTable Pointer to IDT table.
+ @param[in] TemplateMap Pointer to a buffer where the address map is returned.
+ @param[in] IdtEntryCount IDT entries number to be updated.
+
+**/
+VOID
+UpdateIdtTable (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtTable,
+ IN EXCEPTION_HANDLER_TEMPLATE_MAP *TemplateMap,
+ IN UINTN IdtEntryCount
+ );
+
+/**
+ Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param[in] ExceptionType Exception type.
+ @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+
+**/
+VOID
+ArchSaveExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param[in] ExceptionType Exception type.
+ @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+
+**/
+VOID
+ArchRestoreExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Fix up the vector number in the vector code.
+
+ @param[in] VectorBase Base address of the vector handler.
+ @param[in] VectorNum Index of vector.
+ @param[in] HookStub TRUE HookAfterStubHeaderEnd.
+ FALSE HookAfterStubHeaderEnd
+
+**/
+VOID
+EFIAPI
+AsmVectorNumFixup (
+ IN VOID *VectorBase,
+ IN UINT8 VectorNum,
+ IN BOOLEAN HookStub
+ );
+
+/**
+ Read and save reserved vector information
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+ @param[out] ReservedVector Pointer to reserved vector data buffer.
+ @param[in] VectorCount Vector number to be updated.
+
+ @return EFI_SUCCESS Read and save vector info successfully.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+
+**/
+EFI_STATUS
+ReadAndVerifyVectorInfo (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo,
+ OUT RESERVED_VECTORS_DATA *ReservedVector,
+ IN UINTN VectorCount
+ );
+
+#endif
+
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
new file mode 100755
index 0000000000..5873bf021d
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
@@ -0,0 +1,64 @@
+## @file
+# CPU Exception Handler library instance for DXE modules.
+#
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeCpuExceptionHandlerLib
+ MODULE_UNI_FILE = DxeCpuExceptionHandlerLib.uni
+ FILE_GUID = B6E9835A-EDCF-4748-98A8-27D3C722E02D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_CORE DXE_DRIVER UEFI_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.Ia32]
+ Ia32/ExceptionHandlerAsm.asm
+ Ia32/ExceptionHandlerAsm.S |GCC
+ Ia32/ArchExceptionHandler.c
+ Ia32/ArchInterruptDefs.h
+
+[Sources.X64]
+ X64/ExceptionHandlerAsm.asm
+ X64/ExceptionHandlerAsm.S |GCC
+ X64/ArchExceptionHandler.c
+ X64/ArchInterruptDefs.h
+
+[Sources.common]
+ CpuExceptionCommon.h
+ CpuExceptionCommon.c
+ DxeSmmCpuException.c
+ DxeException.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ SerialPortLib
+ PrintLib
+ SynchronizationLib
+ LocalApicLib
+ PeCoffGetEntryPointLib
+ MemoryAllocationLib
+ DebugLib
+
+[Ppis]
+ gEfiVectorHandoffInfoPpiGuid
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.uni b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.uni
new file mode 100755
index 0000000000..7aaaa5b537
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.uni differ
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
new file mode 100755
index 0000000000..f02355ec82
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
@@ -0,0 +1,170 @@
+/** @file
+ CPU exception handler library implemenation for DXE modules.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include
+#include "CpuExceptionCommon.h"
+#include
+#include
+
+CONST UINTN mDoFarReturnFlag = 0;
+
+extern SPIN_LOCK mDisplayMessageSpinLock;
+extern EFI_CPU_INTERRUPT_HANDLER *mExternalInterruptHandler;
+
+/**
+ Initializes all CPU exceptions entries and provides the default exception handlers.
+
+ Caller should try to get an array of interrupt and/or exception vectors that are in use and need to
+ persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.
+ If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.
+ If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized
+ with default exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuExceptionHandlers (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ )
+{
+ return InitializeCpuExceptionHandlersWorker (VectorInfo);
+}
+
+/**
+ Initializes all CPU interrupt/exceptions entries and provides the default interrupt/exception handlers.
+
+ Caller should try to get an array of interrupt and/or exception vectors that are in use and need to
+ persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.
+ If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.
+ If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS All CPU interrupt/exception entries have been successfully initialized
+ with default interrupt/exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuInterruptHandlers (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ IA32_IDT_GATE_DESCRIPTOR *IdtTable;
+ IA32_DESCRIPTOR IdtDescriptor;
+ UINTN IdtEntryCount;
+ EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap;
+ UINTN Index;
+ UINTN InterruptEntry;
+ UINT8 *InterruptEntryCode;
+
+ mReservedVectors = AllocatePool (sizeof (RESERVED_VECTORS_DATA) * CPU_INTERRUPT_NUM);
+ ASSERT (mReservedVectors != NULL);
+ SetMem ((VOID *) mReservedVectors, sizeof (RESERVED_VECTORS_DATA) * CPU_INTERRUPT_NUM, 0xff);
+ if (VectorInfo != NULL) {
+ Status = ReadAndVerifyVectorInfo (VectorInfo, mReservedVectors, CPU_INTERRUPT_NUM);
+ if (EFI_ERROR (Status)) {
+ FreePool (mReservedVectors);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ InitializeSpinLock (&mDisplayMessageSpinLock);
+ mExternalInterruptHandler = AllocateZeroPool (sizeof (EFI_CPU_INTERRUPT_HANDLER) * CPU_INTERRUPT_NUM);
+ ASSERT (mExternalInterruptHandler != NULL);
+
+ //
+ // Read IDT descriptor and calculate IDT size
+ //
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
+ if (IdtEntryCount > CPU_INTERRUPT_NUM) {
+ IdtEntryCount = CPU_INTERRUPT_NUM;
+ }
+ //
+ // Create Interrupt Descriptor Table and Copy the old IDT table in
+ //
+ IdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM);
+ ASSERT (IdtTable != NULL);
+ CopyMem (IdtTable, (VOID *)IdtDescriptor.Base, sizeof (IA32_IDT_GATE_DESCRIPTOR) * IdtEntryCount);
+
+ AsmGetTemplateAddressMap (&TemplateMap);
+ ASSERT (TemplateMap.ExceptionStubHeaderSize <= HOOKAFTER_STUB_SIZE);
+ InterruptEntryCode = AllocatePool (TemplateMap.ExceptionStubHeaderSize * CPU_INTERRUPT_NUM);
+ ASSERT (InterruptEntryCode != NULL);
+
+ InterruptEntry = (UINTN) InterruptEntryCode;
+ for (Index = 0; Index < CPU_INTERRUPT_NUM; Index ++) {
+ CopyMem (
+ (VOID *) InterruptEntry,
+ (VOID *) TemplateMap.ExceptionStart,
+ TemplateMap.ExceptionStubHeaderSize
+ );
+ AsmVectorNumFixup ((VOID *) InterruptEntry, (UINT8) Index, FALSE);
+ InterruptEntry += TemplateMap.ExceptionStubHeaderSize;
+ }
+
+ TemplateMap.ExceptionStart = (UINTN) InterruptEntryCode;
+ UpdateIdtTable (IdtTable, &TemplateMap, CPU_INTERRUPT_NUM);
+
+ //
+ // Load Interrupt Descriptor Table
+ //
+ IdtDescriptor.Base = (UINTN) IdtTable;
+ IdtDescriptor.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);
+ AsmWriteIdtr ((IA32_DESCRIPTOR *) &IdtDescriptor);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Registers a function to be called from the processor interrupt handler.
+
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+ NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or
+ InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned.
+
+ @param[in] InterruptType Defines which interrupt or exception to hook.
+ @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported,
+ or this function is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterCpuInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ return RegisterCpuInterruptHandlerWorker (InterruptType, InterruptHandler);
+}
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c
new file mode 100755
index 0000000000..4829016141
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c
@@ -0,0 +1,288 @@
+/** @file
+ CPU Exception Library provides DXE/SMM CPU common exception handler.
+
+Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.
+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.
+
+**/
+
+#include "CpuExceptionCommon.h"
+#include
+
+//
+// Spinlock for CPU information display
+//
+SPIN_LOCK mDisplayMessageSpinLock;
+
+//
+// Image align size for DXE/SMM
+//
+CONST UINTN mImageAlignSize = SIZE_4KB;
+
+RESERVED_VECTORS_DATA mReservedVectorsData[CPU_INTERRUPT_NUM];
+EFI_CPU_INTERRUPT_HANDLER mExternalInterruptHandlerTable[CPU_INTERRUPT_NUM];
+EFI_CPU_INTERRUPT_HANDLER *mExternalInterruptHandler = NULL;
+UINTN mEnabledInterruptNum = 0;
+
+/**
+ Common exception handler.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ EXCEPTION_HANDLER_CONTEXT *ExceptionHandlerContext;
+
+ ExceptionHandlerContext = (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (SystemContext.SystemContextIa32);
+
+ switch (mReservedVectors[ExceptionType].Attribute) {
+ case EFI_VECTOR_HANDOFF_HOOK_BEFORE:
+ //
+ // Need to jmp to old IDT handler after this exception handler
+ //
+ ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE;
+ ExceptionHandlerContext->OldIdtHandler = mReservedVectors[ExceptionType].ExceptonHandler;
+ break;
+ case EFI_VECTOR_HANDOFF_HOOK_AFTER:
+ while (TRUE) {
+ //
+ // If if anyone has gotten SPIN_LOCK for owner running hook after
+ //
+ if (AcquireSpinLockOrFail (&mReservedVectors[ExceptionType].SpinLock)) {
+ //
+ // Need to execute old IDT handler before running this exception handler
+ //
+ mReservedVectors[ExceptionType].ApicId = GetApicId ();
+ ArchSaveExceptionContext (ExceptionType, SystemContext);
+ ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE;
+ ExceptionHandlerContext->OldIdtHandler = mReservedVectors[ExceptionType].ExceptonHandler;
+ return;
+ }
+ //
+ // If failed to acquire SPIN_LOCK, check if it was locked by processor itself
+ //
+ if (mReservedVectors[ExceptionType].ApicId == GetApicId ()) {
+ //
+ // Old IDT handler has been executed, then retore CPU exception content to
+ // run new exception handler.
+ //
+ ArchRestoreExceptionContext (ExceptionType, SystemContext);
+ //
+ // Rlease spin lock for ApicId
+ //
+ ReleaseSpinLock (&mReservedVectors[ExceptionType].SpinLock);
+ break;
+ }
+ CpuPause ();
+ }
+ break;
+ case 0xffffffff:
+ break;
+ default:
+ //
+ // It should never reach here
+ //
+ CpuDeadLoop ();
+ break;
+ }
+
+ if (mExternalInterruptHandler[ExceptionType] != NULL) {
+ (mExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext);
+ } else if (ExceptionType < CPU_EXCEPTION_NUM) {
+ //
+ // Get Spinlock to display CPU information
+ //
+ while (!AcquireSpinLockOrFail (&mDisplayMessageSpinLock)) {
+ CpuPause ();
+ }
+ //
+ // Display ExceptionType, CPU information and Image information
+ //
+ DumpCpuContent (ExceptionType, SystemContext);
+ //
+ // Release Spinlock of output message
+ //
+ ReleaseSpinLock (&mDisplayMessageSpinLock);
+ //
+ // Enter a dead loop if needn't to execute old IDT handler further
+ //
+ if (mReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) {
+ CpuDeadLoop ();
+ }
+ }
+}
+
+/**
+ Internal worker function to update IDT entries accordling to vector attributes.
+
+ @param[in] IdtTable Pointer to IDT table.
+ @param[in] TemplateMap Pointer to a buffer where the address map is returned.
+ @param[in] IdtEntryCount IDT entries number to be updated.
+
+**/
+VOID
+UpdateIdtTable (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtTable,
+ IN EXCEPTION_HANDLER_TEMPLATE_MAP *TemplateMap,
+ IN UINTN IdtEntryCount
+ )
+{
+ UINT16 CodeSegment;
+ UINTN Index;
+ UINTN InterruptHandler;
+
+ //
+ // Use current CS as the segment selector of interrupt gate in IDT
+ //
+ CodeSegment = AsmReadCs ();
+
+ for (Index = 0; Index < IdtEntryCount; Index ++) {
+ IdtTable[Index].Bits.Selector = CodeSegment;
+ //
+ // Check reserved vectors attributes
+ //
+ switch (mReservedVectors[Index].Attribute) {
+ case EFI_VECTOR_HANDOFF_DO_NOT_HOOK:
+ //
+ // Keep original IDT entry
+ //
+ continue;
+ case EFI_VECTOR_HANDOFF_HOOK_AFTER:
+ InitializeSpinLock (&mReservedVectors[Index].SpinLock);
+ CopyMem (
+ (VOID *) mReservedVectors[Index].HookAfterStubHeaderCode,
+ (VOID *) TemplateMap->HookAfterStubHeaderStart,
+ TemplateMap->ExceptionStubHeaderSize
+ );
+ AsmVectorNumFixup ((VOID *) mReservedVectors[Index].HookAfterStubHeaderCode, (UINT8) Index, TRUE);
+ //
+ // Go on the following code
+ //
+ case EFI_VECTOR_HANDOFF_HOOK_BEFORE:
+ //
+ // Save original IDT handler address
+ //
+ mReservedVectors[Index].ExceptonHandler = ArchGetIdtHandler (&IdtTable[Index]);
+ //
+ // Go on the following code
+ //
+ default:
+ //
+ // Update new IDT entry
+ //
+ InterruptHandler = TemplateMap->ExceptionStart + Index * TemplateMap->ExceptionStubHeaderSize;
+ ArchUpdateIdtEntry (&IdtTable[Index], InterruptHandler);
+ break;
+ }
+ }
+
+ //
+ // Save Interrupt number to global variable used for RegisterCpuInterruptHandler ()
+ //
+ mEnabledInterruptNum = IdtEntryCount;
+}
+
+/**
+ Internal worker function to initialize exception handler.
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized
+ with default exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+InitializeCpuExceptionHandlersWorker (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ IA32_DESCRIPTOR IdtDescriptor;
+ UINTN IdtEntryCount;
+ EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap;
+ IA32_IDT_GATE_DESCRIPTOR *IdtTable;
+
+ mReservedVectors = mReservedVectorsData;
+ SetMem ((VOID *) mReservedVectors, sizeof (RESERVED_VECTORS_DATA) * CPU_EXCEPTION_NUM, 0xff);
+ if (VectorInfo != NULL) {
+ Status = ReadAndVerifyVectorInfo (VectorInfo, mReservedVectors, CPU_EXCEPTION_NUM);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ InitializeSpinLock (&mDisplayMessageSpinLock);
+
+ mExternalInterruptHandler = mExternalInterruptHandlerTable;
+ //
+ // Read IDT descriptor and calculate IDT size
+ //
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
+ if (IdtEntryCount > CPU_EXCEPTION_NUM) {
+ //
+ // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most
+ //
+ IdtEntryCount = CPU_EXCEPTION_NUM;
+ }
+
+ IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+ AsmGetTemplateAddressMap (&TemplateMap);
+ ASSERT (TemplateMap.ExceptionStubHeaderSize <= HOOKAFTER_STUB_SIZE);
+ UpdateIdtTable (IdtTable, &TemplateMap, IdtEntryCount);
+ mEnabledInterruptNum = IdtEntryCount;
+ return EFI_SUCCESS;
+}
+
+/**
+ Registers a function to be called from the processor interrupt handler.
+
+ @param[in] InterruptType Defines which interrupt or exception to hook.
+ @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported,
+ or this function is not supported.
+**/
+EFI_STATUS
+RegisterCpuInterruptHandlerWorker (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType < 0 || InterruptType >= (EFI_EXCEPTION_TYPE)mEnabledInterruptNum ||
+ mReservedVectors[InterruptType].Attribute == EFI_VECTOR_HANDOFF_DO_NOT_HOOK) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (InterruptHandler == NULL && mExternalInterruptHandler[InterruptType] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterruptHandler != NULL && mExternalInterruptHandler[InterruptType] != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mExternalInterruptHandler[InterruptType] = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
new file mode 100755
index 0000000000..40cdedface
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
@@ -0,0 +1,202 @@
+/** @file
+ IA32 CPU Exception Handler functons.
+
+ Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include "CpuExceptionCommon.h"
+
+/**
+ Return address map of exception handler template so that C code can generate
+ exception tables.
+
+ @param IdtEntry Pointer to IDT entry to be updated.
+ @param InterruptHandler IDT handler value.
+
+**/
+VOID
+ArchUpdateIdtEntry (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
+ IN UINTN InterruptHandler
+ )
+{
+ IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
+ IdtEntry->Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+ IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+}
+
+/**
+ Read IDT handler value from IDT entry.
+
+ @param IdtEntry Pointer to IDT entry to be read.
+
+**/
+UINTN
+ArchGetIdtHandler (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
+ )
+{
+ return (UINTN)IdtEntry->Bits.OffsetLow + (((UINTN)IdtEntry->Bits.OffsetHigh) << 16);
+}
+
+/**
+ Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+
+**/
+VOID
+ArchSaveExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ IA32_EFLAGS32 Eflags;
+ //
+ // Save Exception context in global variable
+ //
+ mReservedVectors[ExceptionType].OldFlags = SystemContext.SystemContextIa32->Eflags;
+ mReservedVectors[ExceptionType].OldCs = SystemContext.SystemContextIa32->Cs;
+ mReservedVectors[ExceptionType].OldIp = SystemContext.SystemContextIa32->Eip;
+ mReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextIa32->ExceptionData;
+ //
+ // Clear IF flag to avoid old IDT handler enable interrupt by IRET
+ //
+ Eflags.UintN = SystemContext.SystemContextIa32->Eflags;
+ Eflags.Bits.IF = 0;
+ SystemContext.SystemContextIa32->Eflags = Eflags.UintN;
+ //
+ // Modify the EIP in stack, then old IDT handler will return to the stub code
+ //
+ SystemContext.SystemContextIa32->Eip = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode;
+}
+
+/**
+ Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+ArchRestoreExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ SystemContext.SystemContextIa32->Eflags = mReservedVectors[ExceptionType].OldFlags;
+ SystemContext.SystemContextIa32->Cs = mReservedVectors[ExceptionType].OldCs;
+ SystemContext.SystemContextIa32->Eip = mReservedVectors[ExceptionType].OldIp;
+ SystemContext.SystemContextIa32->ExceptionData = mReservedVectors[ExceptionType].ExceptionData;
+}
+
+/**
+ Display CPU information.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+DumpCpuContent (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINTN ImageBase;
+ UINTN EntryPoint;
+
+ InternalPrintMessage (
+ "!!!! IA32 Exception Type - %08x CPU Apic ID - %08x !!!!\n",
+ ExceptionType,
+ GetApicId ()
+ );
+ InternalPrintMessage (
+ "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->Cs,
+ SystemContext.SystemContextIa32->Eflags
+ );
+ if ((mErrorCodeFlag & (1 << ExceptionType)) != 0) {
+ InternalPrintMessage (
+ "ExceptionData - %08x\n",
+ SystemContext.SystemContextIa32->ExceptionData
+ );
+ }
+ InternalPrintMessage (
+ "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
+ SystemContext.SystemContextIa32->Eax,
+ SystemContext.SystemContextIa32->Ecx,
+ SystemContext.SystemContextIa32->Edx,
+ SystemContext.SystemContextIa32->Ebx
+ );
+ InternalPrintMessage (
+ "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
+ SystemContext.SystemContextIa32->Esp,
+ SystemContext.SystemContextIa32->Ebp,
+ SystemContext.SystemContextIa32->Esi,
+ SystemContext.SystemContextIa32->Edi
+ );
+ InternalPrintMessage (
+ "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
+ SystemContext.SystemContextIa32->Ds,
+ SystemContext.SystemContextIa32->Es,
+ SystemContext.SystemContextIa32->Fs,
+ SystemContext.SystemContextIa32->Gs,
+ SystemContext.SystemContextIa32->Ss
+ );
+ InternalPrintMessage (
+ "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
+ SystemContext.SystemContextIa32->Cr0,
+ SystemContext.SystemContextIa32->Cr2,
+ SystemContext.SystemContextIa32->Cr3,
+ SystemContext.SystemContextIa32->Cr4
+ );
+ InternalPrintMessage (
+ "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
+ SystemContext.SystemContextIa32->Dr0,
+ SystemContext.SystemContextIa32->Dr1,
+ SystemContext.SystemContextIa32->Dr2,
+ SystemContext.SystemContextIa32->Dr3
+ );
+ InternalPrintMessage (
+ "DR6 - %08x, DR7 - %08x\n",
+ SystemContext.SystemContextIa32->Dr6,
+ SystemContext.SystemContextIa32->Dr7
+ );
+ InternalPrintMessage (
+ "GDTR - %08x %08x, IDTR - %08x %08x\n",
+ SystemContext.SystemContextIa32->Gdtr[0],
+ SystemContext.SystemContextIa32->Gdtr[1],
+ SystemContext.SystemContextIa32->Idtr[0],
+ SystemContext.SystemContextIa32->Idtr[1]
+ );
+ InternalPrintMessage (
+ "LDTR - %08x, TR - %08x\n",
+ SystemContext.SystemContextIa32->Ldtr,
+ SystemContext.SystemContextIa32->Tr
+ );
+ InternalPrintMessage (
+ "FXSAVE_STATE - %08x\n",
+ &SystemContext.SystemContextIa32->FxSaveState
+ );
+
+ //
+ // Find module image base and module entry point by RIP
+ //
+ ImageBase = FindModuleImageBase (SystemContext.SystemContextIa32->Eip, &EntryPoint);
+ if (ImageBase != 0) {
+ InternalPrintMessage (
+ " (ImageBase=%08x, EntryPoint=%08x) !!!!\n",
+ ImageBase,
+ EntryPoint
+ );
+ }
+}
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
new file mode 100755
index 0000000000..a8d3556a80
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
@@ -0,0 +1,44 @@
+/** @file
+ Ia32 arch definition for CPU Exception Handler Library.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.
+ 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 _ARCH_CPU_INTERRUPT_DEFS_H_
+#define _ARCH_CPU_INTERRUPT_DEFS_H_
+
+typedef struct {
+ EFI_SYSTEM_CONTEXT_IA32 SystemContext;
+ BOOLEAN ExceptionDataFlag;
+ UINTN OldIdtHandler;
+} EXCEPTION_HANDLER_CONTEXT;
+
+//
+// Register Structure Definitions
+//
+typedef struct {
+ EFI_STATUS_CODE_DATA Header;
+ EFI_SYSTEM_CONTEXT_IA32 SystemContext;
+} CPU_STATUS_CODE_TEMPLATE;
+
+typedef struct {
+ SPIN_LOCK SpinLock;
+ UINT32 ApicId;
+ UINT32 Attribute;
+ UINTN ExceptonHandler;
+ UINTN OldFlags;
+ UINTN OldCs;
+ UINTN OldIp;
+ UINTN ExceptionData;
+ UINT8 HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE];
+} RESERVED_VECTORS_DATA;
+
+#endif
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S
new file mode 100755
index 0000000000..086e896e44
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S
@@ -0,0 +1,642 @@
+#------------------------------------------------------------------------------
+#*
+#* Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.
+#* 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.
+#*
+#* ExceptionHandlerAsm.S
+#*
+#* Abstract:
+#*
+#* IA32 CPU Exception Handler
+#
+#------------------------------------------------------------------------------
+
+
+#.MMX
+#.XMM
+
+ASM_GLOBAL ASM_PFX(CommonExceptionHandler)
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
+ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd)
+
+#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
+#EXTRN ASM_PFX(mDoFarReturnFlag):DWORD # Do far return flag
+
+.text
+
+#
+# exception handler stub table
+#
+Exception0Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 0
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception1Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 1
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception2Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 2
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception3Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 3
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception4Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 4
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception5Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 5
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception6Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 6
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception7Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 7
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception8Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 8
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception9Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 9
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception10Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 10
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception11Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 11
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception12Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 12
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception13Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 13
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception14Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 14
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception15Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 15
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception16Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 16
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception17Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 17
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception18Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 18
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception19Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 19
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception20Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 20
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception21Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 21
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception22Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 22
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception23Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 23
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception24Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 24
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception25Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 25
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception26Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 26
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception27Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 27
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception28Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 28
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception29Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 29
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception30Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 30
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+Exception31Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 31
+ pushl %eax
+ .byte 0xB8
+ .long ASM_PFX(CommonInterruptEntry)
+ jmp *%eax
+
+HookAfterStubBegin:
+ .byte 0x6a # push
+VectorNum:
+ .byte 0 # 0 will be fixed
+ pushl %eax
+ .byte 0xB8 # movl ASM_PFX(HookAfterStubHeaderEnd), %eax
+ .long ASM_PFX(HookAfterStubHeaderEnd)
+ jmp *%eax
+ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd)
+ASM_PFX(HookAfterStubHeaderEnd):
+ popl %eax
+ subl $8, %esp # reserve room for filling exception data later
+ pushl 8(%esp)
+ xchgl (%esp), %ecx # get vector number
+ bt %ecx, ASM_PFX(mErrorCodeFlag)
+ jnc NoErrorData
+ pushl (%esp) # addition push if exception data needed
+NoErrorData:
+ xchg (%esp), %ecx # restore ecx
+ pushl %eax
+
+#---------------------------------------;
+# CommonInterruptEntry ;
+#---------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
+ASM_PFX(CommonInterruptEntry):
+ cli
+ popl %eax
+ #
+ # All interrupt handlers are invoked through interrupt gates, so
+ # IF flag automatically cleared at the entry point
+ #
+
+ #
+ # Get vector number from top of stack
+ #
+ xchgl (%esp), %ecx
+ andl $0x0FF, %ecx # Vector number should be less than 256
+ cmpl $32, %ecx # Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt %ecx, ASM_PFX(mErrorCodeFlag)
+ jc HasErrorCode
+
+NoErrorCode:
+
+ #
+ # Stack:
+ # +---------------------+
+ # + EFlags +
+ # +---------------------+
+ # + CS +
+ # +---------------------+
+ # + EIP +
+ # +---------------------+
+ # + ECX +
+ # +---------------------+ <-- ESP
+ #
+ # Registers:
+ # ECX - Vector Number
+ #
+
+ #
+ # Put Vector Number on stack
+ #
+ pushl %ecx
+
+ #
+ # Put 0 (dummy) error code on stack, and restore ECX
+ #
+ xorl %ecx, %ecx # ECX = 0
+ xchgl 4(%esp), %ecx
+
+ jmp ErrorCodeAndVectorOnStack
+
+HasErrorCode:
+
+ #
+ # Stack:
+ # +---------------------+
+ # + EFlags +
+ # +---------------------+
+ # + CS +
+ # +---------------------+
+ # + EIP +
+ # +---------------------+
+ # + Error Code +
+ # +---------------------+
+ # + ECX +
+ # +---------------------+ <-- ESP
+ #
+ # Registers:
+ # ECX - Vector Number
+ #
+
+ #
+ # Put Vector Number on stack and restore ECX
+ #
+ xchgl (%esp), %ecx
+
+ErrorCodeAndVectorOnStack:
+ pushl %ebp
+ movl %esp, %ebp
+
+ #
+ # Stack:
+ # +---------------------+
+ # + EFlags +
+ # +---------------------+
+ # + CS +
+ # +---------------------+
+ # + EIP +
+ # +---------------------+
+ # + Error Code +
+ # +---------------------+
+ # + Vector Number +
+ # +---------------------+
+ # + EBP +
+ # +---------------------+ <-- EBP
+ #
+
+ #
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ # is 16-byte aligned
+ #
+ andl $0x0fffffff0, %esp
+ subl $12, %esp
+
+ subl $8, %esp
+ pushl $0 # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ pushl $0 # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+
+#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushl %ebx
+ leal 24(%ebp), %ecx
+ pushl %ecx # ESP
+ pushl (%ebp) # EBP
+ pushl %esi
+ pushl %edi
+
+#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ movl %ss, %eax
+ pushl %eax
+ movzwl 16(%ebp), %eax
+ pushl %eax
+ movl %ds, %eax
+ pushl %eax
+ movl %es, %eax
+ pushl %eax
+ movl %fs, %eax
+ pushl %eax
+ movl %gs, %eax
+ pushl %eax
+
+#; UINT32 Eip;
+ movl 12(%ebp), %eax
+ pushl %eax
+
+#; UINT32 Gdtr[2], Idtr[2];
+ subl $8, %esp
+ sidt (%esp)
+ movl 2(%esp), %eax
+ xchgl (%esp), %eax
+ andl $0x0FFFF, %eax
+ movl %eax, 4(%esp)
+
+ subl $8, %esp
+ sgdt (%esp)
+ movl 2(%esp), %eax
+ xchgl (%esp), %eax
+ andl $0x0FFFF, %eax
+ movl %eax, 4(%esp)
+
+#; UINT32 Ldtr, Tr;
+ xorl %eax, %eax
+ str %ax
+ pushl %eax
+ sldt %ax
+ pushl %eax
+
+#; UINT32 EFlags;
+ movl 20(%ebp), %eax
+ pushl %eax
+
+#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ movl %cr4, %eax
+ orl $0x208, %eax
+ movl %eax, %cr4
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ xorl %eax, %eax
+ pushl %eax
+ movl %cr0, %eax
+ pushl %eax
+
+#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movl %dr7, %eax
+ pushl %eax
+ movl %dr6, %eax
+ pushl %eax
+ movl %dr3, %eax
+ pushl %eax
+ movl %dr2, %eax
+ pushl %eax
+ movl %dr1, %eax
+ pushl %eax
+ movl %dr0, %eax
+ pushl %eax
+
+#; FX_SAVE_STATE_IA32 FxSaveState;
+ subl $512, %esp
+ movl %esp, %edi
+ .byte 0x0f, 0x0ae, 0x07 #fxsave [edi]
+
+#; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+#; UINT32 ExceptionData;
+ pushl 8(%ebp)
+
+#; Prepare parameter and call
+ movl %esp, %edx
+ pushl %edx
+ movl 4(%ebp), %edx
+ pushl %edx
+
+ #
+ # Call External Exception Handler
+ #
+ call ASM_PFX(CommonExceptionHandler)
+ addl $8, %esp
+
+ cli
+#; UINT32 ExceptionData;
+ addl $4, %esp
+
+#; FX_SAVE_STATE_IA32 FxSaveState;
+ movl %esp, %esi
+ .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi]
+ addl $512, %esp
+
+#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+#; Skip restoration of DRx registers to support in-circuit emualators
+#; or debuggers set breakpoint in interrupt/exception context
+ addl $24, %esp
+
+#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ popl %eax
+ movl %eax, %cr0
+ addl $4, %esp # not for Cr1
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, %cr3
+ popl %eax
+ movl %eax, %cr4
+
+#; UINT32 EFlags;
+ popl 20(%ebp)
+
+#; UINT32 Ldtr, Tr;
+#; UINT32 Gdtr[2], Idtr[2];
+#; Best not let anyone mess with these particular registers...
+ addl $24, %esp
+
+#; UINT32 Eip;
+ popl 12(%ebp)
+
+#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+#; NOTE - modified segment registers could hang the debugger... We
+#; could attempt to insulate ourselves against this possibility,
+#; but that poses risks as well.
+#;
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popl 16(%ebp)
+ popl %ss
+
+#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ popl %edi
+ popl %esi
+ addl $4, %esp # not for ebp
+ addl $4, %esp # not for esp
+ popl %ebx
+ popl %edx
+ popl %ecx
+ popl %eax
+
+ popl -8(%ebp)
+ popl -4(%ebp)
+ movl %ebp, %esp
+ popl %ebp
+ addl $8, %esp
+ cmpl $0, -16(%esp) # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ jz DoReturn
+ cmpl $1, -20(%esp) # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+ jz ErrorCode
+ jmp *-16(%esp)
+ErrorCode:
+ subl $4, %esp
+ jmp *-12(%esp)
+
+DoReturn:
+ cmpl $0, ASM_PFX(mDoFarReturnFlag)
+ jz DoIret
+ pushl 8(%esp) # save EFLAGS
+ addl $16, %esp
+ pushl -8(%esp) # save CS in new location
+ pushl -8(%esp) # save EIP in new location
+ pushl -8(%esp) # save EFLAGS in new location
+ popfl # restore EFLAGS
+ retf # far return
+
+DoIret:
+ iretl
+
+
+#---------------------------------------;
+# _AsmGetTemplateAddressMap ;
+#---------------------------------------;
+#
+# Protocol prototype
+# AsmGetTemplateAddressMap (
+# EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
+# );
+#
+# Routine Description:
+#
+# Return address map of interrupt handler template so that C code can generate
+# interrupt table.
+#
+# Arguments:
+#
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------;
+#-------------------------------------------------------------------------------------
+# AsmGetAddressMap (&AddressMap);
+#-------------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmGetTemplateAddressMap)
+ASM_PFX(AsmGetTemplateAddressMap):
+
+ pushl %ebp
+ movl %esp,%ebp
+ pushal
+
+ movl 0x8(%ebp), %ebx
+ movl $Exception0Handle, (%ebx)
+ movl $(Exception1Handle - Exception0Handle), 0x4(%ebx)
+ movl $(HookAfterStubBegin), 0x8(%ebx)
+
+ popal
+ popl %ebp
+ ret
+#-------------------------------------------------------------------------------------
+# AsmVectorNumFixup (*VectorBase, VectorNum, HookStub);
+#-------------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmVectorNumFixup)
+ASM_PFX(AsmVectorNumFixup):
+ movl 8(%esp), %eax
+ movl 4(%esp), %ecx
+ movb %al, (VectorNum - HookAfterStubBegin)(%ecx)
+ ret
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm
new file mode 100755
index 0000000000..90da51bd6a
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm
@@ -0,0 +1,445 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.
+; 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.
+;
+; Module Name:
+;
+; ExceptionHandlerAsm.Asm
+;
+; Abstract:
+;
+; IA32 CPU Exception Handler
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ .686
+ .model flat,C
+
+;
+; CommonExceptionHandler()
+;
+CommonExceptionHandler PROTO C
+
+.data
+
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+EXTRN mDoFarReturnFlag:DWORD ; Do far return flag
+
+.code
+
+ALIGN 8
+
+;
+; exception handler stub table
+;
+AsmIdtVectorBegin:
+REPEAT 32
+ db 6ah ; push #VectorNum
+ db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
+ push eax
+ mov eax, CommonInterruptEntry
+ jmp eax
+ENDM
+AsmIdtVectorEnd:
+
+HookAfterStubBegin:
+ db 6ah ; push
+VectorNum:
+ db 0 ; 0 will be fixed
+ push eax
+ mov eax, HookAfterStubHeaderEnd
+ jmp eax
+HookAfterStubHeaderEnd:
+ pop eax
+ sub esp, 8 ; reserve room for filling exception data later
+ push [esp + 8]
+ xchg ecx, [esp] ; get vector number
+ bt mErrorCodeFlag, ecx
+ jnc @F
+ push [esp] ; addition push if exception data needed
+@@:
+ xchg ecx, [esp] ; restore ecx
+ push eax
+
+;----------------------------------------------------------------------------;
+; CommonInterruptEntry ;
+;----------------------------------------------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+; Entry from each interrupt with a push eax and eax=interrupt number
+; Stack:
+; +---------------------+
+; + EFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + EIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+; + EBP +
+; +---------------------+ <-- EBP
+CommonInterruptEntry PROC PUBLIC
+ cli
+ pop eax
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+
+ ;
+ ; Get vector number from top of stack
+ ;
+ xchg ecx, [esp]
+ and ecx, 0FFh ; Vector number should be less than 256
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt mErrorCodeFlag, ecx
+ jc HasErrorCode
+
+NoErrorCode:
+
+ ;
+ ; Stack:
+ ; +---------------------+
+ ; + EFlags +
+ ; +---------------------+
+ ; + CS +
+ ; +---------------------+
+ ; + EIP +
+ ; +---------------------+
+ ; + ECX +
+ ; +---------------------+ <-- ESP
+ ;
+ ; Registers:
+ ; ECX - Vector Number
+ ;
+
+ ;
+ ; Put Vector Number on stack
+ ;
+ push ecx
+
+ ;
+ ; Put 0 (dummy) error code on stack, and restore ECX
+ ;
+ xor ecx, ecx ; ECX = 0
+ xchg ecx, [esp+4]
+
+ jmp ErrorCodeAndVectorOnStack
+
+HasErrorCode:
+
+ ;
+ ; Stack:
+ ; +---------------------+
+ ; + EFlags +
+ ; +---------------------+
+ ; + CS +
+ ; +---------------------+
+ ; + EIP +
+ ; +---------------------+
+ ; + Error Code +
+ ; +---------------------+
+ ; + ECX +
+ ; +---------------------+ <-- ESP
+ ;
+ ; Registers:
+ ; ECX - Vector Number
+ ;
+
+ ;
+ ; Put Vector Number on stack and restore ECX
+ ;
+ xchg ecx, [esp]
+
+ErrorCodeAndVectorOnStack:
+ push ebp
+ mov ebp, esp
+
+ ;
+ ; Stack:
+ ; +---------------------+
+ ; + EFlags +
+ ; +---------------------+
+ ; + CS +
+ ; +---------------------+
+ ; + EIP +
+ ; +---------------------+
+ ; + Error Code +
+ ; +---------------------+
+ ; + Vector Number +
+ ; +---------------------+
+ ; + EBP +
+ ; +---------------------+ <-- EBP
+ ;
+
+ ;
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ ; is 16-byte aligned
+ ;
+ and esp, 0fffffff0h
+ sub esp, 12
+
+ sub esp, 8
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ push eax
+ push ecx
+ push edx
+ push ebx
+ lea ecx, [ebp + 6 * 4]
+ push ecx ; ESP
+ push dword ptr [ebp] ; EBP
+ push esi
+ push edi
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ mov eax, ss
+ push eax
+ movzx eax, word ptr [ebp + 4 * 4]
+ push eax
+ mov eax, ds
+ push eax
+ mov eax, es
+ push eax
+ mov eax, fs
+ push eax
+ mov eax, gs
+ push eax
+
+;; UINT32 Eip;
+ mov eax, [ebp + 3 * 4]
+ push eax
+
+;; UINT32 Gdtr[2], Idtr[2];
+ sub esp, 8
+ sidt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ mov [esp+4], eax
+
+ sub esp, 8
+ sgdt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ mov [esp+4], eax
+
+;; UINT32 Ldtr, Tr;
+ xor eax, eax
+ str ax
+ push eax
+ sldt ax
+ push eax
+
+;; UINT32 EFlags;
+ mov eax, [ebp + 5 * 4]
+ push eax
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ mov eax, cr4
+ or eax, 208h
+ mov cr4, eax
+ push eax
+ mov eax, cr3
+ push eax
+ mov eax, cr2
+ push eax
+ xor eax, eax
+ push eax
+ mov eax, cr0
+ push eax
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov eax, dr7
+ push eax
+ mov eax, dr6
+ push eax
+ mov eax, dr3
+ push eax
+ mov eax, dr2
+ push eax
+ mov eax, dr1
+ push eax
+ mov eax, dr0
+ push eax
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ sub esp, 512
+ mov edi, esp
+ db 0fh, 0aeh, 07h ;fxsave [edi]
+
+;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push dword ptr [ebp + 2 * 4]
+
+;; Prepare parameter and call
+ mov edx, esp
+ push edx
+ mov edx, dword ptr [ebp + 1 * 4]
+ push edx
+
+ ;
+ ; Call External Exception Handler
+ ;
+ mov eax, CommonExceptionHandler
+ call eax
+ add esp, 8
+
+ cli
+;; UINT32 ExceptionData;
+ add esp, 4
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ mov esi, esp
+ db 0fh, 0aeh, 0eh ; fxrstor [esi]
+ add esp, 512
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add esp, 4 * 6
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop eax
+ mov cr0, eax
+ add esp, 4 ; not for Cr1
+ pop eax
+ mov cr2, eax
+ pop eax
+ mov cr3, eax
+ pop eax
+ mov cr4, eax
+
+;; UINT32 EFlags;
+ pop dword ptr [ebp + 5 * 4]
+
+;; UINT32 Ldtr, Tr;
+;; UINT32 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add esp, 24
+
+;; UINT32 Eip;
+ pop dword ptr [ebp + 3 * 4]
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+;; NOTE - modified segment registers could hang the debugger... We
+;; could attempt to insulate ourselves against this possibility,
+;; but that poses risks as well.
+;;
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ pop dword ptr [ebp + 4 * 4]
+ pop ss
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pop edi
+ pop esi
+ add esp, 4 ; not for ebp
+ add esp, 4 ; not for esp
+ pop ebx
+ pop edx
+ pop ecx
+ pop eax
+
+ pop dword ptr [ebp - 8]
+ pop dword ptr [ebp - 4]
+ mov esp, ebp
+ pop ebp
+ add esp, 8
+ cmp dword ptr [esp - 16], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ jz DoReturn
+ cmp dword ptr [esp - 20], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+ jz ErrorCode
+ jmp dword ptr [esp - 16]
+ErrorCode:
+ sub esp, 4
+ jmp dword ptr [esp - 12]
+
+DoReturn:
+ cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET
+ jz DoIret
+ push [esp + 8] ; save EFLAGS
+ add esp, 16
+ push [esp - 8] ; save CS in new location
+ push [esp - 8] ; save EIP in new location
+ push [esp - 8] ; save EFLAGS in new location
+ popfd ; restore EFLAGS
+ retf ; far return
+
+DoIret:
+ iretd
+
+CommonInterruptEntry ENDP
+
+;---------------------------------------;
+; _AsmGetTemplateAddressMap ;
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; AsmGetTemplateAddressMap (
+; EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
+; );
+;
+; Routine Description:
+;
+; Return address map of interrupt handler template so that C code can generate
+; interrupt table.
+;
+; Arguments:
+;
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Input: [ebp][0] = Original ebp
+; [ebp][4] = Return address
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+AsmGetTemplateAddressMap proc near public
+ push ebp ; C prolog
+ mov ebp, esp
+ pushad
+
+ mov ebx, dword ptr [ebp + 08h]
+ mov dword ptr [ebx], AsmIdtVectorBegin
+ mov dword ptr [ebx + 4h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
+ mov dword ptr [ebx + 8h], HookAfterStubBegin
+
+ popad
+ pop ebp
+ ret
+AsmGetTemplateAddressMap ENDP
+
+;-------------------------------------------------------------------------------------
+; AsmVectorNumFixup (*VectorBase, VectorNum, HookStub);
+;-------------------------------------------------------------------------------------
+AsmVectorNumFixup proc near public
+ mov eax, dword ptr [esp + 8]
+ mov ecx, [esp + 4]
+ mov [ecx + (VectorNum - HookAfterStubBegin)], al
+ ret
+AsmVectorNumFixup ENDP
+END
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
new file mode 100755
index 0000000000..7e94e38ae1
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
@@ -0,0 +1,183 @@
+/** @file
+ CPU exception handler library implemenation for SEC/PEIM modules.
+
+Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.
+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.
+
+**/
+
+#include
+#include "CpuExceptionCommon.h"
+
+//
+// Image Aglinment size for SEC/PEI phase
+//
+CONST UINTN mImageAlignSize = 4;
+CONST UINTN mDoFarReturnFlag = 0;
+
+/**
+ Common exception handler.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ //
+ // Display ExceptionType, CPU information and Image information
+ //
+ DumpCpuContent (ExceptionType, SystemContext);
+
+ //
+ // Enter a dead loop.
+ //
+ CpuDeadLoop ();
+}
+
+/**
+ Initializes all CPU exceptions entries and provides the default exception handlers.
+
+ Caller should try to get an array of interrupt and/or exception vectors that are in use and need to
+ persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.
+ If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.
+ If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.
+ Note: Before invoking this API, caller must allocate memory for IDT table and load
+ IDTR by AsmWriteIdtr().
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized
+ with default exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuExceptionHandlers (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ RESERVED_VECTORS_DATA ReservedVectorData[CPU_EXCEPTION_NUM];
+ IA32_DESCRIPTOR IdtDescriptor;
+ UINTN IdtEntryCount;
+ UINT16 CodeSegment;
+ EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap;
+ IA32_IDT_GATE_DESCRIPTOR *IdtTable;
+ UINTN Index;
+ UINTN InterruptHandler;
+
+ if (VectorInfo != NULL) {
+ SetMem ((VOID *) ReservedVectorData, sizeof (RESERVED_VECTORS_DATA) * CPU_EXCEPTION_NUM, 0xff);
+ Status = ReadAndVerifyVectorInfo (VectorInfo, ReservedVectorData, CPU_EXCEPTION_NUM);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Read IDT descriptor and calculate IDT size
+ //
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
+ if (IdtEntryCount > CPU_EXCEPTION_NUM) {
+ //
+ // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most
+ //
+ IdtEntryCount = CPU_EXCEPTION_NUM;
+ }
+ //
+ // Use current CS as the segment selector of interrupt gate in IDT
+ //
+ CodeSegment = AsmReadCs ();
+
+ AsmGetTemplateAddressMap (&TemplateMap);
+ IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base;
+ for (Index = 0; Index < IdtEntryCount; Index ++) {
+ IdtTable[Index].Bits.Selector = CodeSegment;
+ //
+ // Check reserved vectors attributes if has, only EFI_VECTOR_HANDOFF_DO_NOT_HOOK
+ // supported in this instance
+ //
+ if (VectorInfo != NULL) {
+ if (ReservedVectorData[Index].Attribute == EFI_VECTOR_HANDOFF_DO_NOT_HOOK) {
+ continue;
+ }
+ }
+ //
+ // Update IDT entry
+ //
+ InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize;
+ ArchUpdateIdtEntry (&IdtTable[Index], InterruptHandler);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes all CPU interrupt/exceptions entries and provides the default interrupt/exception handlers.
+
+ Caller should try to get an array of interrupt and/or exception vectors that are in use and need to
+ persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.
+ If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.
+ If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS All CPU interrupt/exception entries have been successfully initialized
+ with default interrupt/exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuInterruptHandlers (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Registers a function to be called from the processor interrupt handler.
+
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+ NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or
+ InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned.
+
+ @param[in] InterruptType Defines which interrupt or exception to hook.
+ @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported,
+ or this function is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterCpuInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ return EFI_UNSUPPORTED;
+}
\ No newline at end of file
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
new file mode 100755
index 0000000000..dfd7562898
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
@@ -0,0 +1,57 @@
+## @file
+# CPU Exception Handler library instance for SEC/PEI modules.
+#
+# Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecPeiCpuExceptionHandlerLib
+ MODULE_UNI_FILE = SecPeiCpuExceptionHandlerLib.uni
+ FILE_GUID = CA4BBC99-DFC6-4234-B553-8B6586B7B113
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuExceptionHandlerLib|SEC PEI_CORE PEIM
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.Ia32]
+ Ia32/ExceptionHandlerAsm.asm
+ Ia32/ExceptionHandlerAsm.S |GCC
+ Ia32/ArchExceptionHandler.c
+ Ia32/ArchInterruptDefs.h
+
+[Sources.X64]
+ X64/ExceptionHandlerAsm.asm
+ X64/ExceptionHandlerAsm.S |GCC
+ X64/ArchExceptionHandler.c
+ X64/ArchInterruptDefs.h
+
+[Sources.common]
+ CpuExceptionCommon.h
+ CpuExceptionCommon.c
+ SecPeiCpuException.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ SerialPortLib
+ PrintLib
+ LocalApicLib
+ PeCoffGetEntryPointLib
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.uni b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.uni
new file mode 100755
index 0000000000..af45a33874
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.uni differ
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
new file mode 100755
index 0000000000..37031204c6
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
@@ -0,0 +1,61 @@
+## @file
+# CPU Exception Handler library instance for SMM modules.
+#
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmCpuExceptionHandlerLib
+ MODULE_UNI_FILE = SmmCpuExceptionHandlerLib.uni
+ FILE_GUID = 8D2C439B-3981-42ff-9CE5-1B50ECA502D6
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_SMM_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.Ia32]
+ Ia32/ExceptionHandlerAsm.asm
+ Ia32/ExceptionHandlerAsm.S |GCC
+ Ia32/ArchExceptionHandler.c
+ Ia32/ArchInterruptDefs.h
+
+[Sources.X64]
+ X64/ExceptionHandlerAsm.asm
+ X64/ExceptionHandlerAsm.S |GCC
+ X64/ArchExceptionHandler.c
+ X64/ArchInterruptDefs.h
+
+[Sources.common]
+ CpuExceptionCommon.h
+ CpuExceptionCommon.c
+ DxeSmmCpuException.c
+ SmmException.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ SerialPortLib
+ PrintLib
+ SynchronizationLib
+ LocalApicLib
+ PeCoffGetEntryPointLib
+ DebugLib
+
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.uni b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.uni
new file mode 100755
index 0000000000..6d3ee1c9eb
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.uni differ
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c
new file mode 100755
index 0000000000..40f1250266
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c
@@ -0,0 +1,101 @@
+/** @file
+ CPU exception handler library implemenation for SMM modules.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include
+#include "CpuExceptionCommon.h"
+
+CONST UINTN mDoFarReturnFlag = 1;
+
+/**
+ Initializes all CPU exceptions entries and provides the default exception handlers.
+
+ Caller should try to get an array of interrupt and/or exception vectors that are in use and need to
+ persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.
+ If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.
+ If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized
+ with default exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuExceptionHandlers (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ )
+{
+ return InitializeCpuExceptionHandlersWorker (VectorInfo);
+}
+
+/**
+ Initializes all CPU interrupt/exceptions entries and provides the default interrupt/exception handlers.
+
+ Caller should try to get an array of interrupt and/or exception vectors that are in use and need to
+ persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.
+ If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.
+ If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS All CPU interrupt/exception entries have been successfully initialized
+ with default interrupt/exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuInterruptHandlers (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Registers a function to be called from the processor interrupt handler.
+
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+ NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or
+ InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned.
+
+ @param[in] InterruptType Defines which interrupt or exception to hook.
+ @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported,
+ or this function is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterCpuInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ return RegisterCpuInterruptHandlerWorker (InterruptType, InterruptHandler);
+}
\ No newline at end of file
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
new file mode 100755
index 0000000000..ee16ea856a
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
@@ -0,0 +1,233 @@
+/** @file
+ x64 CPU Exception Handler.
+
+ Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include "CpuExceptionCommon.h"
+
+/**
+ Return address map of exception handler template so that C code can generate
+ exception tables.
+
+ @param IdtEntry Pointer to IDT entry to be updated.
+ @param InterruptHandler IDT handler value.
+**/
+VOID
+ArchUpdateIdtEntry (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
+ IN UINTN InterruptHandler
+ )
+{
+ IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
+ IdtEntry->Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+ IdtEntry->Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
+ IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+}
+
+/**
+ Read IDT handler value from IDT entry.
+
+ @param IdtEntry Pointer to IDT entry to be read.
+
+**/
+UINTN
+ArchGetIdtHandler (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
+ )
+{
+ return IdtEntry->Bits.OffsetLow + (((UINTN) IdtEntry->Bits.OffsetHigh) << 16) +
+ (((UINTN) IdtEntry->Bits.OffsetUpper) << 32);
+}
+
+/**
+ Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+ArchSaveExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ IA32_EFLAGS32 Eflags;
+ //
+ // Save Exception context in global variable
+ //
+ mReservedVectors[ExceptionType].OldSs = SystemContext.SystemContextX64->Ss;
+ mReservedVectors[ExceptionType].OldSp = SystemContext.SystemContextX64->Rsp;
+ mReservedVectors[ExceptionType].OldFlags = SystemContext.SystemContextX64->Rflags;
+ mReservedVectors[ExceptionType].OldCs = SystemContext.SystemContextX64->Cs;
+ mReservedVectors[ExceptionType].OldIp = SystemContext.SystemContextX64->Rip;
+ mReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextX64->ExceptionData;
+ //
+ // Clear IF flag to avoid old IDT handler enable interrupt by IRET
+ //
+ Eflags.UintN = SystemContext.SystemContextX64->Rflags;
+ Eflags.Bits.IF = 0;
+ SystemContext.SystemContextX64->Rflags = Eflags.UintN;
+ //
+ // Modify the EIP in stack, then old IDT handler will return to the stub code
+ //
+ SystemContext.SystemContextX64->Rip = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode;
+}
+
+/**
+ Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+ArchRestoreExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ SystemContext.SystemContextX64->Ss = mReservedVectors[ExceptionType].OldSs;
+ SystemContext.SystemContextX64->Rsp = mReservedVectors[ExceptionType].OldSp;
+ SystemContext.SystemContextX64->Rflags = mReservedVectors[ExceptionType].OldFlags;
+ SystemContext.SystemContextX64->Cs = mReservedVectors[ExceptionType].OldCs;
+ SystemContext.SystemContextX64->Rip = mReservedVectors[ExceptionType].OldIp;
+ SystemContext.SystemContextX64->ExceptionData = mReservedVectors[ExceptionType].ExceptionData;
+}
+
+/**
+ Display CPU information.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+DumpCpuContent (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINTN ImageBase;
+ UINTN EntryPoint;
+
+ InternalPrintMessage (
+ "!!!! X64 Exception Type - %016lx CPU Apic ID - %08x !!!!\n",
+ ExceptionType,
+ GetApicId ()
+ );
+ InternalPrintMessage (
+ "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",
+ SystemContext.SystemContextX64->Rip,
+ SystemContext.SystemContextX64->Cs,
+ SystemContext.SystemContextX64->Rflags
+ );
+ if (mErrorCodeFlag & (1 << ExceptionType)) {
+ InternalPrintMessage (
+ "ExceptionData - %016lx\n",
+ SystemContext.SystemContextX64->ExceptionData
+ );
+ }
+ InternalPrintMessage (
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
+ SystemContext.SystemContextX64->Rax,
+ SystemContext.SystemContextX64->Rcx,
+ SystemContext.SystemContextX64->Rdx
+ );
+ InternalPrintMessage (
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
+ SystemContext.SystemContextX64->Rbx,
+ SystemContext.SystemContextX64->Rsp,
+ SystemContext.SystemContextX64->Rbp
+ );
+ InternalPrintMessage (
+ "RSI - %016lx, RDI - %016lx\n",
+ SystemContext.SystemContextX64->Rsi,
+ SystemContext.SystemContextX64->Rdi
+ );
+ InternalPrintMessage (
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
+ SystemContext.SystemContextX64->R8,
+ SystemContext.SystemContextX64->R9,
+ SystemContext.SystemContextX64->R10
+ );
+ InternalPrintMessage (
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
+ SystemContext.SystemContextX64->R11,
+ SystemContext.SystemContextX64->R12,
+ SystemContext.SystemContextX64->R13
+ );
+ InternalPrintMessage (
+ "R14 - %016lx, R15 - %016lx\n",
+ SystemContext.SystemContextX64->R14,
+ SystemContext.SystemContextX64->R15
+ );
+ InternalPrintMessage (
+ "DS - %016lx, ES - %016lx, FS - %016lx\n",
+ SystemContext.SystemContextX64->Ds,
+ SystemContext.SystemContextX64->Es,
+ SystemContext.SystemContextX64->Fs
+ );
+ InternalPrintMessage (
+ "GS - %016lx, SS - %016lx\n",
+ SystemContext.SystemContextX64->Gs,
+ SystemContext.SystemContextX64->Ss
+ );
+ InternalPrintMessage (
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
+ SystemContext.SystemContextX64->Cr0,
+ SystemContext.SystemContextX64->Cr2,
+ SystemContext.SystemContextX64->Cr3
+ );
+ InternalPrintMessage (
+ "CR4 - %016lx, CR8 - %016lx\n",
+ SystemContext.SystemContextX64->Cr4,
+ SystemContext.SystemContextX64->Cr8
+ );
+ InternalPrintMessage (
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
+ SystemContext.SystemContextX64->Dr0,
+ SystemContext.SystemContextX64->Dr1,
+ SystemContext.SystemContextX64->Dr2
+ );
+ InternalPrintMessage (
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
+ SystemContext.SystemContextX64->Dr3,
+ SystemContext.SystemContextX64->Dr6,
+ SystemContext.SystemContextX64->Dr7
+ );
+ InternalPrintMessage (
+ "GDTR - %016lx %016lx, LDTR - %016lx\n",
+ SystemContext.SystemContextX64->Gdtr[0],
+ SystemContext.SystemContextX64->Gdtr[1],
+ SystemContext.SystemContextX64->Ldtr
+ );
+ InternalPrintMessage (
+ "IDTR - %016lx %016lx, TR - %016lx\n",
+ SystemContext.SystemContextX64->Idtr[0],
+ SystemContext.SystemContextX64->Idtr[1],
+ SystemContext.SystemContextX64->Tr
+ );
+ InternalPrintMessage (
+ "FXSAVE_STATE - %016lx\n",
+ &SystemContext.SystemContextX64->FxSaveState
+ );
+
+ //
+ // Find module image base and module entry point by RIP
+ //
+ ImageBase = FindModuleImageBase (SystemContext.SystemContextX64->Rip, &EntryPoint);
+ if (ImageBase != 0) {
+ InternalPrintMessage (
+ " (ImageBase=%016lx, EntryPoint=%016lx) !!!!\n",
+ ImageBase,
+ EntryPoint
+ );
+ }
+}
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
new file mode 100755
index 0000000000..906480134a
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
@@ -0,0 +1,46 @@
+/** @file
+ X64 arch definition for CPU Exception Handler Library.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.
+ 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 _ARCH_CPU_INTERRUPT_DEFS_H_
+#define _ARCH_CPU_INTERRUPT_DEFS_H_
+
+typedef struct {
+ EFI_SYSTEM_CONTEXT_X64 SystemContext;
+ BOOLEAN ExceptionDataFlag;
+ UINTN OldIdtHandler;
+} EXCEPTION_HANDLER_CONTEXT;
+
+//
+// Register Structure Definitions
+//
+typedef struct {
+ EFI_STATUS_CODE_DATA Header;
+ EFI_SYSTEM_CONTEXT_X64 SystemContext;
+} CPU_STATUS_CODE_TEMPLATE;
+
+typedef struct {
+ SPIN_LOCK SpinLock;
+ UINT32 ApicId;
+ UINT32 Attribute;
+ UINTN ExceptonHandler;
+ UINTN OldSs;
+ UINTN OldSp;
+ UINTN OldFlags;
+ UINTN OldCs;
+ UINTN OldIp;
+ UINTN ExceptionData;
+ UINT8 HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE];
+} RESERVED_VECTORS_DATA;
+
+#endif
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
new file mode 100755
index 0000000000..7711d274b1
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
@@ -0,0 +1,641 @@
+#------------------------------------------------------------------------------ ;
+# Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+# 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.
+#
+# Module Name:
+#
+# ExceptionHandlerAsm.S
+#
+# Abstract:
+#
+# x64 CPU Exception Handler
+#
+# Notes:
+#
+#------------------------------------------------------------------------------
+
+
+
+ASM_GLOBAL ASM_PFX(CommonExceptionHandler)
+#ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
+#ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd)
+
+#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
+#EXTRN ASM_PFX(mDoFarReturnFlag):QWORD # Do far return flag
+.text
+.align 3
+
+#
+# exception handler stub table
+#
+Exception0Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 0
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception1Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 1
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception2Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 2
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception3Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 3
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception4Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 4
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception5Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 5
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception6Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 6
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception7Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 7
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception8Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 8
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception9Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 9
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception10Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 10
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception11Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 11
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception12Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 12
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception13Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 13
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception14Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 14
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception15Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 15
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception16Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 16
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception17Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 17
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception18Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 18
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception19Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 19
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception20Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 20
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception21Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 21
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception22Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 22
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception23Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 23
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception24Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 24
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception25Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 25
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception26Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 26
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception27Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 27
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception28Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 28
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception29Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 29
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception30Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 30
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+Exception31Handle:
+ .byte 0x6a # push #VectorNum
+ .byte 31
+ pushq %rax
+ .byte 0x48, 0xB8
+ .quad 0 #ASM_PFX(CommonInterruptEntry)
+ jmp *%rax
+
+HookAfterStubHeaderBegin:
+ .byte 0x6a # push
+#VectorNum:
+PatchVectorNum:
+ .byte 0 # 0 will be fixed
+ pushq %rax
+ .byte 0x48, 0xB8 # movq ASM_PFX(HookAfterStubHeaderEnd), %rax
+# .quad ASM_PFX(HookAfterStubHeaderEnd)
+PatchFuncAddress:
+ .quad 0
+ jmp *%rax
+ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd)
+ASM_PFX(HookAfterStubHeaderEnd):
+ movq %rsp, %rax
+ andl $0x0fffffff0, %esp # make sure 16-byte aligned for exception context
+ subq $0x18, %rsp # reserve room for filling exception data later
+ pushq %rcx
+ movq 8(%rax), %rcx
+# pushq %rax
+# movabsl ASM_PFX(mErrorCodeFlag), %eax
+# bt %ecx, %eax
+# popq %rax
+ bt %ecx, ASM_PFX(mErrorCodeFlag)(%rip)
+ jnc NoErrorData
+ pushq (%rsp) # push additional rcx to make stack alignment
+NoErrorData:
+ xchgq (%rsp), %rcx # restore rcx, save Exception Number in stack
+ pushq (%rax) # push rax into stack to keep code consistence
+
+#---------------------------------------;
+# CommonInterruptEntry ;
+#---------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
+ASM_PFX(CommonInterruptEntry):
+ cli
+ popq %rax
+ #
+ # All interrupt handlers are invoked through interrupt gates, so
+ # IF flag automatically cleared at the entry point
+ #
+ #
+ # Calculate vector number
+ #
+ xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number.
+ andq $0x0FF, %rcx
+ cmp $32, %ecx # Intel reserved vector for exceptions?
+ jae NoErrorCode
+ pushq %rax
+# movabsl ASM_PFX(mErrorCodeFlag), %eax
+ movl ASM_PFX(mErrorCodeFlag)(%rip), %eax
+ bt %ecx, %eax
+ popq %rax
+ jc CommonInterruptEntry_al_0000
+
+NoErrorCode:
+
+ #
+ # Push a dummy error code on the stack
+ # to maintain coherent stack map
+ #
+ pushq (%rsp)
+ movq $0, 8(%rsp)
+CommonInterruptEntry_al_0000:
+ pushq %rbp
+ movq %rsp, %rbp
+ pushq $0 # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ pushq $0 # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+
+ #
+ # Stack:
+ # +---------------------+ <-- 16-byte aligned ensured by processor
+ # + Old SS +
+ # +---------------------+
+ # + Old RSP +
+ # +---------------------+
+ # + RFlags +
+ # +---------------------+
+ # + CS +
+ # +---------------------+
+ # + RIP +
+ # +---------------------+
+ # + Error Code +
+ # +---------------------+
+ # + RCX / Vector Number +
+ # +---------------------+
+ # + RBP +
+ # +---------------------+ <-- RBP, 16-byte aligned
+ #
+
+
+ #
+ # Since here the stack pointer is 16-byte aligned, so
+ # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+ # is 16-byte aligned
+ #
+
+#; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+#; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %r11
+ pushq %r10
+ pushq %r9
+ pushq %r8
+ pushq %rax
+ pushq 8(%rbp) # RCX
+ pushq %rdx
+ pushq %rbx
+ pushq 48(%rbp) # RSP
+ pushq (%rbp) # RBP
+ pushq %rsi
+ pushq %rdi
+
+#; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzwq 56(%rbp), %rax
+ pushq %rax # for ss
+ movzwq 32(%rbp), %rax
+ pushq %rax # for cs
+ movl %ds, %eax
+ pushq %rax
+ movl %es, %eax
+ pushq %rax
+ movl %fs, %eax
+ pushq %rax
+ movl %gs, %eax
+ pushq %rax
+
+ movq %rcx, 8(%rbp) # save vector number
+
+#; UINT64 Rip;
+ pushq 24(%rbp)
+
+#; UINT64 Gdtr[2], Idtr[2];
+ xorq %rax, %rax
+ pushq %rax
+ pushq %rax
+ sidt (%rsp)
+ xchgq 2(%rsp), %rax
+ xchgq (%rsp), %rax
+ xchgq 8(%rsp), %rax
+
+ xorq %rax, %rax
+ pushq %rax
+ pushq %rax
+ sgdt (%rsp)
+ xchgq 2(%rsp), %rax
+ xchgq (%rsp), %rax
+ xchgq 8(%rsp), %rax
+
+#; UINT64 Ldtr, Tr;
+ xorq %rax, %rax
+ str %ax
+ pushq %rax
+ sldt %ax
+ pushq %rax
+
+#; UINT64 RFlags;
+ pushq 40(%rbp)
+
+#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ movq %cr8, %rax
+ pushq %rax
+ movq %cr4, %rax
+ orq $0x208, %rax
+ movq %rax, %cr4
+ pushq %rax
+ mov %cr3, %rax
+ pushq %rax
+ mov %cr2, %rax
+ pushq %rax
+ xorq %rax, %rax
+ pushq %rax
+ mov %cr0, %rax
+ pushq %rax
+
+#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movq %dr7, %rax
+ pushq %rax
+ movq %dr6, %rax
+ pushq %rax
+ movq %dr3, %rax
+ pushq %rax
+ movq %dr2, %rax
+ pushq %rax
+ movq %dr1, %rax
+ pushq %rax
+ movq %dr0, %rax
+ pushq %rax
+
+#; FX_SAVE_STATE_X64 FxSaveState;
+ subq $512, %rsp
+ movq %rsp, %rdi
+ .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi]
+
+#; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
+ cld
+
+#; UINT32 ExceptionData;
+ pushq 16(%rbp)
+
+#; Prepare parameter and call
+ mov 8(%rbp), %rcx
+ mov %rsp, %rdx
+ #
+ # Per X64 calling convention, allocate maximum parameter stack space
+ # and make sure RSP is 16-byte aligned
+ #
+ subq $40, %rsp
+ call ASM_PFX(CommonExceptionHandler)
+ addq $40, %rsp
+
+ cli
+#; UINT64 ExceptionData;
+ addq $8, %rsp
+
+#; FX_SAVE_STATE_X64 FxSaveState;
+
+ movq %rsp, %rsi
+ .byte 0x0f, 0x0ae, 0x0E # fxrstor [rsi]
+ addq $512, %rsp
+
+#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+#; Skip restoration of DRx registers to support in-circuit emualators
+#; or debuggers set breakpoint in interrupt/exception context
+ addq $48, %rsp
+
+#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ popq %rax
+ movq %rax, %cr0
+ addq $8, %rsp # not for Cr1
+ popq %rax
+ movq %rax, %cr2
+ popq %rax
+ movq %rax, %cr3
+ popq %rax
+ movq %rax, %cr4
+ popq %rax
+ movq %rax, %cr8
+
+#; UINT64 RFlags;
+ popq 40(%rbp)
+
+#; UINT64 Ldtr, Tr;
+#; UINT64 Gdtr[2], Idtr[2];
+#; Best not let anyone mess with these particular registers...
+ addq $48, %rsp
+
+#; UINT64 Rip;
+ popq 24(%rbp)
+
+#; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ popq %rax
+ # mov %rax, %gs ; not for gs
+ popq %rax
+ # mov %rax, %fs ; not for fs
+ # (X64 will not use fs and gs, so we do not restore it)
+ popq %rax
+ movl %eax, %es
+ popq %rax
+ movl %eax, %ds
+ popq 32(%rbp) # for cs
+ popq 56(%rbp) # for ss
+
+#; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+#; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ popq %rdi
+ popq %rsi
+ addq $8, %rsp # not for rbp
+ popq 48(%rbp) # for rsp
+ popq %rbx
+ popq %rdx
+ popq %rcx
+ popq %rax
+ popq %r8
+ popq %r9
+ popq %r10
+ popq %r11
+ popq %r12
+ popq %r13
+ popq %r14
+ popq %r15
+
+ movq %rbp, %rsp
+ popq %rbp
+ addq $16, %rsp
+ cmpq $0, -32(%rsp) # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ jz DoReturn # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+ cmpb $1, -40(%rsp)
+ jz ErrorCode
+ jmp *-32(%rsp)
+ErrorCode:
+ subq $8, %rsp
+ jmp *-24(%rsp)
+
+DoReturn:
+ pushq %rax
+# movabsq ASM_PFX(mDoFarReturnFlag), %rax
+ movq ASM_PFX(mDoFarReturnFlag)(%rip), %rax
+ cmpq $0, %rax # Check if need to do far return instead of IRET
+ popq %rax
+ jz DoIret
+ pushq %rax
+ movq %rsp, %rax # save old RSP to rax
+ movq 0x20(%rsp), %rsp
+ pushq 0x10(%rax) # save CS in new location
+ pushq 0x8(%rax) # save EIP in new location
+ pushq 0x18(%rax) # save EFLAGS in new location
+ movq (%rax), %rax # restore rax
+ popfq # restore EFLAGS
+# .byte 0x48 # prefix to composite "retq" with next "retf"
+# lretq #retf # far return
+ .byte 0x48 # prefix to composite "retq" with next "retf"
+#ifdef __APPLE__
+ .byte 0xCB
+#else
+ retf # far return
+#endif
+
+DoIret:
+ iretq
+
+
+#-------------------------------------------------------------------------------------
+# AsmGetTemplateAddressMap (&AddressMap);
+#-------------------------------------------------------------------------------------
+# comments here for definition of address map
+ASM_GLOBAL ASM_PFX(AsmGetTemplateAddressMap)
+ASM_PFX(AsmGetTemplateAddressMap):
+
+# movabsq $Exception0Handle, %rax
+# movq %rax, (%rcx)
+# movq $(Exception1Handle - Exception0Handle), 0x08(%rcx)
+# movabsq $HookAfterStubHeaderBegin, %rax
+# movq %rax, 0x10(%rcx)
+# ret
+ leaq Exception0Handle(%rip), %rax
+ movq %rax, (%rcx)
+ movq $(Exception1Handle - Exception0Handle), 0x08(%rcx)
+ leaq HookAfterStubHeaderBegin(%rip), %rax
+ movq %rax, 0x10(%rcx)
+ ret
+
+
+#-------------------------------------------------------------------------------------
+# VOID
+# EFIAPI
+# AsmVectorNumFixup (
+# IN VOID *VectorBase, // RCX
+# IN UINT8 VectorNum, // RDX
+# IN BOOLEAN HookStub // R8
+# );
+#-------------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmVectorNumFixup)
+ASM_PFX(AsmVectorNumFixup):
+# movq %rdx, %rax
+# movb %al, (VectorNum - HookAfterStubHeaderBegin)(%rcx)
+# ret
+ pushq %rbp
+ movq %rsp, %rbp
+
+# Patch vector #
+ movb %dl, (PatchVectorNum - HookAfterStubHeaderBegin)(%rcx)
+
+# Patch Function address
+ leaq ASM_PFX(HookAfterStubHeaderEnd)(%rip), %rax
+ leaq ASM_PFX(CommonInterruptEntry)(%rip), %r10
+ testb %r8b, %r8b
+ cmovneq %rax, %r10
+ movq %r10, (PatchFuncAddress - HookAfterStubHeaderBegin)(%rcx)
+
+ popq %rbp
+ ret
+
+#END
+
+
diff --git a/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
new file mode 100755
index 0000000000..dfb66e2bcf
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
@@ -0,0 +1,389 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+; 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.
+;
+; Module Name:
+;
+; ExceptionHandlerAsm.Asm
+;
+; Abstract:
+;
+; x64 CPU Exception Handler
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+;
+; CommonExceptionHandler()
+;
+externdef CommonExceptionHandler:near
+
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+EXTRN mDoFarReturnFlag:QWORD ; Do far return flag
+
+data SEGMENT
+
+.code
+
+ALIGN 8
+
+AsmIdtVectorBegin:
+REPEAT 32
+ db 6ah ; push #VectorNum
+ db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
+ push rax
+ mov rax, CommonInterruptEntry
+ jmp rax
+ENDM
+AsmIdtVectorEnd:
+
+HookAfterStubHeaderBegin:
+ db 6ah ; push
+@VectorNum:
+ db 0 ; 0 will be fixed
+ push rax
+ mov rax, HookAfterStubHeaderEnd
+ jmp rax
+HookAfterStubHeaderEnd:
+ mov rax, rsp
+ and sp, 0fff0h ; make sure 16-byte aligned for exception context
+ sub rsp, 18h ; reserve room for filling exception data later
+ push rcx
+ mov rcx, [rax + 8]
+ bt mErrorCodeFlag, ecx
+ jnc @F
+ push [rsp] ; push additional rcx to make stack alignment
+@@:
+ xchg rcx, [rsp] ; restore rcx, save Exception Number in stack
+ push [rax] ; push rax into stack to keep code consistence
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+; Entry from each interrupt with a push eax and eax=interrupt number
+; Stack frame would be as follows as specified in IA32 manuals:
+;
+; +---------------------+ <-- 16-byte aligned ensured by processor
+; + Old SS +
+; +---------------------+
+; + Old RSP +
+; +---------------------+
+; + RFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + RIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+; + RBP +
+; +---------------------+ <-- RBP, 16-byte aligned
+; The follow algorithm is used for the common interrupt routine.
+CommonInterruptEntry PROC PUBLIC
+ cli
+ pop rax
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+ xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx
+ and rcx, 0FFh
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt mErrorCodeFlag, ecx
+ jc @F
+
+NoErrorCode:
+
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push [rsp]
+ mov qword ptr [rsp + 8], 0
+@@:
+ push rbp
+ mov rbp, rsp
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+
+ ;
+ ; Stack:
+ ; +---------------------+ <-- 16-byte aligned ensured by processor
+ ; + Old SS +
+ ; +---------------------+
+ ; + Old RSP +
+ ; +---------------------+
+ ; + RFlags +
+ ; +---------------------+
+ ; + CS +
+ ; +---------------------+
+ ; + RIP +
+ ; +---------------------+
+ ; + Error Code +
+ ; +---------------------+
+ ; + RCX / Vector Number +
+ ; +---------------------+
+ ; + RBP +
+ ; +---------------------+ <-- RBP, 16-byte aligned
+ ;
+
+
+ ;
+ ; Since here the stack pointer is 16-byte aligned, so
+ ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+ ; is 16-byte aligned
+ ;
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ push r15
+ push r14
+ push r13
+ push r12
+ push r11
+ push r10
+ push r9
+ push r8
+ push rax
+ push qword ptr [rbp + 8] ; RCX
+ push rdx
+ push rbx
+ push qword ptr [rbp + 48] ; RSP
+ push qword ptr [rbp] ; RBP
+ push rsi
+ push rdi
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzx rax, word ptr [rbp + 56]
+ push rax ; for ss
+ movzx rax, word ptr [rbp + 32]
+ push rax ; for cs
+ mov rax, ds
+ push rax
+ mov rax, es
+ push rax
+ mov rax, fs
+ push rax
+ mov rax, gs
+ push rax
+
+ mov [rbp + 8], rcx ; save vector number
+
+;; UINT64 Rip;
+ push qword ptr [rbp + 24]
+
+;; UINT64 Gdtr[2], Idtr[2];
+ xor rax, rax
+ push rax
+ push rax
+ sidt [rsp]
+ xchg rax, [rsp + 2]
+ xchg rax, [rsp]
+ xchg rax, [rsp + 8]
+
+ xor rax, rax
+ push rax
+ push rax
+ sgdt [rsp]
+ xchg rax, [rsp + 2]
+ xchg rax, [rsp]
+ xchg rax, [rsp + 8]
+
+;; UINT64 Ldtr, Tr;
+ xor rax, rax
+ str ax
+ push rax
+ sldt ax
+ push rax
+
+;; UINT64 RFlags;
+ push qword ptr [rbp + 40]
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ mov rax, cr8
+ push rax
+ mov rax, cr4
+ or rax, 208h
+ mov cr4, rax
+ push rax
+ mov rax, cr3
+ push rax
+ mov rax, cr2
+ push rax
+ xor rax, rax
+ push rax
+ mov rax, cr0
+ push rax
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov rax, dr7
+ push rax
+ mov rax, dr6
+ push rax
+ mov rax, dr3
+ push rax
+ mov rax, dr2
+ push rax
+ mov rax, dr1
+ push rax
+ mov rax, dr0
+ push rax
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+ sub rsp, 512
+ mov rdi, rsp
+ db 0fh, 0aeh, 07h ;fxsave [rdi]
+
+;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push qword ptr [rbp + 16]
+
+;; Prepare parameter and call
+ mov rcx, [rbp + 8]
+ mov rdx, rsp
+ ;
+ ; Per X64 calling convention, allocate maximum parameter stack space
+ ; and make sure RSP is 16-byte aligned
+ ;
+ sub rsp, 4 * 8 + 8
+ mov rax, CommonExceptionHandler
+ call rax
+ add rsp, 4 * 8 + 8
+
+ cli
+;; UINT64 ExceptionData;
+ add rsp, 8
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ mov rsi, rsp
+ db 0fh, 0aeh, 0Eh ; fxrstor [rsi]
+ add rsp, 512
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add rsp, 8 * 6
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ pop rax
+ mov cr0, rax
+ add rsp, 8 ; not for Cr1
+ pop rax
+ mov cr2, rax
+ pop rax
+ mov cr3, rax
+ pop rax
+ mov cr4, rax
+ pop rax
+ mov cr8, rax
+
+;; UINT64 RFlags;
+ pop qword ptr [rbp + 40]
+
+;; UINT64 Ldtr, Tr;
+;; UINT64 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add rsp, 48
+
+;; UINT64 Rip;
+ pop qword ptr [rbp + 24]
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ pop rax
+ ; mov gs, rax ; not for gs
+ pop rax
+ ; mov fs, rax ; not for fs
+ ; (X64 will not use fs and gs, so we do not restore it)
+ pop rax
+ mov es, rax
+ pop rax
+ mov ds, rax
+ pop qword ptr [rbp + 32] ; for cs
+ pop qword ptr [rbp + 56] ; for ss
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ pop rdi
+ pop rsi
+ add rsp, 8 ; not for rbp
+ pop qword ptr [rbp + 48] ; for rsp
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rax
+ pop r8
+ pop r9
+ pop r10
+ pop r11
+ pop r12
+ pop r13
+ pop r14
+ pop r15
+
+ mov rsp, rbp
+ pop rbp
+ add rsp, 16
+ cmp qword ptr [rsp - 32], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ jz DoReturn
+ cmp qword ptr [rsp - 40], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+ jz ErrorCode
+ jmp qword ptr [rsp - 32]
+ErrorCode:
+ sub rsp, 8
+ jmp qword ptr [rsp - 24]
+
+DoReturn:
+ cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET
+ jz DoIret
+ push rax
+ mov rax, rsp ; save old RSP to rax
+ mov rsp, [rsp + 20h]
+ push [rax + 10h] ; save CS in new location
+ push [rax + 8h] ; save EIP in new location
+ push [rax + 18h] ; save EFLAGS in new location
+ mov rax, [rax] ; restore rax
+ popfq ; restore EFLAGS
+ DB 48h ; prefix to composite "retq" with next "retf"
+ retf ; far return
+DoIret:
+ iretq
+
+CommonInterruptEntry ENDP
+
+;-------------------------------------------------------------------------------------
+; GetTemplateAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+; comments here for definition of address map
+AsmGetTemplateAddressMap PROC
+ mov rax, offset AsmIdtVectorBegin
+ mov qword ptr [rcx], rax
+ mov qword ptr [rcx + 8h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
+ mov rax, offset HookAfterStubHeaderBegin
+ mov qword ptr [rcx + 10h], rax
+ ret
+AsmGetTemplateAddressMap ENDP
+
+;-------------------------------------------------------------------------------------
+; AsmVectorNumFixup (*VectorBase, VectorNum, HookStub);
+;-------------------------------------------------------------------------------------
+AsmVectorNumFixup PROC
+ mov rax, rdx
+ mov [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al
+ ret
+AsmVectorNumFixup ENDP
+
+END
diff --git a/CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
new file mode 100755
index 0000000000..50a108726a
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
@@ -0,0 +1,1692 @@
+/** @file
+ MTRR setting library
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+//
+// This table defines the offset, base and length of the fixed MTRRs
+//
+CONST FIXED_MTRR mMtrrLibFixedMtrrTable[] = {
+ {
+ MTRR_LIB_IA32_MTRR_FIX64K_00000,
+ 0,
+ SIZE_64KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_80000,
+ 0x80000,
+ SIZE_16KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_A0000,
+ 0xA0000,
+ SIZE_16KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C0000,
+ 0xC0000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C8000,
+ 0xC8000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D0000,
+ 0xD0000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D8000,
+ 0xD8000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E0000,
+ 0xE0000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E8000,
+ 0xE8000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F0000,
+ 0xF0000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F8000,
+ 0xF8000,
+ SIZE_4KB
+ },
+};
+
+//
+// Lookup table used to print MTRRs
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mMtrrMemoryCacheTypeShortName[] = {
+ "UC", // CacheUncacheable
+ "WC", // CacheWriteCombining
+ "R*", // Invalid
+ "R*", // Invalid
+ "WT", // CacheWriteThrough
+ "WP", // CacheWriteProtected
+ "WB", // CacheWriteBack
+ "R*" // Invalid
+};
+
+/**
+ Returns the variable MTRR count for the CPU.
+
+ @return Variable MTRR count
+
+**/
+UINT32
+EFIAPI
+GetVariableMtrrCount (
+ VOID
+ )
+{
+ UINT32 VariableMtrrCount;
+
+ if (!IsMtrrSupported ()) {
+ return 0;
+ }
+
+ VariableMtrrCount = (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK);
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ return VariableMtrrCount;
+}
+
+/**
+ Returns the firmware usable variable MTRR count for the CPU.
+
+ @return Firmware usable variable MTRR count
+
+**/
+UINT32
+EFIAPI
+GetFirmwareVariableMtrrCount (
+ VOID
+ )
+{
+ UINT32 VariableMtrrCount;
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+ if (VariableMtrrCount < RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER) {
+ return 0;
+ }
+
+ return VariableMtrrCount - RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER;
+}
+
+/**
+ Returns the default MTRR cache type for the system.
+
+ @return The default MTRR cache type.
+
+**/
+MTRR_MEMORY_CACHE_TYPE
+EFIAPI
+MtrrGetDefaultMemoryType (
+ VOID
+)
+{
+ if (!IsMtrrSupported ()) {
+ return CacheUncacheable;
+}
+
+ return (MTRR_MEMORY_CACHE_TYPE) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE) & 0x7);
+}
+
+/**
+ Preparation before programming MTRR.
+
+ This function will do some preparation for programming MTRRs:
+ disable cache, invalid cache and disable MTRR caching functionality
+
+ @return CR4 value before changing.
+
+**/
+UINTN
+PreMtrrChange (
+ VOID
+ )
+{
+ UINTN Value;
+
+ //
+ // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
+ //
+ AsmDisableCache ();
+
+ //
+ // Save original CR4 value and clear PGE flag (Bit 7)
+ //
+ Value = AsmReadCr4 ();
+ AsmWriteCr4 (Value & (~BIT7));
+
+ //
+ // Flush all TLBs
+ //
+ CpuFlushTlb ();
+
+ //
+ // Disable Mtrrs
+ //
+ AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 0);
+
+ //
+ // Return original CR4 value
+ //
+ return Value;
+}
+
+
+/**
+ Cleaning up after programming MTRRs.
+
+ This function will do some clean up after programming MTRRs:
+ enable MTRR caching functionality, and enable cache
+
+ @param Cr4 CR4 value to restore
+
+**/
+VOID
+PostMtrrChange (
+ UINTN Cr4
+ )
+{
+ //
+ // Enable Cache MTRR
+ //
+ AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 3);
+
+ //
+ // Flush all TLBs
+ //
+ CpuFlushTlb ();
+
+ //
+ // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
+ //
+ AsmEnableCache ();
+
+ //
+ // Restore original CR4 value
+ //
+ AsmWriteCr4 (Cr4);
+}
+
+
+/**
+ Programs fixed MTRRs registers.
+
+ @param MemoryCacheType The memory type to set.
+ @param Base The base address of memory range.
+ @param Length The length of memory range.
+
+ @retval RETURN_SUCCESS The cache type was updated successfully
+ @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
+ for the fixed MTRRs.
+
+**/
+RETURN_STATUS
+ProgramFixedMtrr (
+ IN UINT64 MemoryCacheType,
+ IN OUT UINT64 *Base,
+ IN OUT UINT64 *Length
+ )
+{
+ UINT32 MsrNum;
+ UINT32 ByteShift;
+ UINT64 TempQword;
+ UINT64 OrMask;
+ UINT64 ClearMask;
+
+ TempQword = 0;
+ OrMask = 0;
+ ClearMask = 0;
+
+ for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {
+ if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&
+ (*Base <
+ (
+ mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +
+ (8 * mMtrrLibFixedMtrrTable[MsrNum].Length)
+ )
+ )
+ ) {
+ break;
+ }
+ }
+
+ if (MsrNum == MTRR_NUMBER_OF_FIXED_MTRR) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // We found the fixed MTRR to be programmed
+ //
+ for (ByteShift = 0; ByteShift < 8; ByteShift++) {
+ if (*Base ==
+ (
+ mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +
+ (ByteShift * mMtrrLibFixedMtrrTable[MsrNum].Length)
+ )
+ ) {
+ break;
+ }
+ }
+
+ if (ByteShift == 8) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ for (
+ ;
+ ((ByteShift < 8) && (*Length >= mMtrrLibFixedMtrrTable[MsrNum].Length));
+ ByteShift++
+ ) {
+ OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));
+ ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));
+ *Length -= mMtrrLibFixedMtrrTable[MsrNum].Length;
+ *Base += mMtrrLibFixedMtrrTable[MsrNum].Length;
+ }
+
+ if (ByteShift < 8 && (*Length != 0)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ TempQword =
+ (AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask;
+ AsmWriteMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr, TempQword);
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Get the attribute of variable MTRRs.
+
+ This function shadows the content of variable MTRRs into an
+ internal array: VariableMtrr.
+
+ @param MtrrValidBitsMask The mask for the valid bit of the MTRR
+ @param MtrrValidAddressMask The valid address mask for MTRR
+ @param VariableMtrr The array to shadow variable MTRRs content
+
+ @return The return value of this paramter indicates the
+ number of MTRRs which has been used.
+
+**/
+UINT32
+EFIAPI
+MtrrGetMemoryAttributeInVariableMtrr (
+ IN UINT64 MtrrValidBitsMask,
+ IN UINT64 MtrrValidAddressMask,
+ OUT VARIABLE_MTRR *VariableMtrr
+ )
+{
+ UINTN Index;
+ UINT32 MsrNum;
+ UINT32 UsedMtrr;
+ UINT32 FirmwareVariableMtrrCount;
+ UINT32 VariableMtrrEnd;
+
+ if (!IsMtrrSupported ()) {
+ return 0;
+ }
+
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
+ VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;
+
+ ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);
+ UsedMtrr = 0;
+
+ for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;
+ (
+ (MsrNum < VariableMtrrEnd) &&
+ (Index < FirmwareVariableMtrrCount)
+ );
+ MsrNum += 2
+ ) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {
+ VariableMtrr[Index].Msr = MsrNum;
+ VariableMtrr[Index].BaseAddress = (AsmReadMsr64 (MsrNum) &
+ MtrrValidAddressMask);
+ VariableMtrr[Index].Length = ((~(AsmReadMsr64 (MsrNum + 1) &
+ MtrrValidAddressMask)
+ ) &
+ MtrrValidBitsMask
+ ) + 1;
+ VariableMtrr[Index].Type = (AsmReadMsr64 (MsrNum) & 0x0ff);
+ VariableMtrr[Index].Valid = TRUE;
+ VariableMtrr[Index].Used = TRUE;
+ UsedMtrr = UsedMtrr + 1;
+ Index++;
+ }
+ }
+ return UsedMtrr;
+}
+
+
+/**
+ Checks overlap between given memory range and MTRRs.
+
+ @param Start The start address of memory range.
+ @param End The end address of memory range.
+ @param VariableMtrr The array to shadow variable MTRRs content
+
+ @retval TRUE Overlap exists.
+ @retval FALSE No overlap.
+
+**/
+BOOLEAN
+CheckMemoryAttributeOverlap (
+ IN PHYSICAL_ADDRESS Start,
+ IN PHYSICAL_ADDRESS End,
+ IN VARIABLE_MTRR *VariableMtrr
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < 6; Index++) {
+ if (
+ VariableMtrr[Index].Valid &&
+ !(
+ (Start > (VariableMtrr[Index].BaseAddress +
+ VariableMtrr[Index].Length - 1)
+ ) ||
+ (End < VariableMtrr[Index].BaseAddress)
+ )
+ ) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Marks a variable MTRR as non-valid.
+
+ @param Index The index of the array VariableMtrr to be invalidated
+ @param VariableMtrr The array to shadow variable MTRRs content
+ @param UsedMtrr The number of MTRRs which has already been used
+
+**/
+VOID
+InvalidateShadowMtrr (
+ IN UINTN Index,
+ IN VARIABLE_MTRR *VariableMtrr,
+ OUT UINT32 *UsedMtrr
+ )
+{
+ VariableMtrr[Index].Valid = FALSE;
+ *UsedMtrr = *UsedMtrr - 1;
+}
+
+
+/**
+ Combine memory attributes.
+
+ If overlap exists between given memory range and MTRRs, try to combine them.
+
+ @param Attributes The memory type to set.
+ @param Base The base address of memory range.
+ @param Length The length of memory range.
+ @param VariableMtrr The array to shadow variable MTRRs content
+ @param UsedMtrr The number of MTRRs which has already been used
+ @param OverwriteExistingMtrr Returns whether an existing MTRR was used
+
+ @retval EFI_SUCCESS Memory region successfully combined.
+ @retval EFI_ACCESS_DENIED Memory region cannot be combined.
+
+**/
+RETURN_STATUS
+CombineMemoryAttribute (
+ IN UINT64 Attributes,
+ IN OUT UINT64 *Base,
+ IN OUT UINT64 *Length,
+ IN VARIABLE_MTRR *VariableMtrr,
+ IN OUT UINT32 *UsedMtrr,
+ OUT BOOLEAN *OverwriteExistingMtrr
+ )
+{
+ UINT32 Index;
+ UINT64 CombineStart;
+ UINT64 CombineEnd;
+ UINT64 MtrrEnd;
+ UINT64 EndAddress;
+ UINT32 FirmwareVariableMtrrCount;
+ BOOLEAN CoveredByExistingMtrr;
+
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
+
+ *OverwriteExistingMtrr = FALSE;
+ CoveredByExistingMtrr = FALSE;
+ EndAddress = *Base +*Length - 1;
+
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
+
+ MtrrEnd = VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length - 1;
+ if (
+ !VariableMtrr[Index].Valid ||
+ (
+ *Base > (MtrrEnd) ||
+ (EndAddress < VariableMtrr[Index].BaseAddress)
+ )
+ ) {
+ continue;
+ }
+
+ //
+ // Combine same attribute MTRR range
+ //
+ if (Attributes == VariableMtrr[Index].Type) {
+ //
+ // if the Mtrr range contain the request range, set a flag, then continue to
+ // invalidate any MTRR of the same request range with higher priority cache type.
+ //
+ if (VariableMtrr[Index].BaseAddress <= *Base && MtrrEnd >= EndAddress) {
+ CoveredByExistingMtrr = TRUE;
+ continue;
+ }
+ //
+ // invalid this MTRR, and program the combine range
+ //
+ CombineStart =
+ (*Base) < VariableMtrr[Index].BaseAddress ?
+ (*Base) :
+ VariableMtrr[Index].BaseAddress;
+ CombineEnd = EndAddress > MtrrEnd ? EndAddress : MtrrEnd;
+
+ //
+ // Record the MTRR usage status in VariableMtrr array.
+ //
+ InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);
+ *Base = CombineStart;
+ *Length = CombineEnd - CombineStart + 1;
+ EndAddress = CombineEnd;
+ *OverwriteExistingMtrr = TRUE;
+ continue;
+ } else {
+ //
+ // The cache type is different, but the range is convered by one MTRR
+ //
+ if (VariableMtrr[Index].BaseAddress == *Base && MtrrEnd == EndAddress) {
+ InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);
+ continue;
+ }
+
+ }
+
+ if ((Attributes== MTRR_CACHE_WRITE_THROUGH &&
+ VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) ||
+ (Attributes == MTRR_CACHE_WRITE_BACK &&
+ VariableMtrr[Index].Type == MTRR_CACHE_WRITE_THROUGH) ||
+ (Attributes == MTRR_CACHE_UNCACHEABLE) ||
+ (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE)
+ ) {
+ *OverwriteExistingMtrr = TRUE;
+ continue;
+ }
+ //
+ // Other type memory overlap is invalid
+ //
+ return RETURN_ACCESS_DENIED;
+ }
+
+ if (CoveredByExistingMtrr) {
+ *Length = 0;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Calculate the maximum value which is a power of 2, but less the MemoryLength.
+
+ @param MemoryLength The number to pass in.
+ @return The maximum value which is align to power of 2 and less the MemoryLength
+
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+{
+ UINT64 Result;
+
+ if (RShiftU64 (MemoryLength, 32) != 0) {
+ Result = LShiftU64 (
+ (UINT64) GetPowerOfTwo32 (
+ (UINT32) RShiftU64 (MemoryLength, 32)
+ ),
+ 32
+ );
+ } else {
+ Result = (UINT64) GetPowerOfTwo32 ((UINT32) MemoryLength);
+ }
+
+ return Result;
+}
+
+
+/**
+ Determine the MTRR numbers used to program a memory range.
+
+ This function first checks the alignment of the base address. If the alignment of the base address <= Length,
+ cover the memory range (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and Length -= alignment.
+ Repeat the step until alignment > Length.
+
+ Then this function determines which direction of programming the variable MTRRs for the remaining length
+ will use fewer MTRRs.
+
+ @param BaseAddress Length of Memory to program MTRR
+ @param Length Length of Memory to program MTRR
+ @param MtrrNumber Pointer to the number of necessary MTRRs
+
+ @retval TRUE Positive direction is better.
+ FALSE Negtive direction is better.
+
+**/
+BOOLEAN
+GetMtrrNumberAndDirection (
+ IN UINT64 BaseAddress,
+ IN UINT64 Length,
+ IN UINTN *MtrrNumber
+ )
+{
+ UINT64 TempQword;
+ UINT64 Alignment;
+ UINT32 Positive;
+ UINT32 Subtractive;
+
+ *MtrrNumber = 0;
+
+ if (BaseAddress != 0) {
+ do {
+ //
+ // Calculate the alignment of the base address.
+ //
+ Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));
+
+ if (Alignment > Length) {
+ break;
+ }
+
+ (*MtrrNumber)++;
+ BaseAddress += Alignment;
+ Length -= Alignment;
+ } while (TRUE);
+
+ if (Length == 0) {
+ return TRUE;
+ }
+ }
+
+ TempQword = Length;
+ Positive = 0;
+ Subtractive = 0;
+
+ do {
+ TempQword -= Power2MaxMemory (TempQword);
+ Positive++;
+ } while (TempQword != 0);
+
+ TempQword = Power2MaxMemory (LShiftU64 (Length, 1)) - Length;
+ Subtractive++;
+ do {
+ TempQword -= Power2MaxMemory (TempQword);
+ Subtractive++;
+ } while (TempQword != 0);
+
+ if (Positive <= Subtractive) {
+ *MtrrNumber += Positive;
+ return TRUE;
+ } else {
+ *MtrrNumber += Subtractive;
+ return FALSE;
+ }
+}
+
+/**
+ Invalid variable MTRRs according to the value in the shadow array.
+
+ This function programs MTRRs according to the values specified
+ in the shadow array.
+
+ @param VariableMtrr The array to shadow variable MTRRs content
+
+**/
+VOID
+InvalidateMtrr (
+ IN VARIABLE_MTRR *VariableMtrr
+ )
+{
+ UINTN Index;
+ UINTN Cr4;
+ UINTN VariableMtrrCount;
+
+ Cr4 = PreMtrrChange ();
+ Index = 0;
+ VariableMtrrCount = GetVariableMtrrCount ();
+ while (Index < VariableMtrrCount) {
+ if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {
+ AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);
+ AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0);
+ VariableMtrr[Index].Used = FALSE;
+ }
+ Index ++;
+ }
+ PostMtrrChange (Cr4);
+}
+
+
+/**
+ Programs variable MTRRs
+
+ This function programs variable MTRRs
+
+ @param MtrrNumber Index of MTRR to program.
+ @param BaseAddress Base address of memory region.
+ @param Length Length of memory region.
+ @param MemoryCacheType Memory type to set.
+ @param MtrrValidAddressMask The valid address mask for MTRR
+
+**/
+VOID
+ProgramVariableMtrr (
+ IN UINTN MtrrNumber,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 MemoryCacheType,
+ IN UINT64 MtrrValidAddressMask
+ )
+{
+ UINT64 TempQword;
+ UINTN Cr4;
+
+ Cr4 = PreMtrrChange ();
+
+ //
+ // MTRR Physical Base
+ //
+ TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType;
+ AsmWriteMsr64 ((UINT32) MtrrNumber, TempQword);
+
+ //
+ // MTRR Physical Mask
+ //
+ TempQword = ~(Length - 1);
+ AsmWriteMsr64 (
+ (UINT32) (MtrrNumber + 1),
+ (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED
+ );
+
+ PostMtrrChange (Cr4);
+}
+
+
+/**
+ Convert the Memory attibute value to MTRR_MEMORY_CACHE_TYPE.
+
+ @param MtrrType MTRR memory type
+
+ @return The enum item in MTRR_MEMORY_CACHE_TYPE
+
+**/
+MTRR_MEMORY_CACHE_TYPE
+GetMemoryCacheTypeFromMtrrType (
+ IN UINT64 MtrrType
+ )
+{
+ switch (MtrrType) {
+ case MTRR_CACHE_UNCACHEABLE:
+ return CacheUncacheable;
+ case MTRR_CACHE_WRITE_COMBINING:
+ return CacheWriteCombining;
+ case MTRR_CACHE_WRITE_THROUGH:
+ return CacheWriteThrough;
+ case MTRR_CACHE_WRITE_PROTECTED:
+ return CacheWriteProtected;
+ case MTRR_CACHE_WRITE_BACK:
+ return CacheWriteBack;
+ default:
+ //
+ // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
+ // no mtrr covers the range
+ //
+ return CacheUncacheable;
+ }
+}
+
+/**
+ Initializes the valid bits mask and valid address mask for MTRRs.
+
+ This function initializes the valid bits mask and valid address mask for MTRRs.
+
+ @param MtrrValidBitsMask The mask for the valid bit of the MTRR
+ @param MtrrValidAddressMask The valid address mask for the MTRR
+
+**/
+VOID
+MtrrLibInitializeMtrrMask (
+ OUT UINT64 *MtrrValidBitsMask,
+ OUT UINT64 *MtrrValidAddressMask
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+
+ PhysicalAddressBits = (UINT8) RegEax;
+
+ *MtrrValidBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
+ *MtrrValidAddressMask = *MtrrValidBitsMask & 0xfffffffffffff000ULL;
+ } else {
+ *MtrrValidBitsMask = MTRR_LIB_CACHE_VALID_ADDRESS;
+ *MtrrValidAddressMask = 0xFFFFFFFF;
+ }
+}
+
+
+/**
+ Determing the real attribute of a memory range.
+
+ This function is to arbitrate the real attribute of the memory when
+ there are 2 MTRR covers the same memory range. For further details,
+ please refer the IA32 Software Developer's Manual, Volume 3,
+ Section 10.11.4.1.
+
+ @param MtrrType1 the first kind of Memory type
+ @param MtrrType2 the second kind of memory type
+
+**/
+UINT64
+MtrrPrecedence (
+ UINT64 MtrrType1,
+ UINT64 MtrrType2
+ )
+{
+ UINT64 MtrrType;
+
+ MtrrType = MTRR_CACHE_INVALID_TYPE;
+ switch (MtrrType1) {
+ case MTRR_CACHE_UNCACHEABLE:
+ MtrrType = MTRR_CACHE_UNCACHEABLE;
+ break;
+ case MTRR_CACHE_WRITE_COMBINING:
+ if (
+ MtrrType2==MTRR_CACHE_WRITE_COMBINING ||
+ MtrrType2==MTRR_CACHE_UNCACHEABLE
+ ) {
+ MtrrType = MtrrType2;
+ }
+ break;
+ case MTRR_CACHE_WRITE_THROUGH:
+ if (
+ MtrrType2==MTRR_CACHE_WRITE_THROUGH ||
+ MtrrType2==MTRR_CACHE_WRITE_BACK
+ ) {
+ MtrrType = MTRR_CACHE_WRITE_THROUGH;
+ } else if(MtrrType2==MTRR_CACHE_UNCACHEABLE) {
+ MtrrType = MTRR_CACHE_UNCACHEABLE;
+ }
+ break;
+ case MTRR_CACHE_WRITE_PROTECTED:
+ if (MtrrType2 == MTRR_CACHE_WRITE_PROTECTED ||
+ MtrrType2 == MTRR_CACHE_UNCACHEABLE) {
+ MtrrType = MtrrType2;
+ }
+ break;
+ case MTRR_CACHE_WRITE_BACK:
+ if (
+ MtrrType2== MTRR_CACHE_UNCACHEABLE ||
+ MtrrType2==MTRR_CACHE_WRITE_THROUGH ||
+ MtrrType2== MTRR_CACHE_WRITE_BACK
+ ) {
+ MtrrType = MtrrType2;
+ }
+ break;
+ case MTRR_CACHE_INVALID_TYPE:
+ MtrrType = MtrrType2;
+ break;
+ default:
+ break;
+ }
+
+ if (MtrrType2 == MTRR_CACHE_INVALID_TYPE) {
+ MtrrType = MtrrType1;
+ }
+ return MtrrType;
+}
+
+
+/**
+ This function attempts to set the attributes for a memory range.
+
+ @param BaseAddress The physical address that is the start
+ address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the
+ memory region.
+
+ @retval RETURN_SUCCESS The attributes were set for the memory
+ region.
+ @retval RETURN_INVALID_PARAMETER Length is zero.
+ @retval RETURN_UNSUPPORTED The processor does not support one or
+ more bytes of the memory resource range
+ specified by BaseAddress and Length.
+ @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
+ for the memory resource range specified
+ by BaseAddress and Length.
+ @retval RETURN_ACCESS_DENIED The attributes for the memory resource
+ range specified by BaseAddress and Length
+ cannot be modified.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
+ modify the attributes of the memory
+ resource range.
+
+**/
+RETURN_STATUS
+EFIAPI
+MtrrSetMemoryAttribute (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN MTRR_MEMORY_CACHE_TYPE Attribute
+ )
+{
+ UINT64 TempQword;
+ RETURN_STATUS Status;
+ UINT64 MemoryType;
+ UINT64 Alignment;
+ BOOLEAN OverLap;
+ BOOLEAN Positive;
+ UINT32 MsrNum;
+ UINTN MtrrNumber;
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ UINT32 UsedMtrr;
+ UINT64 MtrrValidBitsMask;
+ UINT64 MtrrValidAddressMask;
+ UINTN Cr4;
+ BOOLEAN OverwriteExistingMtrr;
+ UINT32 FirmwareVariableMtrrCount;
+ UINT32 VariableMtrrEnd;
+
+ DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));
+
+ if (!IsMtrrSupported ()) {
+ Status = RETURN_UNSUPPORTED;
+ goto Done;
+ }
+
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
+ VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;
+
+ MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);
+
+ TempQword = 0;
+ MemoryType = (UINT64)Attribute;
+ OverwriteExistingMtrr = FALSE;
+
+ //
+ // Check for an invalid parameter
+ //
+ if (Length == 0) {
+ Status = RETURN_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (
+ (BaseAddress & ~MtrrValidAddressMask) != 0 ||
+ (Length & ~MtrrValidAddressMask) != 0
+ ) {
+ Status = RETURN_UNSUPPORTED;
+ goto Done;
+ }
+
+ //
+ // Check if Fixed MTRR
+ //
+ Status = RETURN_SUCCESS;
+ while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {
+ Cr4 = PreMtrrChange ();
+ Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);
+ PostMtrrChange (Cr4);
+ if (RETURN_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ if (Length == 0) {
+ //
+ // A Length of 0 can only make sense for fixed MTTR ranges.
+ // Since we just handled the fixed MTRRs, we can skip the
+ // variable MTRR section.
+ //
+ goto Done;
+ }
+
+ //
+ // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
+ // we can set the base to 0 to save variable MTRRs.
+ //
+ if (BaseAddress == BASE_1MB) {
+ BaseAddress = 0;
+ Length += SIZE_1MB;
+ }
+
+ //
+ // Check for overlap
+ //
+ UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);
+ OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);
+ if (OverLap) {
+ Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);
+ if (RETURN_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Length == 0) {
+ //
+ // Combined successfully, invalidate the now-unused MTRRs
+ //
+ InvalidateMtrr(VariableMtrr);
+ Status = RETURN_SUCCESS;
+ goto Done;
+ }
+ }
+
+ //
+ // The memory type is the same with the type specified by
+ // MTRR_LIB_IA32_MTRR_DEF_TYPE.
+ //
+ if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryType ())) {
+ //
+ // Invalidate the now-unused MTRRs
+ //
+ InvalidateMtrr(VariableMtrr);
+ goto Done;
+ }
+
+ Positive = GetMtrrNumberAndDirection (BaseAddress, Length, &MtrrNumber);
+
+ if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {
+ Status = RETURN_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Invalidate the now-unused MTRRs
+ //
+ InvalidateMtrr(VariableMtrr);
+
+ //
+ // Find first unused MTRR
+ //
+ for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;
+ MsrNum < VariableMtrrEnd;
+ MsrNum += 2
+ ) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ break;
+ }
+ }
+
+ if (BaseAddress != 0) {
+ do {
+ //
+ // Calculate the alignment of the base address.
+ //
+ Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));
+
+ if (Alignment > Length) {
+ break;
+ }
+
+ //
+ // Find unused MTRR
+ //
+ for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ break;
+ }
+ }
+
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Alignment,
+ MemoryType,
+ MtrrValidAddressMask
+ );
+ BaseAddress += Alignment;
+ Length -= Alignment;
+ } while (TRUE);
+
+ if (Length == 0) {
+ goto Done;
+ }
+ }
+
+ TempQword = Length;
+
+ if (!Positive) {
+ Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
+
+ //
+ // Find unused MTRR
+ //
+ for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ break;
+ }
+ }
+
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ MemoryType,
+ MtrrValidAddressMask
+ );
+ BaseAddress += Length;
+ TempQword = Length - TempQword;
+ MemoryType = MTRR_CACHE_UNCACHEABLE;
+ }
+
+ do {
+ //
+ // Find unused MTRR
+ //
+ for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ break;
+ }
+ }
+
+ Length = Power2MaxMemory (TempQword);
+ if (!Positive) {
+ BaseAddress -= Length;
+ }
+
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ MemoryType,
+ MtrrValidAddressMask
+ );
+
+ if (Positive) {
+ BaseAddress += Length;
+ }
+ TempQword -= Length;
+
+ } while (TempQword > 0);
+
+Done:
+ DEBUG((DEBUG_CACHE, " Status = %r\n", Status));
+ if (!RETURN_ERROR (Status)) {
+ MtrrDebugPrintAllMtrrs ();
+ }
+
+ return Status;
+}
+
+
+/**
+ This function will get the memory cache type of the specific address.
+
+ This function is mainly for debug purpose.
+
+ @param Address The specific address
+
+ @return Memory cache type of the sepcific address
+
+**/
+MTRR_MEMORY_CACHE_TYPE
+EFIAPI
+MtrrGetMemoryAttribute (
+ IN PHYSICAL_ADDRESS Address
+ )
+{
+ UINT64 TempQword;
+ UINTN Index;
+ UINTN SubIndex;
+ UINT64 MtrrType;
+ UINT64 TempMtrrType;
+ MTRR_MEMORY_CACHE_TYPE CacheType;
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ UINT64 MtrrValidBitsMask;
+ UINT64 MtrrValidAddressMask;
+ UINTN VariableMtrrCount;
+
+ if (!IsMtrrSupported ()) {
+ return CacheUncacheable;
+ }
+
+ //
+ // Check if MTRR is enabled, if not, return UC as attribute
+ //
+ TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);
+ MtrrType = MTRR_CACHE_INVALID_TYPE;
+
+ if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ return CacheUncacheable;
+ }
+
+ //
+ // If address is less than 1M, then try to go through the fixed MTRR
+ //
+ if (Address < BASE_1MB) {
+ if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) {
+ //
+ // Go through the fixed MTRR
+ //
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&
+ Address < (
+ mMtrrLibFixedMtrrTable[Index].BaseAddress +
+ (mMtrrLibFixedMtrrTable[Index].Length * 8)
+ )
+ ) {
+ SubIndex =
+ ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /
+ mMtrrLibFixedMtrrTable[Index].Length;
+ TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
+ MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF;
+ return GetMemoryCacheTypeFromMtrrType (MtrrType);
+ }
+ }
+ }
+ }
+ MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);
+ MtrrGetMemoryAttributeInVariableMtrr(
+ MtrrValidBitsMask,
+ MtrrValidAddressMask,
+ VariableMtrr
+ );
+
+ //
+ // Go through the variable MTRR
+ //
+ VariableMtrrCount = GetVariableMtrrCount ();
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ if (VariableMtrr[Index].Valid) {
+ if (Address >= VariableMtrr[Index].BaseAddress &&
+ Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {
+ TempMtrrType = VariableMtrr[Index].Type;
+ MtrrType = MtrrPrecedence (MtrrType, TempMtrrType);
+ }
+ }
+ }
+ CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType);
+
+ return CacheType;
+}
+
+
+/**
+ This function will get the raw value in variable MTRRs
+
+ @param VariableSettings A buffer to hold variable MTRRs content.
+
+ @return The VariableSettings input pointer
+
+**/
+MTRR_VARIABLE_SETTINGS*
+EFIAPI
+MtrrGetVariableMtrr (
+ OUT MTRR_VARIABLE_SETTINGS *VariableSettings
+ )
+{
+ UINT32 Index;
+ UINT32 VariableMtrrCount;
+
+ if (!IsMtrrSupported ()) {
+ return VariableSettings;
+ }
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ VariableSettings->Mtrr[Index].Base =
+ AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));
+ VariableSettings->Mtrr[Index].Mask =
+ AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);
+ }
+
+ return VariableSettings;
+}
+
+
+/**
+ Worker function setting variable MTRRs
+
+ @param VariableSettings A buffer to hold variable MTRRs content.
+
+**/
+VOID
+MtrrSetVariableMtrrWorker (
+ IN MTRR_VARIABLE_SETTINGS *VariableSettings
+ )
+{
+ UINT32 Index;
+ UINT32 VariableMtrrCount;
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ AsmWriteMsr64 (
+ MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),
+ VariableSettings->Mtrr[Index].Base
+ );
+ AsmWriteMsr64 (
+ MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1,
+ VariableSettings->Mtrr[Index].Mask
+ );
+ }
+}
+
+
+/**
+ This function sets variable MTRRs
+
+ @param VariableSettings A buffer to hold variable MTRRs content.
+
+ @return The pointer of VariableSettings
+
+**/
+MTRR_VARIABLE_SETTINGS*
+EFIAPI
+MtrrSetVariableMtrr (
+ IN MTRR_VARIABLE_SETTINGS *VariableSettings
+ )
+{
+ UINTN Cr4;
+
+ if (!IsMtrrSupported ()) {
+ return VariableSettings;
+ }
+
+ Cr4 = PreMtrrChange ();
+ MtrrSetVariableMtrrWorker (VariableSettings);
+ PostMtrrChange (Cr4);
+ return VariableSettings;
+}
+
+
+/**
+ This function gets the content in fixed MTRRs
+
+ @param FixedSettings A buffer to hold fixed Mtrrs content.
+
+ @retval The pointer of FixedSettings
+
+**/
+MTRR_FIXED_SETTINGS*
+EFIAPI
+MtrrGetFixedMtrr (
+ OUT MTRR_FIXED_SETTINGS *FixedSettings
+ )
+{
+ UINT32 Index;
+
+ if (!IsMtrrSupported ()) {
+ return FixedSettings;
+ }
+
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ FixedSettings->Mtrr[Index] =
+ AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
+ };
+
+ return FixedSettings;
+}
+
+/**
+ Worker function setting fixed MTRRs
+
+ @param FixedSettings A buffer to hold fixed Mtrrs content.
+
+**/
+VOID
+MtrrSetFixedMtrrWorker (
+ IN MTRR_FIXED_SETTINGS *FixedSettings
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ AsmWriteMsr64 (
+ mMtrrLibFixedMtrrTable[Index].Msr,
+ FixedSettings->Mtrr[Index]
+ );
+ }
+}
+
+
+/**
+ This function sets fixed MTRRs
+
+ @param FixedSettings A buffer to hold fixed Mtrrs content.
+
+ @retval The pointer of FixedSettings
+
+**/
+MTRR_FIXED_SETTINGS*
+EFIAPI
+MtrrSetFixedMtrr (
+ IN MTRR_FIXED_SETTINGS *FixedSettings
+ )
+{
+ UINTN Cr4;
+
+ if (!IsMtrrSupported ()) {
+ return FixedSettings;
+ }
+
+ Cr4 = PreMtrrChange ();
+ MtrrSetFixedMtrrWorker (FixedSettings);
+ PostMtrrChange (Cr4);
+
+ return FixedSettings;
+}
+
+
+/**
+ This function gets the content in all MTRRs (variable and fixed)
+
+ @param MtrrSetting A buffer to hold all Mtrrs content.
+
+ @retval the pointer of MtrrSetting
+
+**/
+MTRR_SETTINGS *
+EFIAPI
+MtrrGetAllMtrrs (
+ OUT MTRR_SETTINGS *MtrrSetting
+ )
+{
+ if (!IsMtrrSupported ()) {
+ return MtrrSetting;
+ }
+
+ //
+ // Get fixed MTRRs
+ //
+ MtrrGetFixedMtrr (&MtrrSetting->Fixed);
+
+ //
+ // Get variable MTRRs
+ //
+ MtrrGetVariableMtrr (&MtrrSetting->Variables);
+
+ //
+ // Get MTRR_DEF_TYPE value
+ //
+ MtrrSetting->MtrrDefType = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);
+
+ return MtrrSetting;
+}
+
+
+/**
+ This function sets all MTRRs (variable and fixed)
+
+ @param MtrrSetting A buffer holding all MTRRs content.
+
+ @retval The pointer of MtrrSetting
+
+**/
+MTRR_SETTINGS *
+EFIAPI
+MtrrSetAllMtrrs (
+ IN MTRR_SETTINGS *MtrrSetting
+ )
+{
+ UINTN Cr4;
+
+ if (!IsMtrrSupported ()) {
+ return MtrrSetting;
+ }
+
+ Cr4 = PreMtrrChange ();
+
+ //
+ // Set fixed MTRRs
+ //
+ MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed);
+
+ //
+ // Set variable MTRRs
+ //
+ MtrrSetVariableMtrrWorker (&MtrrSetting->Variables);
+
+ //
+ // Set MTRR_DEF_TYPE value
+ //
+ AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType);
+
+ PostMtrrChange (Cr4);
+
+ return MtrrSetting;
+}
+
+/**
+ This function prints all MTRRs for debugging.
+**/
+VOID
+EFIAPI
+MtrrDebugPrintAllMtrrs (
+ VOID
+ )
+{
+ DEBUG_CODE (
+ MTRR_SETTINGS MtrrSettings;
+ UINTN Index;
+ UINTN Index1;
+ UINTN VariableMtrrCount;
+ UINT64 Base;
+ UINT64 Limit;
+ UINT64 MtrrBase;
+ UINT64 MtrrLimit;
+ UINT64 RangeBase;
+ UINT64 RangeLimit;
+ UINT64 NoRangeBase;
+ UINT64 NoRangeLimit;
+ UINT32 RegEax;
+ UINTN MemoryType;
+ UINTN PreviousMemoryType;
+ BOOLEAN Found;
+
+ if (!IsMtrrSupported ()) {
+ return;
+ }
+
+ DEBUG((DEBUG_CACHE, "MTRR Settings\n"));
+ DEBUG((DEBUG_CACHE, "=============\n"));
+
+ MtrrGetAllMtrrs (&MtrrSettings);
+ DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", MtrrSettings.MtrrDefType));
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, MtrrSettings.Fixed.Mtrr[Index]));
+ }
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ DEBUG((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
+ Index,
+ MtrrSettings.Variables.Mtrr[Index].Base,
+ MtrrSettings.Variables.Mtrr[Index].Mask
+ ));
+ }
+ DEBUG((DEBUG_CACHE, "\n"));
+ DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));
+ DEBUG((DEBUG_CACHE, "====================================\n"));
+
+ Base = 0;
+ PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ Base = mMtrrLibFixedMtrrTable[Index].BaseAddress;
+ for (Index1 = 0; Index1 < 8; Index1++) {
+ MemoryType = (UINTN)(RShiftU64 (MtrrSettings.Fixed.Mtrr[Index], Index1 * 8) & 0xff);
+ if (MemoryType > CacheWriteBack) {
+ MemoryType = MTRR_CACHE_INVALID_TYPE;
+ }
+ if (MemoryType != PreviousMemoryType) {
+ if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
+ }
+ PreviousMemoryType = MemoryType;
+ DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));
+ }
+ Base += mMtrrLibFixedMtrrTable[Index].Length;
+ }
+ }
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+
+ Base = BASE_1MB;
+ PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;
+ do {
+ MemoryType = MtrrGetMemoryAttribute (Base);
+ if (MemoryType > CacheWriteBack) {
+ MemoryType = MTRR_CACHE_INVALID_TYPE;
+ }
+
+ if (MemoryType != PreviousMemoryType) {
+ if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
+ }
+ PreviousMemoryType = MemoryType;
+ DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));
+ }
+
+ RangeBase = BASE_1MB;
+ NoRangeBase = BASE_1MB;
+ Limit = BIT36 - 1;
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ Limit = LShiftU64 (1, RegEax & 0xff) - 1;
+ }
+ RangeLimit = Limit;
+ NoRangeLimit = Limit;
+
+ for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) {
+ if ((MtrrSettings.Variables.Mtrr[Index].Mask & BIT11) == 0) {
+ //
+ // If mask is not valid, then do not display range
+ //
+ continue;
+ }
+ MtrrBase = (MtrrSettings.Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1)));
+ MtrrLimit = MtrrBase + ((~(MtrrSettings.Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit);
+
+ if (Base >= MtrrBase && Base < MtrrLimit) {
+ Found = TRUE;
+ }
+
+ if (Base >= MtrrBase && MtrrBase > RangeBase) {
+ RangeBase = MtrrBase;
+ }
+ if (Base > MtrrLimit && MtrrLimit > RangeBase) {
+ RangeBase = MtrrLimit + 1;
+ }
+ if (Base < MtrrBase && MtrrBase < RangeLimit) {
+ RangeLimit = MtrrBase - 1;
+ }
+ if (Base < MtrrLimit && MtrrLimit <= RangeLimit) {
+ RangeLimit = MtrrLimit;
+ }
+
+ if (Base > MtrrLimit && NoRangeBase < MtrrLimit) {
+ NoRangeBase = MtrrLimit + 1;
+ }
+ if (Base < MtrrBase && NoRangeLimit > MtrrBase) {
+ NoRangeLimit = MtrrBase - 1;
+ }
+ }
+
+ if (Found) {
+ Base = RangeLimit + 1;
+ } else {
+ Base = NoRangeLimit + 1;
+ }
+ } while (Found);
+ DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1));
+ );
+}
+
+/**
+ Checks if MTRR is supported.
+
+ @retval TRUE MTRR is supported.
+ @retval FALSE MTRR is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+IsMtrrSupported (
+ VOID
+ )
+{
+ UINT32 RegEdx;
+ UINT64 MtrrCap;
+
+ //
+ // Check CPUID(1).EDX[12] for MTRR capability
+ //
+ AsmCpuid (1, NULL, NULL, NULL, &RegEdx);
+ if (BitFieldRead32 (RegEdx, 12, 12) == 0) {
+ return FALSE;
+ }
+
+ //
+ // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for
+ // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not
+ // exist, return false.
+ //
+ MtrrCap = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP);
+ if ((BitFieldRead64 (MtrrCap, 0, 7) == 0) || (BitFieldRead64 (MtrrCap, 8, 8) == 0)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf b/CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
new file mode 100755
index 0000000000..ef4a596512
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
@@ -0,0 +1,41 @@
+## @file
+# MTRR library provides API for MTRR operation
+#
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MtrrLib
+ FILE_GUID = 6826b408-f4f3-47ee-917f-af7047f9d937
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MtrrLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ MtrrLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ BaseLib
+ CpuLib
+
diff --git a/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/IpfTimerLib.c b/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/IpfTimerLib.c
new file mode 100755
index 0000000000..714b99eec4
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/IpfTimerLib.c
@@ -0,0 +1,216 @@
+/** @file
+ Timer Library functions built upon ITC on IPF.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include
+#include
+#include
+#include
+
+
+/**
+ Performs a delay measured as number of ticks.
+
+ An internal function to perform a delay measured as number of ticks. It's
+ invoked by MicroSecondDelay() and NanoSecondDelay().
+
+ @param Delay The number of ticks to delay.
+
+**/
+VOID
+EFIAPI
+InternalIpfDelay (
+ IN INT64 Delay
+ )
+{
+ INT64 Ticks;
+
+ //
+ // The target timer count is calculated here
+ //
+ Ticks = (INT64)AsmReadItc () + Delay;
+
+ //
+ // Wait until time out
+ // Delay > 2^63 could not be handled by this function
+ // Timer wrap-arounds are handled correctly by this function
+ //
+ while (Ticks - (INT64)AsmReadItc() >= 0);
+}
+
+/**
+ Stalls the CPU for at least the given number of microseconds.
+
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param MicroSeconds The minimum number of microseconds to delay.
+
+ @return The value of MicroSeconds inputted.
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+ InternalIpfDelay (
+ GetPerformanceCounterProperties (NULL, NULL) *
+ MicroSeconds /
+ 1000000
+ );
+ return MicroSeconds;
+}
+
+/**
+ Stalls the CPU for at least the given number of nanoseconds.
+
+ Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+ @param NanoSeconds The minimum number of nanoseconds to delay.
+
+ @return The value of NanoSeconds inputted.
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+ IN UINTN NanoSeconds
+ )
+{
+ InternalIpfDelay (
+ GetPerformanceCounterProperties (NULL, NULL) *
+ NanoSeconds /
+ 1000000000
+ );
+ return NanoSeconds;
+}
+
+/**
+ Retrieves the current value of a 64-bit free running performance counter.
+
+ The counter can either count up by 1 or count down by 1. If the physical
+ performance counter counts by a larger increment, then the counter values
+ must be translated. The properties of the counter can be retrieved from
+ GetPerformanceCounterProperties().
+
+ @return The current value of the free running performance counter.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounter (
+ VOID
+ )
+{
+ return AsmReadItc ();
+}
+
+/**
+ Retrieves the 64-bit frequency in Hz and the range of performance counter
+ values.
+
+ If StartValue is not NULL, then the value that the performance counter starts
+ with immediately after is it rolls over is returned in StartValue. If
+ EndValue is not NULL, then the value that the performance counter end with
+ immediately before it rolls over is returned in EndValue. The 64-bit
+ frequency of the performance counter in Hz is always returned. If StartValue
+ is less than EndValue, then the performance counter counts up. If StartValue
+ is greater than EndValue, then the performance counter counts down. For
+ example, a 64-bit free running counter that counts up would have a StartValue
+ of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+ that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+ @param StartValue The value the performance counter starts with when it
+ rolls over.
+ @param EndValue The value that the performance counter ends with before
+ it rolls over.
+
+ @return The frequency in Hz.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+ OUT UINT64 *StartValue, OPTIONAL
+ OUT UINT64 *EndValue OPTIONAL
+ )
+{
+ PAL_CALL_RETURN PalRet;
+ UINT64 BaseFrequence;
+
+ if (StartValue != NULL) {
+ *StartValue = 0;
+ }
+
+ if (EndValue != NULL) {
+ *EndValue = (UINT64)(-1);
+ }
+
+ PalRet = PalCall (PAL_FREQ_BASE, 0, 0, 0);
+ if (PalRet.Status != 0) {
+ return 1000000;
+ }
+ BaseFrequence = PalRet.r9;
+
+ PalRet = PalCall (PAL_FREQ_RATIOS, 0, 0, 0);
+ if (PalRet.Status != 0) {
+ return 1000000;
+ }
+
+ return BaseFrequence * (PalRet.r11 >> 32) / (UINT32)PalRet.r11;
+}
+
+/**
+ Converts elapsed ticks of performance counter to time in nanoseconds.
+
+ This function converts the elapsed ticks of running performance counter to
+ time value in unit of nanoseconds.
+
+ @param Ticks The number of elapsed ticks of running performance counter.
+
+ @return The elapsed time in nanoseconds.
+
+**/
+UINT64
+EFIAPI
+GetTimeInNanoSecond (
+ IN UINT64 Ticks
+ )
+{
+ UINT64 Frequency;
+ UINT64 NanoSeconds;
+ UINT64 Remainder;
+ INTN Shift;
+
+ Frequency = GetPerformanceCounterProperties (NULL, NULL);
+
+ //
+ // Ticks
+ // Time = --------- x 1,000,000,000
+ // Frequency
+ //
+ NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
+
+ //
+ // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
+ // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
+ // i.e. highest bit set in Remainder should <= 33.
+ //
+ Shift = MAX (0, HighBitSet64 (Remainder) - 33);
+ Remainder = RShiftU64 (Remainder, (UINTN) Shift);
+ Frequency = RShiftU64 (Frequency, (UINTN) Shift);
+ NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
+
+ return NanoSeconds;
+}
diff --git a/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf b/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
new file mode 100755
index 0000000000..91566c6473
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
@@ -0,0 +1,63 @@
+## @file
+# Instance of Timer Library only using CPU resources.
+#
+# Timer Library that only uses CPU resources to provide calibrated delays
+# on IA-32, x64, and IPF.
+# Note: Because CPU Local APIC and ITC could be programmed by OS, it cannot be
+# used by SMM drivers and runtime drivers, ACPI timer is recommended for SMM
+# drivers and runtime drivers.
+#
+# This library differs with the SecPeiDxeTimerLibCpu library in the MdePkg in
+# that it uses the local APIC library so that it supports x2APIC mode.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecPeiDxeTimerLibUefiCpu
+ FILE_GUID = 4FFF2014-2086-4ee6-9B58-886D1967861C
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TimerLib|BASE DXE_CORE DXE_DRIVER DXE_SAL_DRIVER PEIM PEI_CORE SEC UEFI_APPLICATION UEFI_DRIVER
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[Sources.Ia32, Sources.X64]
+ X86TimerLib.c
+
+[Sources.IPF]
+ IpfTimerLib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ PcdLib
+ DebugLib
+ LocalApicLib
+
+[LibraryClasses.IPF]
+ PalLib
+
+
+[Pcd.IA32, Pcd.X64]
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES
+
diff --git a/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/X86TimerLib.c b/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/X86TimerLib.c
new file mode 100755
index 0000000000..99f8121eed
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/X86TimerLib.c
@@ -0,0 +1,239 @@
+/** @file
+ Timer Library functions built upon local APIC on IA32/x64.
+
+ This library uses the local APIC library so that it supports x2APIC mode.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ 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.
+
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ Internal function to return the frequency of the local APIC timer.
+
+ @return The frequency of the timer in Hz.
+
+**/
+UINT32
+EFIAPI
+InternalX86GetTimerFrequency (
+ VOID
+ )
+{
+ UINTN Divisor;
+
+ GetApicTimerState (&Divisor, NULL, NULL);
+ return PcdGet32(PcdFSBClock) / (UINT32)Divisor;
+}
+
+/**
+ Stalls the CPU for at least the given number of ticks.
+
+ Stalls the CPU for at least the given number of ticks. It's invoked by
+ MicroSecondDelay() and NanoSecondDelay().
+
+ @param Delay A period of time to delay in ticks.
+
+**/
+VOID
+EFIAPI
+InternalX86Delay (
+ IN UINT32 Delay
+ )
+{
+ INT32 Ticks;
+ UINT32 PowerOfTwoCounter;
+
+ //
+ // The target timer count is calculated here
+ //
+ Ticks = GetApicTimerCurrentCount () - Delay;
+
+ //
+ // Wait until time out
+ // Delay > 2^31 could not be handled by this function
+ // Timer wrap-arounds are handled correctly by this function
+ //
+ PowerOfTwoCounter = GetPowerOfTwo32 (GetApicTimerInitCount ());
+ while (((UINT32)(GetApicTimerCurrentCount () - Ticks) & PowerOfTwoCounter) == 0) {
+ CpuPause ();
+ }
+}
+
+/**
+ Stalls the CPU for at least the given number of microseconds.
+
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param MicroSeconds The minimum number of microseconds to delay.
+
+ @return The value of MicroSeconds inputted.
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+ InternalX86Delay (
+ (UINT32)DivU64x32 (
+ MultU64x64 (
+ InternalX86GetTimerFrequency (),
+ MicroSeconds
+ ),
+ 1000000u
+ )
+ );
+ return MicroSeconds;
+}
+
+/**
+ Stalls the CPU for at least the given number of nanoseconds.
+
+ Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+ @param NanoSeconds The minimum number of nanoseconds to delay.
+
+ @return The value of NanoSeconds inputted.
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+ IN UINTN NanoSeconds
+ )
+{
+ InternalX86Delay (
+ (UINT32)DivU64x32 (
+ MultU64x64 (
+ InternalX86GetTimerFrequency (),
+ NanoSeconds
+ ),
+ 1000000000u
+ )
+ );
+ return NanoSeconds;
+}
+
+/**
+ Retrieves the current value of a 64-bit free running performance counter.
+
+ The counter can either count up by 1 or count down by 1. If the physical
+ performance counter counts by a larger increment, then the counter values
+ must be translated. The properties of the counter can be retrieved from
+ GetPerformanceCounterProperties().
+
+ @return The current value of the free running performance counter.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounter (
+ VOID
+ )
+{
+ return (UINT64)GetApicTimerCurrentCount ();
+}
+
+/**
+ Retrieves the 64-bit frequency in Hz and the range of performance counter
+ values.
+
+ If StartValue is not NULL, then the value that the performance counter starts
+ with immediately after is it rolls over is returned in StartValue. If
+ EndValue is not NULL, then the value that the performance counter end with
+ immediately before it rolls over is returned in EndValue. The 64-bit
+ frequency of the performance counter in Hz is always returned. If StartValue
+ is less than EndValue, then the performance counter counts up. If StartValue
+ is greater than EndValue, then the performance counter counts down. For
+ example, a 64-bit free running counter that counts up would have a StartValue
+ of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+ that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+ @param StartValue The value the performance counter starts with when it
+ rolls over.
+ @param EndValue The value that the performance counter ends with before
+ it rolls over.
+
+ @return The frequency in Hz.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+ OUT UINT64 *StartValue, OPTIONAL
+ OUT UINT64 *EndValue OPTIONAL
+ )
+{
+ if (StartValue != NULL) {
+ *StartValue = (UINT64)GetApicTimerInitCount ();
+ //
+ // make sure StartValue is all 1s from High Bit
+ //
+ ASSERT ((*StartValue & (*StartValue + 1)) == 0);
+ }
+
+ if (EndValue != NULL) {
+ *EndValue = 0;
+ }
+
+ return (UINT64) InternalX86GetTimerFrequency ();
+}
+
+/**
+ Converts elapsed ticks of performance counter to time in nanoseconds.
+
+ This function converts the elapsed ticks of running performance counter to
+ time value in unit of nanoseconds.
+
+ @param Ticks The number of elapsed ticks of running performance counter.
+
+ @return The elapsed time in nanoseconds.
+
+**/
+UINT64
+EFIAPI
+GetTimeInNanoSecond (
+ IN UINT64 Ticks
+ )
+{
+ UINT64 Frequency;
+ UINT64 NanoSeconds;
+ UINT64 Remainder;
+ INTN Shift;
+
+ Frequency = GetPerformanceCounterProperties (NULL, NULL);
+
+ //
+ // Ticks
+ // Time = --------- x 1,000,000,000
+ // Frequency
+ //
+ NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
+
+ //
+ // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
+ // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
+ // i.e. highest bit set in Remainder should <= 33.
+ //
+ Shift = MAX (0, HighBitSet64 (Remainder) - 33);
+ Remainder = RShiftU64 (Remainder, (UINTN) Shift);
+ Frequency = RShiftU64 (Frequency, (UINTN) Shift);
+ NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
+
+ return NanoSeconds;
+}
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.port80.raw b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.port80.raw
new file mode 100755
index 0000000000..ec6bcfd48b
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.port80.raw differ
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.raw b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.raw
new file mode 100755
index 0000000000..02cb66c848
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.raw differ
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.serial.raw b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.serial.raw
new file mode 100755
index 0000000000..58542ad9d1
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.ia32.serial.raw differ
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
new file mode 100755
index 0000000000..63e1e2cf56
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
@@ -0,0 +1,33 @@
+## @file
+# Reset Vector binary
+#
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ResetVector
+ FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.1
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Binaries.Ia32]
+ RAW|ResetVector.ia32.raw|*
+
+[Binaries.X64]
+ RAW|ResetVector.x64.raw|*
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.port80.raw b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.port80.raw
new file mode 100755
index 0000000000..393b6ef2ca
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.port80.raw differ
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.raw b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.raw
new file mode 100755
index 0000000000..7ab1161a21
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.raw differ
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.serial.raw b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.serial.raw
new file mode 100755
index 0000000000..f32e81ac12
Binary files /dev/null and b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.x64.serial.raw differ
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Build.py b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Build.py
new file mode 100755
index 0000000000..dad257c16a
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Build.py
@@ -0,0 +1,53 @@
+## @file
+# Automate the process of building the various reset vector types
+#
+# Copyright (c) 2009, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+
+import glob
+import os
+import subprocess
+import sys
+
+def RunCommand(commandLine):
+ #print ' '.join(commandLine)
+ return subprocess.call(commandLine)
+
+for filename in glob.glob(os.path.join('Bin', '*.raw')):
+ os.remove(filename)
+
+for arch in ('ia32', 'x64'):
+ for debugType in (None, 'port80', 'serial'):
+ output = os.path.join('Bin', 'ResetVector')
+ output += '.' + arch
+ if debugType is not None:
+ output += '.' + debugType
+ output += '.raw'
+ commandLine = (
+ 'nasm',
+ '-D', 'ARCH_%s' % arch.upper(),
+ '-D', 'DEBUG_%s' % str(debugType).upper(),
+ '-o', output,
+ 'ResetVectorCode.asm',
+ )
+ ret = RunCommand(commandLine)
+ print '\tASM\t' + output
+ if ret != 0: sys.exit(ret)
+
+ commandLine = (
+ 'python',
+ 'Tools/FixupForRawSection.py',
+ output,
+ )
+ print '\tFIXUP\t' + output
+ ret = RunCommand(commandLine)
+ if ret != 0: sys.exit(ret)
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/CommonMacros.inc b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/CommonMacros.inc
new file mode 100755
index 0000000000..b46da27686
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/CommonMacros.inc
@@ -0,0 +1,31 @@
+;------------------------------------------------------------------------------
+; @file
+; Common macros used in the ResetVector VTF module.
+;
+; Copyright (c) 2008, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+%define ADDR16_OF(x) (0x10000 - fourGigabytes + x)
+%define ADDR_OF(x) (0x100000000 - fourGigabytes + x)
+
+%macro OneTimeCall 1
+ jmp %1
+%1 %+ OneTimerCallReturn:
+%endmacro
+
+%macro OneTimeCallRet 1
+ jmp %1 %+ OneTimerCallReturn
+%endmacro
+
+StartOfResetVectorCode:
+
+%define ADDR_OF_START_OF_RESET_CODE ADDR_OF(StartOfResetVectorCode)
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/DebugDisabled.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/DebugDisabled.asm
new file mode 100755
index 0000000000..883cef03e0
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/DebugDisabled.asm
@@ -0,0 +1,26 @@
+;------------------------------------------------------------------------------
+; @file
+; Debug disabled
+;
+; Copyright (c) 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+BITS 16
+
+%macro debugInitialize 0
+ ;
+ ; No initialization is required
+ ;
+%endmacro
+
+%macro debugShowPostCode 1
+%endmacro
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
new file mode 100755
index 0000000000..226c49f220
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
@@ -0,0 +1,48 @@
+;------------------------------------------------------------------------------
+; @file
+; 16-bit initialization code
+;
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+
+BITS 16
+
+;
+; @param[out] DI 'BP' to indicate boot-strap processor
+;
+EarlyBspInitReal16:
+ mov di, 'BP'
+ jmp short Main16
+
+;
+; @param[out] DI 'AP' to indicate application processor
+;
+EarlyApInitReal16:
+ mov di, 'AP'
+ jmp short Main16
+
+;
+; Modified: EAX
+;
+; @param[in] EAX Initial value of the EAX register (BIST: Built-in Self Test)
+; @param[out] ESP Initial value of the EAX register (BIST: Built-in Self Test)
+;
+EarlyInit16:
+ ;
+ ; ESP - Initial value of the EAX register (BIST: Built-in Self Test)
+ ;
+ mov esp, eax
+
+ debugInitialize
+
+ OneTimeCallRet EarlyInit16
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
new file mode 100755
index 0000000000..146df600a6
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
@@ -0,0 +1,133 @@
+;------------------------------------------------------------------------------
+; @file
+; Transition from 16 bit real mode into 32 bit flat protected mode
+;
+; Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+%define SEC_DEFAULT_CR0 0x40000023
+%define SEC_DEFAULT_CR4 0x640
+
+BITS 16
+
+;
+; Modified: EAX, EBX
+;
+TransitionFromReal16To32BitFlat:
+
+ debugShowPostCode POSTCODE_16BIT_MODE
+
+ cli
+
+ mov bx, 0xf000
+ mov ds, bx
+
+ mov bx, ADDR16_OF(gdtr)
+
+o32 lgdt [cs:bx]
+
+ mov eax, SEC_DEFAULT_CR0
+ mov cr0, eax
+
+ jmp LINEAR_CODE_SEL:dword ADDR_OF(jumpTo32BitAndLandHere)
+BITS 32
+jumpTo32BitAndLandHere:
+
+ mov eax, SEC_DEFAULT_CR4
+ mov cr4, eax
+
+ debugShowPostCode POSTCODE_32BIT_MODE
+
+ mov ax, LINEAR_SEL
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ OneTimeCallRet TransitionFromReal16To32BitFlat
+
+ALIGN 2
+
+gdtr:
+ dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd ADDR_OF(GDT_BASE)
+
+ALIGN 16
+
+;
+; Macros for GDT entries
+;
+
+%define PRESENT_FLAG(p) (p << 7)
+%define DPL(dpl) (dpl << 5)
+%define SYSTEM_FLAG(s) (s << 4)
+%define DESC_TYPE(t) (t)
+
+; Type: data, expand-up, writable, accessed
+%define DATA32_TYPE 3
+
+; Type: execute, readable, expand-up, accessed
+%define CODE32_TYPE 0xb
+
+; Type: execute, readable, expand-up, accessed
+%define CODE64_TYPE 0xb
+
+%define GRANULARITY_FLAG(g) (g << 7)
+%define DEFAULT_SIZE32(d) (d << 6)
+%define CODE64_FLAG(l) (l << 5)
+%define UPPER_LIMIT(l) (l)
+
+;
+; The Global Descriptor Table (GDT)
+;
+
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ DW 0 ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB 0 ; sys flag, dpl, type
+ DB 0 ; limit 19:16, flags
+ DB 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ DW 0xffff ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE)
+ DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+ DB 0 ; base 31:24
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ DW 0xffff ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)
+ DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+ DB 0 ; base 31:24
+
+%ifdef ARCH_X64
+; linear code (64-bit) segment descriptor
+LINEAR_CODE64_SEL equ $-GDT_BASE
+ DW 0xffff ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE)
+ DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf)
+ DB 0 ; base 31:24
+%endif
+
+GDT_END:
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
new file mode 100755
index 0000000000..d0830ec87c
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
@@ -0,0 +1,58 @@
+;------------------------------------------------------------------------------
+; @file
+; First code exectuted by processor after resetting.
+;
+; Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+BITS 16
+
+ALIGN 16
+
+applicationProcessorEntryPoint:
+;
+; Application Processors entry point
+;
+; GenFv generates code aligned on a 4k boundary which will jump to this
+; location. (0xffffffe0) This allows the Local APIC Startup IPI to be
+; used to wake up the application processors.
+;
+ jmp short EarlyApInitReal16
+
+ALIGN 8
+
+ DD 0
+
+;
+; The VTF signature
+;
+; VTF-0 means that the VTF (Volume Top File) code does not require
+; any fixups.
+;
+vtfSignature:
+ DB 'V', 'T', 'F', 0
+
+ALIGN 16
+
+resetVector:
+;
+; Reset Vector
+;
+; This is where the processor will begin execution
+;
+ nop
+ nop
+ jmp short EarlyBspInitReal16
+
+ALIGN 16
+
+fourGigabytes:
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm
new file mode 100755
index 0000000000..9eba864c28
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm
@@ -0,0 +1,46 @@
+;------------------------------------------------------------------------------
+; @file
+; Transition from 32 bit flat protected mode into 64 bit flat protected mode
+;
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+BITS 32
+
+;
+; Modified: EAX
+;
+Transition32FlatTo64Flat:
+
+ mov eax, ((ADDR_OF_START_OF_RESET_CODE & ~0xfff) - 0x1000)
+ mov cr3, eax
+
+ mov eax, cr4
+ bts eax, 5 ; enable PAE
+ mov cr4, eax
+
+ mov ecx, 0xc0000080
+ rdmsr
+ bts eax, 8 ; set LME
+ wrmsr
+
+ mov eax, cr0
+ bts eax, 31 ; set PG
+ mov cr0, eax ; enable paging
+
+ jmp LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere)
+BITS 64
+jumpTo64BitAndLandHere:
+
+ debugShowPostCode POSTCODE_64BIT_MODE
+
+ OneTimeCallRet Transition32FlatTo64Flat
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForBfvBase.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForBfvBase.asm
new file mode 100755
index 0000000000..d0c2d8c39c
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForBfvBase.asm
@@ -0,0 +1,86 @@
+;------------------------------------------------------------------------------
+; @file
+; Search for the Boot Firmware Volume (BFV) base address
+;
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+;#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \
+; { 0x8c8ce578, 0x8a3d, 0x4f1c, { 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } }
+%define FFS_GUID_DWORD0 0x8c8ce578
+%define FFS_GUID_DWORD1 0x4f1c8a3d
+%define FFS_GUID_DWORD2 0x61893599
+%define FFS_GUID_DWORD3 0xd32dc385
+
+BITS 32
+
+;
+; Modified: EAX, EBX
+; Preserved: EDI, ESP
+;
+; @param[out] EBP Address of Boot Firmware Volume (BFV)
+;
+Flat32SearchForBfvBase:
+
+ xor eax, eax
+searchingForBfvHeaderLoop:
+ ;
+ ; We check for a firmware volume at every 4KB address in the top 16MB
+ ; just below 4GB. (Addresses at 0xffHHH000 where H is any hex digit.)
+ ;
+ sub eax, 0x1000
+ cmp eax, 0xff000000
+ jb searchedForBfvHeaderButNotFound
+
+ ;
+ ; Check FFS GUID
+ ;
+ cmp dword [eax + 0x10], FFS_GUID_DWORD0
+ jne searchingForBfvHeaderLoop
+ cmp dword [eax + 0x14], FFS_GUID_DWORD1
+ jne searchingForBfvHeaderLoop
+ cmp dword [eax + 0x18], FFS_GUID_DWORD2
+ jne searchingForBfvHeaderLoop
+ cmp dword [eax + 0x1c], FFS_GUID_DWORD3
+ jne searchingForBfvHeaderLoop
+
+ ;
+ ; Check FV Length
+ ;
+ cmp dword [eax + 0x24], 0
+ jne searchingForBfvHeaderLoop
+ mov ebx, eax
+ add ebx, dword [eax + 0x20]
+ jnz searchingForBfvHeaderLoop
+
+ jmp searchedForBfvHeaderAndItWasFound
+
+searchedForBfvHeaderButNotFound:
+ ;
+ ; Hang if the SEC entry point was not found
+ ;
+ debugShowPostCode POSTCODE_BFV_NOT_FOUND
+
+ ;
+ ; 0xbfbfbfbf in the EAX & EBP registers helps signal what failed
+ ; for debugging purposes.
+ ;
+ mov eax, 0xBFBFBFBF
+ mov ebp, eax
+ jmp $
+
+searchedForBfvHeaderAndItWasFound:
+ mov ebp, eax
+
+ debugShowPostCode POSTCODE_BFV_FOUND
+
+ OneTimeCallRet Flat32SearchForBfvBase
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm
new file mode 100755
index 0000000000..9558b9d350
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm
@@ -0,0 +1,196 @@
+;------------------------------------------------------------------------------
+; @file
+; Search for the SEC Core entry point
+;
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+BITS 32
+
+%define EFI_FV_FILETYPE_SECURITY_CORE 0x03
+
+;
+; Modified: EAX, EBX, ECX, EDX
+; Preserved: EDI, EBP, ESP
+;
+; @param[in] EBP Address of Boot Firmware Volume (BFV)
+; @param[out] ESI SEC Core Entry Point Address
+;
+Flat32SearchForSecEntryPoint:
+
+ ;
+ ; Initialize EBP and ESI to 0
+ ;
+ xor ebx, ebx
+ mov esi, ebx
+
+ ;
+ ; Pass over the BFV header
+ ;
+ mov eax, ebp
+ mov bx, [ebp + 0x30]
+ add eax, ebx
+ jc secEntryPointWasNotFound
+
+ jmp searchingForFfsFileHeaderLoop
+
+moveForwardWhileSearchingForFfsFileHeaderLoop:
+ ;
+ ; Make forward progress in the search
+ ;
+ inc eax
+ jc secEntryPointWasNotFound
+
+searchingForFfsFileHeaderLoop:
+ test eax, eax
+ jz secEntryPointWasNotFound
+
+ ;
+ ; Ensure 8 byte alignment
+ ;
+ add eax, 7
+ jc secEntryPointWasNotFound
+ and al, 0xf8
+
+ ;
+ ; Look to see if there is an FFS file at eax
+ ;
+ mov bl, [eax + 0x17]
+ test bl, 0x20
+ jz moveForwardWhileSearchingForFfsFileHeaderLoop
+ mov ecx, [eax + 0x14]
+ and ecx, 0x00ffffff
+ or ecx, ecx
+ jz moveForwardWhileSearchingForFfsFileHeaderLoop
+ add ecx, eax
+ jz jumpSinceWeFoundTheLastFfsFile
+ jc moveForwardWhileSearchingForFfsFileHeaderLoop
+jumpSinceWeFoundTheLastFfsFile:
+
+ ;
+ ; There seems to be a valid file at eax
+ ;
+ cmp byte [eax + 0x12], EFI_FV_FILETYPE_SECURITY_CORE ; Check File Type
+ jne readyToTryFfsFileAtEcx
+
+fileTypeIsSecCore:
+ OneTimeCall GetEntryPointOfFfsFile
+ test eax, eax
+ jnz doneSeachingForSecEntryPoint
+
+readyToTryFfsFileAtEcx:
+ ;
+ ; Try the next FFS file at ECX
+ ;
+ mov eax, ecx
+ jmp searchingForFfsFileHeaderLoop
+
+secEntryPointWasNotFound:
+ xor eax, eax
+
+doneSeachingForSecEntryPoint:
+ mov esi, eax
+
+ test esi, esi
+ jnz secCoreEntryPointWasFound
+
+secCoreEntryPointWasNotFound:
+ ;
+ ; Hang if the SEC entry point was not found
+ ;
+ debugShowPostCode POSTCODE_SEC_NOT_FOUND
+ jz $
+
+secCoreEntryPointWasFound:
+ debugShowPostCode POSTCODE_SEC_FOUND
+
+ OneTimeCallRet Flat32SearchForSecEntryPoint
+
+%define EFI_SECTION_PE32 0x10
+
+;
+; Input:
+; EAX - Start of FFS file
+; ECX - End of FFS file
+;
+; Output:
+; EAX - Entry point of PE32 (or 0 if not found)
+;
+; Modified:
+; EBX
+;
+GetEntryPointOfFfsFile:
+ test eax, eax
+ jz getEntryPointOfFfsFileErrorReturn
+ add eax, 0x18 ; EAX = Start of section
+
+getEntryPointOfFfsFileLoopForSections:
+ cmp eax, ecx
+ jae getEntryPointOfFfsFileErrorReturn
+
+ cmp byte [eax + 3], EFI_SECTION_PE32
+ je getEntryPointOfFfsFileFoundPe32Section
+
+ ;
+ ; The section type was not PE32, so move to next section
+ ;
+ mov ebx, dword [eax]
+ and ebx, 0x00ffffff
+ add eax, ebx
+ jc getEntryPointOfFfsFileErrorReturn
+
+ ;
+ ; Ensure that FFS section is 32-bit aligned
+ ;
+ add eax, 3
+ jc getEntryPointOfFfsFileErrorReturn
+ and al, 0xfc
+ jmp getEntryPointOfFfsFileLoopForSections
+
+getEntryPointOfFfsFileFoundPe32Section:
+ add eax, 4 ; EAX = Start of PE32 image
+
+ mov ebx, eax
+ cmp word [eax], 'MZ'
+ jne thereIsNotAnMzSignature
+ movzx ebx, word [eax + 0x3c]
+ add ebx, eax
+thereIsNotAnMzSignature:
+
+ ; if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE)
+ cmp word [ebx], 'VZ'
+ jne thereIsNoVzSignature
+ ; *EntryPoint = (VOID *)((UINTN)Pe32Data +
+ ; (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) +
+ ; sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
+ add eax, [ebx + 0x8]
+ add eax, 0x28
+ movzx ebx, word [ebx + 0x6]
+ sub eax, ebx
+ jmp getEntryPointOfFfsFileReturn
+
+thereIsNoVzSignature:
+
+ ; if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)
+ cmp dword [ebx], `PE\x00\x00`
+ jne getEntryPointOfFfsFileErrorReturn
+
+ ; *EntryPoint = (VOID *)((UINTN)Pe32Data +
+ ; (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
+ add eax, [ebx + 0x4 + 0x14 + 0x10]
+ jmp getEntryPointOfFfsFileReturn
+
+getEntryPointOfFfsFileErrorReturn:
+ mov eax, 0
+
+getEntryPointOfFfsFileReturn:
+ OneTimeCallRet GetEntryPointOfFfsFile
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Main.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Main.asm
new file mode 100755
index 0000000000..ebfb9015d4
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Main.asm
@@ -0,0 +1,106 @@
+;------------------------------------------------------------------------------
+; @file
+; Main routine of the pre-SEC code up through the jump into SEC
+;
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+
+BITS 16
+
+;
+; Modified: EBX, ECX, EDX, EBP
+;
+; @param[in,out] RAX/EAX Initial value of the EAX register
+; (BIST: Built-in Self Test)
+; @param[in,out] DI 'BP': boot-strap processor, or
+; 'AP': application processor
+; @param[out] RBP/EBP Address of Boot Firmware Volume (BFV)
+;
+; @return None This routine jumps to SEC and does not return
+;
+Main16:
+ OneTimeCall EarlyInit16
+
+ ;
+ ; Transition the processor from 16-bit real mode to 32-bit flat mode
+ ;
+ OneTimeCall TransitionFromReal16To32BitFlat
+
+BITS 32
+
+ ;
+ ; Search for the Boot Firmware Volume (BFV)
+ ;
+ OneTimeCall Flat32SearchForBfvBase
+
+ ;
+ ; EBP - Start of BFV
+ ;
+
+ ;
+ ; Search for the SEC entry point
+ ;
+ OneTimeCall Flat32SearchForSecEntryPoint
+
+ ;
+ ; ESI - SEC Core entry point
+ ; EBP - Start of BFV
+ ;
+
+%ifdef ARCH_IA32
+
+ ;
+ ; Restore initial EAX value into the EAX register
+ ;
+ mov eax, esp
+
+ ;
+ ; Jump to the 32-bit SEC entry point
+ ;
+ jmp esi
+
+%else
+
+ ;
+ ; Transition the processor from 32-bit flat mode to 64-bit flat mode
+ ;
+ OneTimeCall Transition32FlatTo64Flat
+
+BITS 64
+
+ ;
+ ; Some values were calculated in 32-bit mode. Make sure the upper
+ ; 32-bits of 64-bit registers are zero for these values.
+ ;
+ mov rax, 0x00000000ffffffff
+ and rsi, rax
+ and rbp, rax
+ and rsp, rax
+
+ ;
+ ; RSI - SEC Core entry point
+ ; RBP - Start of BFV
+ ;
+
+ ;
+ ; Restore initial EAX value into the RAX register
+ ;
+ mov rax, rsp
+
+ ;
+ ; Jump to the 64-bit SEC entry point
+ ;
+ jmp rsi
+
+%endif
+
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Port80Debug.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Port80Debug.asm
new file mode 100755
index 0000000000..4b13c4860b
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Port80Debug.asm
@@ -0,0 +1,28 @@
+;------------------------------------------------------------------------------
+; @file
+; Port 0x80 debug support macros
+;
+; Copyright (c) 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+BITS 16
+
+%macro debugInitialize 0
+ ;
+ ; No initialization is required
+ ;
+%endmacro
+
+%macro debugShowPostCode 1
+ mov al, %1
+ out 0x80, al
+%endmacro
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc
new file mode 100755
index 0000000000..62eda5d992
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc
@@ -0,0 +1,25 @@
+;------------------------------------------------------------------------------
+; @file
+; Definitions of POST CODES for the reset vector module
+;
+; Copyright (c) 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+%define POSTCODE_16BIT_MODE 0x16
+%define POSTCODE_32BIT_MODE 0x32
+%define POSTCODE_64BIT_MODE 0x64
+
+%define POSTCODE_BFV_NOT_FOUND 0xb0
+%define POSTCODE_BFV_FOUND 0xb1
+
+%define POSTCODE_SEC_NOT_FOUND 0xf0
+%define POSTCODE_SEC_FOUND 0xf1
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/ReadMe.txt b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/ReadMe.txt
new file mode 100755
index 0000000000..1b3d6643e5
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/ReadMe.txt
@@ -0,0 +1,41 @@
+
+=== HOW TO USE VTF0 ===
+
+Add this line to your FDF FV section:
+INF RuleOverride=RESET_VECTOR USE = IA32 CloverEFI/UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
+(For X64 SEC/PEI change IA32 to X64 => 'USE = X64')
+
+In your FDF FFS file rules sections add:
+[Rule.Common.SEC.RESET_VECTOR]
+ FILE RAW = $(NAMED_GUID) {
+ RAW RAW |.raw
+ }
+
+=== VTF0 Boot Flow ===
+
+1. Transition to IA32 flat mode
+2. Locate BFV (Boot Firmware Volume) by checking every 4kb boundary
+3. Locate SEC image
+4. X64 VTF0 transitions to X64 mode
+5. Call SEC image entry point
+
+== VTF0 SEC input parameters ==
+
+All inputs to SEC image are register based:
+EAX/RAX - Initial value of the EAX register (BIST: Built-in Self Test)
+DI - 'BP': boot-strap processor, or 'AP': application processor
+EBP/RBP - Pointer to the start of the Boot Firmware Volume
+
+=== HOW TO BUILD VTF0 ===
+
+Dependencies:
+* Python 2.5~2.7
+* Nasm 2.03 or newer
+
+To rebuild the VTF0 binaries:
+1. Change to VTF0 source dir: UefiCpuPkg/ResetVector/Vtf0
+2. nasm and python should be in executable path
+3. Run this command:
+ python Build.py
+4. Binaries output will be in UefiCpuPkg/ResetVector/Vtf0/Bin
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/ResetVectorCode.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/ResetVectorCode.asm
new file mode 100755
index 0000000000..96f686b0e6
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/ResetVectorCode.asm
@@ -0,0 +1,52 @@
+;------------------------------------------------------------------------------
+; @file
+; This file includes all other code files to assemble the reset vector code
+;
+; Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+%ifdef ARCH_IA32
+ %ifdef ARCH_X64
+ %error "Only one of ARCH_IA32 or ARCH_X64 can be defined."
+ %endif
+%elifdef ARCH_X64
+%else
+ %error "Either ARCH_IA32 or ARCH_X64 must be defined."
+%endif
+
+%include "CommonMacros.inc"
+
+%include "PostCodes.inc"
+
+%ifdef DEBUG_NONE
+ %include "DebugDisabled.asm"
+%elifdef DEBUG_PORT80
+ %include "Port80Debug.asm"
+%elifdef DEBUG_SERIAL
+ %include "SerialDebug.asm"
+%else
+ %error "No debug type was specified."
+%endif
+
+%include "Ia32/SearchForBfvBase.asm"
+%include "Ia32/SearchForSecEntry.asm"
+
+%ifdef ARCH_X64
+%include "Ia32/Flat32ToFlat64.asm"
+%endif
+
+%include "Ia16/Real16ToFlat32.asm"
+%include "Ia16/Init16.asm"
+
+%include "Main.asm"
+
+%include "Ia16/ResetVectorVtf0.asm"
+
diff --git a/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/SerialDebug.asm b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/SerialDebug.asm
new file mode 100755
index 0000000000..ebd0910f4a
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/ResetVector/Vtf0/SerialDebug.asm
@@ -0,0 +1,132 @@
+;------------------------------------------------------------------------------
+; @file
+; Serial port debug support macros
+;
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.
+; 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.
+;
+;------------------------------------------------------------------------------
+
+;//---------------------------------------------
+;// UART Register Offsets
+;//---------------------------------------------
+%define BAUD_LOW_OFFSET 0x00
+%define BAUD_HIGH_OFFSET 0x01
+%define IER_OFFSET 0x01
+%define LCR_SHADOW_OFFSET 0x01
+%define FCR_SHADOW_OFFSET 0x02
+%define IR_CONTROL_OFFSET 0x02
+%define FCR_OFFSET 0x02
+%define EIR_OFFSET 0x02
+%define BSR_OFFSET 0x03
+%define LCR_OFFSET 0x03
+%define MCR_OFFSET 0x04
+%define LSR_OFFSET 0x05
+%define MSR_OFFSET 0x06
+
+;//---------------------------------------------
+;// UART Register Bit Defines
+;//---------------------------------------------
+%define LSR_TXRDY 0x20
+%define LSR_RXDA 0x01
+%define DLAB 0x01
+
+; UINT16 gComBase = 0x3f8;
+; UINTN gBps = 115200;
+; UINT8 gData = 8;
+; UINT8 gStop = 1;
+; UINT8 gParity = 0;
+; UINT8 gBreakSet = 0;
+
+%define DEFAULT_COM_BASE 0x3f8
+%define DEFAULT_BPS 115200
+%define DEFAULT_DATA 8
+%define DEFAULT_STOP 1
+%define DEFAULT_PARITY 0
+%define DEFAULT_BREAK_SET 0
+
+%define SERIAL_DEFAULT_LCR ( \
+ (DEFAULT_BREAK_SET << 6) | \
+ (DEFAULT_PARITY << 3) | \
+ (DEFAULT_STOP << 2) | \
+ (DEFAULT_DATA - 5) \
+ )
+
+%define SERIAL_PORT_IO_BASE_ADDRESS DEFAULT_COM_BASE
+
+%macro inFromSerialPort 1
+ mov dx, (SERIAL_PORT_IO_BASE_ADDRESS + %1)
+ in al, dx
+%endmacro
+
+%macro waitForSerialTxReady 0
+
+%%waitingForTx:
+ inFromSerialPort LSR_OFFSET
+ test al, LSR_TXRDY
+ jz %%waitingForTx
+
+%endmacro
+
+%macro outToSerialPort 2
+ mov dx, (SERIAL_PORT_IO_BASE_ADDRESS + %1)
+ mov al, %2
+ out dx, al
+%endmacro
+
+%macro debugShowCharacter 1
+ waitForSerialTxReady
+ outToSerialPort 0, %1
+%endmacro
+
+%macro debugShowHexDigit 1
+ %if (%1 < 0xa)
+ debugShowCharacter BYTE ('0' + (%1))
+ %else
+ debugShowCharacter BYTE ('a' + ((%1) - 0xa))
+ %endif
+%endmacro
+
+%macro debugNewline 0
+ debugShowCharacter `\r`
+ debugShowCharacter `\n`
+%endmacro
+
+%macro debugShowPostCode 1
+ debugShowHexDigit (((%1) >> 4) & 0xf)
+ debugShowHexDigit ((%1) & 0xf)
+ debugNewline
+%endmacro
+
+BITS 16
+
+%macro debugInitialize 0
+ jmp real16InitDebug
+real16InitDebugReturn:
+%endmacro
+
+real16InitDebug:
+ ;
+ ; Set communications format
+ ;
+ outToSerialPort LCR_OFFSET, ((DLAB << 7) | SERIAL_DEFAULT_LCR)
+
+ ;
+ ; Configure baud rate
+ ;
+ outToSerialPort BAUD_HIGH_OFFSET, ((115200 / DEFAULT_BPS) >> 8)
+ outToSerialPort BAUD_LOW_OFFSET, ((115200 / DEFAULT_BPS) & 0xff)
+
+ ;
+ ; Switch back to bank 0
+ ;
+ outToSerialPort LCR_OFFSET, SERIAL_DEFAULT_LCR
+
+ jmp real16InitDebugReturn
+
diff --git a/CloverEFI/UefiCpuPkg/UefiCpuPkg.dec b/CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
new file mode 100755
index 0000000000..31b7303e6f
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
@@ -0,0 +1,46 @@
+## @file UefiCpuPkg.dec
+#
+# This Package provides UEFI compatible CPU modules and libraries.
+#
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = UefiCpuPkg
+ PACKAGE_GUID = 2171df9b-0d39-45aa-ac37-2de190010d23
+ PACKAGE_VERSION = 0.1
+
+[Includes]
+ Include
+
+[LibraryClasses]
+ ## @libraryclass Defines some routines that are generic for IA32 family CPU
+ ## to be UEFI specification compliant.
+ ##
+ UefiCpuLib|Include/Library/UefiCpuLib.h
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ ## @libraryclass Provides functions to manage MTRR settings on IA32 and X64 CPUs.
+ ##
+ MtrrLib|Include/Library/MtrrLib.h
+
+ ## @libraryclass Provides functions to manage the Local APIC on IA32 and X64 CPUs.
+ ##
+ LocalApicLib|Include/Library/LocalApicLib.h
+
+[Guids]
+ gUefiCpuPkgTokenSpaceGuid = { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa, 0xb8, 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }}
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress|0xfee00000|UINT32|0x00000001
+
diff --git a/CloverEFI/UefiCpuPkg/UefiCpuPkg.dsc b/CloverEFI/UefiCpuPkg/UefiCpuPkg.dsc
new file mode 100755
index 0000000000..c4c4e30854
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/UefiCpuPkg.dsc
@@ -0,0 +1,89 @@
+## @file
+# UefiCpuPkg Package
+#
+# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+##
+
+[Defines]
+ PLATFORM_NAME = UefiCpu
+ PLATFORM_GUID = a1b7be22-78b3-4260-9569-8649e8c17d49
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/UefiCpu
+ SUPPORTED_ARCHITECTURES = IA32|IPF|X64
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+
+#
+# External libraries to build package
+#
+
+[LibraryClasses]
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ MtrrLib|CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ LocalApicLib|CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+
+[LibraryClasses.common.PEIM]
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+
+[LibraryClasses.IA32.PEIM, LibraryClasses.X64.PEIM]
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+
+[LibraryClasses.IPF.PEIM]
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibKr7/PeiServicesTablePointerLibKr7.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+
+[LibraryClasses.common.DXE_SMM_DRIVER]
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+
+#
+# Drivers/Libraries within this package
+#
+
+[Components]
+ CloverEFI/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+ CloverEFI/UefiCpuPkg/CpuIoPei/CpuIoPei.inf
+ CloverEFI/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
+
+[Components.IA32, Components.X64]
+ CloverEFI/UefiCpuPkg/CpuDxe/CpuDxe.inf
+ CloverEFI/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
+ CloverEFI/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+ CloverEFI/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ CloverEFI/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
+ CloverEFI/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+ CloverEFI/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+
diff --git a/CloverEFI/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c b/CloverEFI/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
new file mode 100755
index 0000000000..58ba2a9ed9
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
@@ -0,0 +1,991 @@
+/** @file
+ This module produces the EFI_PEI_S3_RESUME_PPI.
+ This module works with StandAloneBootScriptExecutor to S3 resume to OS.
+ This module will excute the boot script saved during last boot and after that,
+ control is passed to OS waking up handler.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+
+ 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.
+
+**/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#pragma pack(1)
+typedef union {
+ struct {
+ UINT32 LimitLow : 16;
+ UINT32 BaseLow : 16;
+ UINT32 BaseMid : 8;
+ UINT32 Type : 4;
+ UINT32 System : 1;
+ UINT32 Dpl : 2;
+ UINT32 Present : 1;
+ UINT32 LimitHigh : 4;
+ UINT32 Software : 1;
+ UINT32 Reserved : 1;
+ UINT32 DefaultSize : 1;
+ UINT32 Granularity : 1;
+ UINT32 BaseHigh : 8;
+ } Bits;
+ UINT64 Uint64;
+} IA32_GDT;
+
+//
+// Page-Map Level-4 Offset (PML4) and
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:2; // Must Be Zero
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} PAGE_MAP_AND_DIRECTORY_POINTER;
+
+//
+// Page Table Entry 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:8; // Must be zero;
+ UINT64 PageTableBaseAddress:31; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_ENTRY;
+
+//
+// Page Table Entry 1GB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:17; // Must be zero;
+ UINT64 PageTableBaseAddress:22; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_1G_ENTRY;
+
+#pragma pack()
+
+//
+// Function prototypes
+//
+/**
+ a ASM function to transfer control to OS.
+
+ @param S3WakingVector The S3 waking up vector saved in ACPI Facs table
+ @param AcpiLowMemoryBase a buffer under 1M which could be used during the transfer
+**/
+typedef
+VOID
+(EFIAPI *ASM_TRANSFER_CONTROL) (
+ IN UINT32 S3WakingVector,
+ IN UINT32 AcpiLowMemoryBase
+ );
+
+/**
+ Restores the platform to its preboot configuration for an S3 resume and
+ jumps to the OS waking vector.
+
+ This function will restore the platform to its pre-boot configuration that was
+ pre-stored in the boot script table and transfer control to OS waking vector.
+ Upon invocation, this function is responsible for locating the following
+ information before jumping to OS waking vector:
+ - ACPI tables
+ - boot script table
+ - any other information that it needs
+
+ The S3RestoreConfig() function then executes the pre-stored boot script table
+ and transitions the platform to the pre-boot state. The boot script is recorded
+ during regular boot using the EFI_S3_SAVE_STATE_PROTOCOL.Write() and
+ EFI_S3_SMM_SAVE_STATE_PROTOCOL.Write() functions. Finally, this function
+ transfers control to the OS waking vector. If the OS supports only a real-mode
+ waking vector, this function will switch from flat mode to real mode before
+ jumping to the waking vector. If all platform pre-boot configurations are
+ successfully restored and all other necessary information is ready, this
+ function will never return and instead will directly jump to the OS waking
+ vector. If this function returns, it indicates that the attempt to resume
+ from the ACPI S3 sleep state failed.
+
+ @param[in] This Pointer to this instance of the PEI_S3_RESUME_PPI
+
+ @retval EFI_ABORTED Execution of the S3 resume boot script table failed.
+ @retval EFI_NOT_FOUND Some necessary information that is used for the S3
+ resume boot path could not be located.
+
+**/
+EFI_STATUS
+EFIAPI
+S3RestoreConfig2 (
+ IN EFI_PEI_S3_RESUME2_PPI *This
+ );
+
+//
+// Globals
+//
+EFI_PEI_S3_RESUME2_PPI mS3ResumePpi = { S3RestoreConfig2 };
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiS3Resume2PpiGuid,
+ &mS3ResumePpi
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListPostScriptTable = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiPostScriptTablePpiGuid,
+ 0
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListEndOfPeiTable = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ 0
+};
+
+//
+// Global Descriptor Table (GDT)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
+/* selector { Global Segment Descriptor } */
+/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x08 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x10 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}},
+/* 0x18 */ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}},
+/* 0x20 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x28 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 0, 1, 0}},
+/* 0x30 */ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 0, 1, 0}},
+/* 0x38 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}},
+/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+};
+
+//
+// IA32 Gdt register
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
+ sizeof (mGdtEntries) - 1,
+ (UINTN) mGdtEntries
+ };
+
+/**
+ Performance measure function to get S3 detailed performance data.
+
+ This function will getS3 detailed performance data and saved in pre-reserved ACPI memory.
+**/
+VOID
+WriteToOsS3PerformanceData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase;
+ PERF_HEADER *PerfHeader;
+ PERF_DATA *PerfData;
+ UINT64 Ticker;
+ UINTN Index;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
+ UINTN VarSize;
+ UINTN LogEntryKey;
+ CONST VOID *Handle;
+ CONST CHAR8 *Token;
+ CONST CHAR8 *Module;
+ UINT64 StartTicker;
+ UINT64 EndTicker;
+ UINT64 StartValue;
+ UINT64 EndValue;
+ BOOLEAN CountUp;
+ UINT64 Freq;
+
+ //
+ // Retrive time stamp count as early as possilbe
+ //
+ Ticker = GetPerformanceCounter ();
+
+ Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
+
+ Freq = DivU64x32 (Freq, 1000);
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &VariableServices
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
+ Status = VariableServices->GetVariable (
+ VariableServices,
+ L"PerfDataMemAddr",
+ &gPerformanceProtocolGuid,
+ NULL,
+ &VarSize,
+ &mAcpiLowMemoryBase
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Fail to retrieve variable to log S3 performance data \n"));
+ return;
+ }
+
+ PerfHeader = (PERF_HEADER *) (UINTN) mAcpiLowMemoryBase;
+
+ if (PerfHeader->Signiture != PERFORMANCE_SIGNATURE) {
+ DEBUG ((EFI_D_ERROR, "Performance data in ACPI memory get corrupted! \n"));
+ return;
+ }
+
+ //
+ // Record total S3 resume time.
+ //
+ if (EndValue >= StartValue) {
+ PerfHeader->S3Resume = Ticker - StartValue;
+ CountUp = TRUE;
+ } else {
+ PerfHeader->S3Resume = StartValue - Ticker;
+ CountUp = FALSE;
+ }
+
+ //
+ // Get S3 detailed performance data
+ //
+ Index = 0;
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurement (
+ LogEntryKey,
+ &Handle,
+ &Token,
+ &Module,
+ &StartTicker,
+ &EndTicker)) != 0) {
+ if (EndTicker != 0) {
+ PerfData = &PerfHeader->S3Entry[Index];
+
+ //
+ // Use File Handle to specify the different performance log for PEIM.
+ // File Handle is the base address of PEIM FFS file.
+ //
+ if ((AsciiStrnCmp (Token, "PEIM", PEI_PERFORMANCE_STRING_SIZE) == 0) && (Handle != NULL)) {
+ AsciiSPrint (PerfData->Token, PERF_TOKEN_LENGTH, "0x%11p", Handle);
+ } else {
+ AsciiStrnCpyS (PerfData->Token, PERF_TOKEN_LENGTH+1, Token, PERF_TOKEN_LENGTH);
+ }
+ if (StartTicker == 1) {
+ StartTicker = StartValue;
+ }
+ if (EndTicker == 1) {
+ EndTicker = StartValue;
+ }
+ Ticker = CountUp? (EndTicker - StartTicker) : (StartTicker - EndTicker);
+ PerfData->Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
+
+ //
+ // Only Record > 1ms performance data so that more big performance can be recorded.
+ //
+ if ((Ticker > Freq) && (++Index >= PERF_PEI_ENTRY_MAX_NUM)) {
+ //
+ // Reach the maximum number of PEI performance log entries.
+ //
+ break;
+ }
+ }
+ }
+ PerfHeader->S3EntryNum = (UINT32) Index;
+}
+
+/**
+ Jump to OS waking vector.
+ The function will install boot script done PPI, report S3 resume status code, and then jump to OS waking vector.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+ @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
+**/
+VOID
+EFIAPI
+S3ResumeBootOs (
+ IN ACPI_S3_CONTEXT *AcpiS3Context,
+ IN PEI_S3_RESUME_STATE *PeiS3ResumeState
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+ ASM_TRANSFER_CONTROL AsmTransferControl;
+ UINTN TempStackTop;
+ UINTN TempStack[0x10];
+
+ //
+ // Restore IDT
+ //
+ AsmWriteIdtr (&PeiS3ResumeState->Idtr);
+
+ //
+ // Install BootScriptDonePpi
+ //
+ Status = PeiServicesInstallPpi (&mPpiListPostScriptTable);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get ACPI Table Address
+ //
+ Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable));
+
+ if ((Facs == NULL) ||
+ (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
+ ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) {
+ CpuDeadLoop ();
+ return ;
+ }
+
+ //
+ // report status code on S3 resume
+ //
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);
+
+ //
+ // Install EndOfPeiPpi
+ //
+ Status = PeiServicesInstallPpi (&mPpiListEndOfPeiTable);
+ ASSERT_EFI_ERROR (Status);
+
+ PERF_CODE (
+ WriteToOsS3PerformanceData ();
+ );
+
+ AsmTransferControl = (ASM_TRANSFER_CONTROL)(UINTN)PeiS3ResumeState->AsmTransferControl;
+ if (Facs->XFirmwareWakingVector != 0) {
+ //
+ // Switch to native waking vector
+ //
+ TempStackTop = (UINTN)&TempStack + sizeof(TempStack);
+ if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
+ ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
+ ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) {
+ //
+ // X64 long mode waking vector
+ //
+ DEBUG (( EFI_D_ERROR, "Transfer to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ AsmEnablePaging64 (
+ 0x38,
+ Facs->XFirmwareWakingVector,
+ 0,
+ 0,
+ (UINT64)(UINTN)TempStackTop
+ );
+ } else {
+ DEBUG (( EFI_D_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));
+ ASSERT (FALSE);
+ }
+ } else {
+ //
+ // IA32 protected mode waking vector (Page disabled)
+ //
+ DEBUG (( EFI_D_ERROR, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT) (UINTN) Facs->XFirmwareWakingVector,
+ NULL,
+ NULL,
+ (VOID *)(UINTN)TempStackTop
+ );
+ }
+ } else {
+ //
+ // 16bit Realmode waking vector
+ //
+ DEBUG (( EFI_D_ERROR, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));
+ AsmTransferControl (Facs->FirmwareWakingVector, 0x0);
+ }
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop();
+}
+
+/**
+ Restore S3 page table because we do not trust ACPINvs content.
+ If BootScriptExector driver will not run in 64-bit mode, this function will do nothing.
+
+ @param S3NvsPageTableAddress PageTableAddress in ACPINvs
+**/
+VOID
+RestoreS3PageTables (
+ IN UINTN S3NvsPageTableAddress
+ )
+{
+/* if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ UINT8 PhysicalAddressBits;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN IndexOfPml4Entries;
+ UINTN IndexOfPdpEntries;
+ UINTN IndexOfPageDirectoryEntries;
+ UINT32 NumberOfPml4EntriesNeeded;
+ UINT32 NumberOfPdpEntriesNeeded;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;
+ VOID *Hob;
+ BOOLEAN Page1GSupport;
+ PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
+
+ //
+ // NOTE: We have to ASSUME the page table generation format, because we do not know whole page table information.
+ // The whole page table is too large to be saved in SMRAM.
+ //
+ // The assumption is : whole page table is allocated in CONTINOUS memory and CR3 points to TOP page.
+ //
+ DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x\n", S3NvsPageTableAddress));
+
+ //
+ // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.
+ //
+ PageMap = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;
+ S3NvsPageTableAddress += SIZE_4KB;
+
+ Page1GSupport = FALSE;
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT26) != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+
+ //
+ // Get physical address bits supported.
+ //
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ if (Hob != NULL) {
+ PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
+ } else {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8) RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+ }
+
+ //
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
+ //
+ ASSERT (PhysicalAddressBits <= 52);
+ if (PhysicalAddressBits > 48) {
+ PhysicalAddressBits = 48;
+ }
+
+ //
+ // Calculate the table entries needed.
+ //
+ if (PhysicalAddressBits <= 39) {
+ NumberOfPml4EntriesNeeded = 1;
+ NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
+ } else {
+ NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
+ NumberOfPdpEntriesNeeded = 512;
+ }
+
+ PageMapLevel4Entry = PageMap;
+ PageAddress = 0;
+ for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {
+ //
+ // Each PML4 entry points to a page of Page Directory Pointer entires.
+ // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
+ //
+ PageDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;
+ S3NvsPageTableAddress += SIZE_4KB;
+
+ //
+ // Make a PML4 Entry
+ //
+ PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
+ PageMapLevel4Entry->Bits.ReadWrite = 1;
+ PageMapLevel4Entry->Bits.Present = 1;
+
+ if (Page1GSupport) {
+ PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectory1GEntry->Bits.ReadWrite = 1;
+ PageDirectory1GEntry->Bits.Present = 1;
+ PageDirectory1GEntry->Bits.MustBe1 = 1;
+ }
+ } else {
+ for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+ //
+ // Each Directory Pointer entries points to a page of Page Directory entires.
+ // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
+ //
+ PageDirectoryEntry = (PAGE_TABLE_ENTRY *)S3NvsPageTableAddress;
+ S3NvsPageTableAddress += SIZE_4KB;
+
+ //
+ // Fill in a Page Directory Pointer Entries
+ //
+ PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;
+ PageDirectoryPointerEntry->Bits.ReadWrite = 1;
+ PageDirectoryPointerEntry->Bits.Present = 1;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectoryEntry->Bits.ReadWrite = 1;
+ PageDirectoryEntry->Bits.Present = 1;
+ PageDirectoryEntry->Bits.MustBe1 = 1;
+ }
+ }
+ }
+ }
+ return ;
+ } else {
+ //
+ // If DXE is running 32-bit mode, no need to establish page table.
+ //
+ return ;
+ } */
+ return;
+}
+
+/**
+ Jump to boot script executor driver.
+
+ The function will close and lock SMRAM and then jump to boot script execute driver to executing S3 boot script table.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+ @param EfiBootScriptExecutorVariable The function entry to executing S3 boot Script table. This function is build in
+ boot script execute driver
+**/
+VOID
+EFIAPI
+S3ResumeExecuteBootScript (
+ IN ACPI_S3_CONTEXT *AcpiS3Context,
+ IN BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_ACCESS_PPI *SmmAccess;
+ UINTN Index;
+ VOID *GuidHob;
+ IA32_DESCRIPTOR *IdtDescriptor;
+ VOID *IdtBuffer;
+ PEI_S3_RESUME_STATE *PeiS3ResumeState;
+
+ DEBUG ((EFI_D_ERROR, "S3ResumeExecuteBootScript()\n"));
+
+ //
+ // Attempt to use content from SMRAM first
+ //
+ GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+ if (GuidHob != NULL) {
+ //
+ // Last step for SMM - send SMI for initialization
+ //
+
+ //
+ // Send SMI to APs
+ //
+ SendSmiIpiAllExcludingSelf ();
+ //
+ // Send SMI to BSP
+ //
+ SendSmiIpi (GetApicId ());
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SmmAccess
+ );
+
+ DEBUG ((EFI_D_ERROR, "Close all SMRAM regions before executing boot script\n"));
+
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+
+ DEBUG ((EFI_D_ERROR, "Lock all SMRAM regions before executing boot script\n"));
+
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+ }
+
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ //
+ // Need reconstruct page table here, since we do not trust ACPINvs.
+ //
+ RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress);
+ AsmWriteCr3 ((UINTN)AcpiS3Context->S3NvsPageTableAddress);
+ }
+
+ if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
+ //
+ // On some platform, such as ECP, a dispatch node in boot script table may execute a 32-bit PEIM which may need PeiServices
+ // pointer. So PeiServices need preserve in (IDTBase- sizeof (UINTN)).
+ //
+ IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);
+ //
+ // Make sure the newly allcated IDT align with 16-bytes
+ //
+ IdtBuffer = AllocatePages (EFI_SIZE_TO_PAGES((IdtDescriptor->Limit + 1) + 16));
+ ASSERT (IdtBuffer != NULL);
+ CopyMem ((VOID*)((UINT8*)IdtBuffer + 16),(VOID*)(IdtDescriptor->Base), (IdtDescriptor->Limit + 1));
+ IdtDescriptor->Base = (UINTN)((UINT8*)IdtBuffer + 16);
+ *(UINTN*)(IdtDescriptor->Base - sizeof(UINTN)) = (UINTN)GetPeiServicesTablePointer ();
+ }
+
+ //
+ // Need to make sure the GDT is loaded with values that support long mode and real mode.
+ //
+ AsmWriteGdtr (&mGdt);
+
+ //
+ // Prepare data for return back
+ //
+ PeiS3ResumeState = AllocatePool (sizeof(*PeiS3ResumeState));
+ ASSERT (PeiS3ResumeState != NULL);
+ DEBUG (( EFI_D_ERROR, "PeiS3ResumeState - %x\r\n", PeiS3ResumeState));
+ PeiS3ResumeState->ReturnCs = 0x10;
+ PeiS3ResumeState->ReturnEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeBootOs;
+ PeiS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;
+ //
+ // Save IDT
+ //
+ AsmReadIdtr (&PeiS3ResumeState->Idtr);
+
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ //
+ // X64 S3 Resume
+ //
+ DEBUG (( EFI_D_ERROR, "Enable X64 and transfer control to Standalone Boot Script Executor\r\n"));
+
+ //
+ // Switch to long mode to complete resume.
+ //
+ AsmEnablePaging64 (
+ 0x38,
+ EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint,
+ (UINT64)(UINTN)AcpiS3Context,
+ (UINT64)(UINTN)PeiS3ResumeState,
+ (UINT64)(UINTN)(AcpiS3Context->BootScriptStackBase + AcpiS3Context->BootScriptStackSize)
+ );
+ } else {
+ //
+ // IA32 S3 Resume
+ //
+ DEBUG (( EFI_D_ERROR, "transfer control to Standalone Boot Script Executor\r\n"));
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT) (UINTN) EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint,
+ (VOID *)AcpiS3Context,
+ (VOID *)PeiS3ResumeState,
+ (VOID *)(UINTN)(AcpiS3Context->BootScriptStackBase + AcpiS3Context->BootScriptStackSize)
+ );
+ }
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop();
+}
+/**
+ Restores the platform to its preboot configuration for an S3 resume and
+ jumps to the OS waking vector.
+
+ This function will restore the platform to its pre-boot configuration that was
+ pre-stored in the boot script table and transfer control to OS waking vector.
+ Upon invocation, this function is responsible for locating the following
+ information before jumping to OS waking vector:
+ - ACPI tables
+ - boot script table
+ - any other information that it needs
+
+ The S3RestoreConfig() function then executes the pre-stored boot script table
+ and transitions the platform to the pre-boot state. The boot script is recorded
+ during regular boot using the EFI_S3_SAVE_STATE_PROTOCOL.Write() and
+ EFI_S3_SMM_SAVE_STATE_PROTOCOL.Write() functions. Finally, this function
+ transfers control to the OS waking vector. If the OS supports only a real-mode
+ waking vector, this function will switch from flat mode to real mode before
+ jumping to the waking vector. If all platform pre-boot configurations are
+ successfully restored and all other necessary information is ready, this
+ function will never return and instead will directly jump to the OS waking
+ vector. If this function returns, it indicates that the attempt to resume
+ from the ACPI S3 sleep state failed.
+
+ @param[in] This Pointer to this instance of the PEI_S3_RESUME_PPI
+
+ @retval EFI_ABORTED Execution of the S3 resume boot script table failed.
+ @retval EFI_NOT_FOUND Some necessary information that is used for the S3
+ resume boot path could not be located.
+
+**/
+EFI_STATUS
+EFIAPI
+S3RestoreConfig2 (
+ IN EFI_PEI_S3_RESUME2_PPI *This
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_ACCESS_PPI *SmmAccess;
+ UINTN Index;
+ ACPI_S3_CONTEXT *AcpiS3Context;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
+ EFI_PHYSICAL_ADDRESS TempEfiBootScriptExecutorVariable;
+ EFI_PHYSICAL_ADDRESS TempAcpiS3Context;
+ BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
+ UINTN VarSize;
+ EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
+ SMM_S3_RESUME_STATE *SmmS3ResumeState;
+ VOID *GuidHob;
+
+ DEBUG ((EFI_D_ERROR, "Enter S3 PEIM\r\n"));
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SmmAccess
+ );
+ for (Index = 0; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &VariableServices
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
+ Status = RestoreLockBox (
+ &gEfiAcpiVariableGuid,
+ &TempAcpiS3Context,
+ &VarSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ AcpiS3Context = (ACPI_S3_CONTEXT *)(UINTN)TempAcpiS3Context;
+ ASSERT (AcpiS3Context != NULL);
+
+ Status = RestoreLockBox (
+ &gEfiAcpiS3ContextGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ VarSize = sizeof (TempEfiBootScriptExecutorVariable);
+ Status = RestoreLockBox (
+ &gEfiBootScriptExecutorVariableGuid,
+ &TempEfiBootScriptExecutorVariable,
+ &VarSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = RestoreLockBox (
+ &gEfiBootScriptExecutorContextGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *) (UINTN) TempEfiBootScriptExecutorVariable;
+
+ DEBUG (( EFI_D_ERROR, "AcpiS3Context = %x\n", AcpiS3Context));
+ DEBUG (( EFI_D_ERROR, "Waking Vector = %x\n", ((EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable)))->FirmwareWakingVector));
+ DEBUG (( EFI_D_ERROR, "AcpiS3Context->AcpiFacsTable = %x\n", AcpiS3Context->AcpiFacsTable));
+ DEBUG (( EFI_D_ERROR, "AcpiS3Context->S3NvsPageTableAddress = %x\n", AcpiS3Context->S3NvsPageTableAddress));
+ DEBUG (( EFI_D_ERROR, "AcpiS3Context->S3DebugBufferAddress = %x\n", AcpiS3Context->S3DebugBufferAddress));
+ DEBUG (( EFI_D_ERROR, "EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = %x\n", EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint));
+
+ //
+ // Additional step for BootScript integrity - we only handle BootScript and BootScriptExecutor.
+ // Script dispatch image and context (parameter) are handled by platform.
+ // We just use restore all lock box in place, no need restore one by one.
+ //
+ Status = RestoreAllLockBoxInPlace ();
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ // Something wrong
+ CpuDeadLoop ();
+ }
+
+ //
+ // Attempt to use content from SMRAM first
+ //
+ GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+ if (GuidHob != NULL) {
+ SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
+ SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
+
+ SmmS3ResumeState->ReturnCs = AsmReadCs ();
+ SmmS3ResumeState->ReturnEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeExecuteBootScript;
+ SmmS3ResumeState->ReturnContext1 = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;
+ SmmS3ResumeState->ReturnContext2 = (EFI_PHYSICAL_ADDRESS)(UINTN)EfiBootScriptExecutorVariable;
+ SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;
+
+ DEBUG (( EFI_D_ERROR, "SMM S3 Signature = %x\n", SmmS3ResumeState->Signature));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Stack Base = %x\n", SmmS3ResumeState->SmmS3StackBase));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Stack Size = %x\n", SmmS3ResumeState->SmmS3StackSize));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Resume Entry Point = %x\n", SmmS3ResumeState->SmmS3ResumeEntryPoint));
+ DEBUG (( EFI_D_ERROR, "SMM S3 CR0 = %x\n", SmmS3ResumeState->SmmS3Cr0));
+ DEBUG (( EFI_D_ERROR, "SMM S3 CR3 = %x\n", SmmS3ResumeState->SmmS3Cr3));
+ DEBUG (( EFI_D_ERROR, "SMM S3 CR4 = %x\n", SmmS3ResumeState->SmmS3Cr4));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Return CS = %x\n", SmmS3ResumeState->ReturnCs));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Return Entry Point = %x\n", SmmS3ResumeState->ReturnEntryPoint));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Return Context1 = %x\n", SmmS3ResumeState->ReturnContext1));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Return Context2 = %x\n", SmmS3ResumeState->ReturnContext2));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Return Stack Pointer = %x\n", SmmS3ResumeState->ReturnStackPointer));
+ DEBUG (( EFI_D_ERROR, "SMM S3 Smst = %x\n", SmmS3ResumeState->Smst));
+
+ //
+ // Disable interrupt of Debug timer.
+ //
+ SaveAndSetDebugTimerInterrupt (FALSE);
+
+ if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->SmmS3ResumeEntryPoint,
+ (VOID *)AcpiS3Context,
+ 0,
+ (VOID *)(UINTN)(SmmS3ResumeState->SmmS3StackBase + SmmS3ResumeState->SmmS3StackSize)
+ );
+ }
+ if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {
+ //
+ // Switch to long mode to complete resume.
+ //
+
+ //
+ // Need to make sure the GDT is loaded with values that support long mode and real mode.
+ //
+ AsmWriteGdtr (&mGdt);
+ AsmWriteCr3 ((UINTN)SmmS3ResumeState->SmmS3Cr3);
+ AsmEnablePaging64 (
+ 0x38,
+ SmmS3ResumeState->SmmS3ResumeEntryPoint,
+ (UINT64)(UINTN)AcpiS3Context,
+ 0,
+ SmmS3ResumeState->SmmS3StackBase + SmmS3ResumeState->SmmS3StackSize
+ );
+ }
+
+ }
+
+ S3ResumeExecuteBootScript (AcpiS3Context, EfiBootScriptExecutorVariable );
+ return EFI_SUCCESS;
+}
+/**
+ Main entry for S3 Resume PEIM.
+
+ This routine is to install EFI_PEI_S3_RESUME2_PPI.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Pointer to PEI Services table.
+
+ @retval EFI_SUCCESS S3Resume Ppi is installed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimS3ResumeEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install S3 Resume Ppi
+ //
+ Status = (**PeiServices).InstallPpi (PeiServices, &mPpiList);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/CloverEFI/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf b/CloverEFI/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
new file mode 100755
index 0000000000..1a38f518ad
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
@@ -0,0 +1,79 @@
+## @file
+# S3 Resume Module:
+# This module works with StandAloneBootScriptExecutor to S3 resume to OS.
+# This module will excute the boot script saved during last boot and after that,
+# control is passed to OS waking up handler.
+#
+# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = S3Resume2Pei
+ FILE_GUID = 89E549B0-7CFE-449d-9BA3-10D8B2312D71
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PeimS3ResumeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ S3Resume.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CloverEFI/UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ PeiServicesTablePointerLib
+ PerformanceLib
+ HobLib
+ PeiServicesLib
+ PeimEntryPoint
+ TimerLib
+ BaseLib
+ DebugLib
+ PcdLib
+ IoLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ DebugAgentLib
+ LocalApicLib
+ ReportStatusCodeLib
+ LockBoxLib
+ PrintLib
+
+[Guids]
+ gEfiBootScriptExecutorVariableGuid # SOMETIMES_CONSUMED
+ gEfiBootScriptExecutorContextGuid # SOMETIMES_CONSUMED
+ gPerformanceProtocolGuid # ALWAYS_CONSUMED L"PerfDataMemAddr"
+ gEfiAcpiVariableGuid # ALWAYS_CONSUMED Hob: GUID_EXTENSION
+ gEfiAcpiS3ContextGuid # ALWAYS_CONSUMED
+
+[Ppis]
+ gEfiPeiReadOnlyVariable2PpiGuid # PPI ALWAYS_CONSUMED
+ gEfiPeiS3Resume2PpiGuid # PPI ALWAYS_PRODUCED
+ gPeiSmmAccessPpiGuid # PPI ALWAYS_CONSUMED
+ gPeiPostScriptTablePpiGuid # PPI ALWAYS_PRODUCED
+ gEfiEndOfPeiSignalPpiGuid # PPI ALWAYS_PRODUCED
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport
+
+[Depex]
+ gEfiPeiReadOnlyVariable2PpiGuid
diff --git a/CloverEFI/UefiCpuPkg/build.sh b/CloverEFI/UefiCpuPkg/build.sh
new file mode 100755
index 0000000000..0d479420e6
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/build.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+#
+# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Copyright (c) 2010, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+
+set -e
+shopt -s nocasematch
+
+
+#
+# Setup workspace if it is not set
+#
+if [ -z "$WORKSPACE" ]
+then
+ echo Initializing workspace
+ if [ ! -e `pwd`/edksetup.sh ]
+ then
+ cd ..
+ fi
+# This version is for the tools in the BaseTools project.
+# this assumes svn pulls have the same root dir
+# export EDK_TOOLS_PATH=`pwd`/../BaseTools
+# This version is for the tools source in edk2
+ export EDK_TOOLS_PATH=`pwd`/BaseTools
+ echo $EDK_TOOLS_PATH
+ source edksetup.sh BaseTools
+else
+ echo Building from: $WORKSPACE
+fi
+
+#
+# Pick a default tool type for a given OS
+#
+TARGET_TOOLS=MYTOOLS
+NETWORK_SUPPORT=
+case `uname` in
+ CYGWIN*) echo Cygwin not fully supported yet. ;;
+ Darwin*)
+ Major=$(uname -r | cut -f 1 -d '.')
+ if [[ $Major == 9 ]]
+ then
+ echo UnixPkg requires Snow Leopard or later OS
+ exit 1
+ else
+ TARGET_TOOLS=XCODE32
+ fi
+# NETWORK_SUPPORT="-D NETWORK_SUPPORT"
+ ;;
+ Linux*) TARGET_TOOLS=ELFGCC ;;
+
+esac
+
+BUILD_ROOT_ARCH=$WORKSPACE/Build/Shell/DEBUG_"$TARGET_TOOLS"/IA32
+
+
+#
+# Build the edk2 UnixPkg
+#
+echo $PATH
+echo `which build`
+#build -p $WORKSPACE/UnixPkg/UnixPkg.dsc -a IA32 -t $TARGET_TOOLS $NETWORK_SUPPORT -n 3 $1 $2 $3 $4 $5 $6 $7 $8
+build -p $WORKSPACE/CloverEFI/UefiCpuPkg/UefiCpuPkg.dsc -a IA32 -t $TARGET_TOOLS -n 3 $*
+exit $?
+
diff --git a/CloverEFI/UefiCpuPkg/edk2.patch-idtgdt b/CloverEFI/UefiCpuPkg/edk2.patch-idtgdt
new file mode 100755
index 0000000000..34230487f6
--- /dev/null
+++ b/CloverEFI/UefiCpuPkg/edk2.patch-idtgdt
@@ -0,0 +1,283 @@
+Index: UefiCpuPkg/CpuDxe/CpuDxe.inf
+===================================================================
+--- UefiCpuPkg/CpuDxe/CpuDxe.inf (revision 9332)
++++ UefiCpuPkg/CpuDxe/CpuDxe.inf (working copy)
+@@ -62,6 +62,9 @@
+ [Protocols]
+ gEfiCpuArchProtocolGuid
+
++[Guids]
++ gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED Create Event: EVENT_GROUP_GUID
++
+ [Depex]
+ TRUE
+
+Index: UefiCpuPkg/CpuDxe/CpuGdt.c
+===================================================================
+--- UefiCpuPkg/CpuDxe/CpuGdt.c (revision 9332)
++++ UefiCpuPkg/CpuDxe/CpuGdt.c (working copy)
+@@ -67,6 +67,9 @@
+ #error CPU type not supported for CPU GDT initialization!
+ #endif
+
++VOID * Gdt;
++UINT32 GdtSize;
++
+ //
+ // Global descriptor table (GDT) Template
+ //
+@@ -161,6 +164,20 @@
+ },
+ };
+
++VOID EFIAPI
++LoadGdt(VOID* Gdt, UINT32 GdtSize)
++{
++ IA32_DESCRIPTOR gdtPtr;
++
++ //
++ // Write GDT register
++ //
++ gdtPtr.Base = (UINT32)(UINTN)Gdt;
++ gdtPtr.Limit = GdtSize - 1;
++
++ AsmWriteGdtr (&gdtPtr);
++}
++
+ /**
+ Initialize Global Descriptor Table
+
+@@ -169,27 +186,27 @@
+ InitGlobalDescriptorTable (
+ )
+ {
+- GDT_ENTRIES *gdt;
+- IA32_DESCRIPTOR gdtPtr;
+-
+ //
+ // Allocate Runtime Data for the GDT
+ //
+- gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
+- ASSERT (gdt != NULL);
+- gdt = ALIGN_POINTER (gdt, 8);
++ GdtSize = sizeof (GdtTemplate);
++#if 0
++ Gdt = AllocateRuntimePool (GdtSize + 8);
++ ASSERT (Gdt != NULL);
++ Gdt = ALIGN_POINTER (Gdt, 8);
++#else
++ Gdt = (VOID*)(UINTN)HandyCpuPage;
++#endif
+
+ //
+ // Initialize all GDT entries
+ //
+- CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));
++ CopyMem (Gdt, &GdtTemplate, GdtSize);
+
+ //
+ // Write GDT register
+ //
+- gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt;
+- gdtPtr.Limit = sizeof (GdtTemplate) - 1;
+- AsmWriteGdtr (&gdtPtr);
++ LoadGdt(Gdt, GdtSize);
+
+ //
+ // Update selector (segment) registers base on new GDT
+@@ -197,4 +214,3 @@
+ SetCodeSelector ((UINT16)CPU_CODE_SEL);
+ SetDataSelectors ((UINT16)CPU_DATA_SEL);
+ }
+-
+Index: UefiCpuPkg/CpuDxe/CpuDxe.c
+===================================================================
+--- UefiCpuPkg/CpuDxe/CpuDxe.c (revision 9332)
++++ UefiCpuPkg/CpuDxe/CpuDxe.c (working copy)
+@@ -14,11 +14,14 @@
+
+ #include "CpuDxe.h"
+
++EFI_EVENT mEfiVirtualNotifyEvent;
++EFI_PHYSICAL_ADDRESS HandyCpuPage;
++IA32_IDT_GATE_DESCRIPTOR* Idt;
++UINT32 IdtSize;
++
+ //
+ // Global Variables
+ //
+-IA32_IDT_GATE_DESCRIPTOR gIdtTable[INTERRUPT_VECTOR_NUMBER] = { 0 };
+-
+ EFI_CPU_INTERRUPT_HANDLER ExternalVectorTable[0x100];
+ BOOLEAN InterruptState = FALSE;
+ EFI_HANDLE mCpuHandle = NULL;
+@@ -1004,8 +1007,6 @@
+ )
+ {
+ EFI_STATUS Status;
+- VOID *IdtPtrAlignmentBuffer;
+- IA32_DESCRIPTOR *IdtPtr;
+ UINTN Index;
+ UINTN CurrentHandler;
+
+@@ -1015,27 +1016,33 @@
+ // Initialize IDT
+ //
+ CurrentHandler = (UINTN)AsmIdtVector00;
++
++ //
++ // Allocate Runtime Data for the IDT
++ //
++ IdtSize = INTERRUPT_VECTOR_NUMBER*sizeof(IA32_IDT_GATE_DESCRIPTOR);
++#if 0
++ Idt = AllocateRuntimePool (IdtSize + 16);
++ ASSERT (Idt != NULL);
++ Idt = ALIGN_POINTER (Idt, 16);
++#else
++ Idt = (VOID*)(UINTN)HandyCpuPage + 0x500;
++#endif
++
+ for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++, CurrentHandler += 0x08) {
+- gIdtTable[Index].Bits.OffsetLow = (UINT16)CurrentHandler;
+- gIdtTable[Index].Bits.Selector = AsmReadCs();
+- gIdtTable[Index].Bits.Reserved_0 = 0;
+- gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+- gIdtTable[Index].Bits.OffsetHigh = (UINT16)(CurrentHandler >> 16);
++ Idt[Index].Bits.OffsetLow = (UINT16)CurrentHandler;
++ Idt[Index].Bits.Selector = AsmReadCs();
++ Idt[Index].Bits.Reserved_0 = 0;
++ Idt[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
++ Idt[Index].Bits.OffsetHigh = (UINT16)(CurrentHandler >> 16);
+ #if defined (MDE_CPU_X64)
+- gIdtTable[Index].Bits.OffsetUpper = (UINT32)(CurrentHandler >> 32);
+- gIdtTable[Index].Bits.Reserved_1 = 0;
++ Idt[Index].Bits.OffsetUpper = (UINT32)(CurrentHandler >> 32);
++ Idt[Index].Bits.Reserved_1 = 0;
+ #endif
+ }
+
+- //
+- // Load IDT Pointer
+- //
+- IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16);
+- IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16);
+- IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1));
+- IdtPtr->Limit = sizeof (gIdtTable) - 1;
+- AsmWriteIdtr (IdtPtr);
+- FreePool (IdtPtrAlignmentBuffer);
++ // Load IDT
++ LoadIdt(Idt, IdtSize);
+
+ //
+ // Initialize Exception Handlers
+@@ -1052,7 +1059,50 @@
+
+ }
+
++VOID EFIAPI
++LoadIdt(VOID* Idt, UINT32 IdtSize)
++{
++ IA32_DESCRIPTOR IdtPtr;
+
++ IdtPtr.Base = (UINT32)(((UINTN) Idt) & (BASE_4GB-1));
++ IdtPtr.Limit = IdtSize - 1;
++ AsmWriteIdtr (&IdtPtr);
++}
++
++UINT32
++EFIAPI
++IoWrite32 (
++ IN UINTN Port,
++ IN UINT32 Value
++ )
++{
++ __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port));
++ return Value;
++}
++
++VOID
++EFIAPI
++CpuLibVirtualNotifyEvent (
++ IN EFI_EVENT Event,
++ IN VOID *Context
++ )
++{
++ EFI_RUNTIME_SERVICES * rs = (EFI_RUNTIME_SERVICES *)Context;
++
++ rs->ConvertPointer (0, (VOID **) &Gdt);
++ rs->ConvertPointer (0, (VOID **) &Idt);
++
++ DisableInterrupts();
++
++ LoadIdt(Idt, IdtSize);
++ LoadGdt(Gdt, GdtSize);
++
++ //IoWrite32(0xef11, 1);
++}
++
++extern EFI_GUID gEfiEventVirtualAddressChangeGuid;
++
++
+ /**
+ Initialize the state information for the CPU Architectural Protocol.
+
+@@ -1073,6 +1123,17 @@
+ {
+ EFI_STATUS Status;
+
++
++ // Allocate handy page
++ HandyCpuPage = 0xffffffff;
++ Status = gBS->AllocatePages (
++ AllocateMaxAddress,
++ EfiReservedMemoryType,
++ 1,
++ &HandyCpuPage );
++ ASSERT_EFI_ERROR (Status);
++ ASSERT (HandyCpuPage != 0xffffffff);
++
+ //
+ // Make sure interrupts are disabled
+ //
+@@ -1103,6 +1164,18 @@
+ //
+ RefreshGcdMemoryAttributes ();
+
++
++ // Register virtual address change notifier
++#if 0
++ gBS->CreateEventEx (
++ EVT_NOTIFY_SIGNAL,
++ TPL_NOTIFY,
++ CpuLibVirtualNotifyEvent,
++ SystemTable->RuntimeServices,
++ &gEfiEventVirtualAddressChangeGuid,
++ &mEfiVirtualNotifyEvent
++ );
++#endif
++
+ return Status;
+ }
+-
+Index: UefiCpuPkg/CpuDxe/CpuDxe.h
+===================================================================
+--- UefiCpuPkg/CpuDxe/CpuDxe.h (revision 9332)
++++ UefiCpuPkg/CpuDxe/CpuDxe.h (working copy)
+@@ -136,5 +136,17 @@
+ );
+
+
++VOID EFIAPI
++LoadGdt(VOID* Gdt, UINT32 GdtSize);
++
++VOID EFIAPI
++LoadIdt(VOID* Idt, UINT32 IdtSize);
++
++extern EFI_PHYSICAL_ADDRESS HandyCpuPage;
++extern VOID* Gdt;
++extern UINT32 GdtSize;
++extern IA32_IDT_GATE_DESCRIPTOR* Idt;
++extern UINT32 IdtSize;
++
+ #endif
+
diff --git a/Protocols/DataHubDxe/DataHub.c b/Protocols/DataHubDxe/DataHub.c
old mode 100644
new mode 100755
index 1a97f4fa7d..9a193d5ff0
--- a/Protocols/DataHubDxe/DataHub.c
+++ b/Protocols/DataHubDxe/DataHub.c
@@ -14,596 +14,574 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "DataHub.h"
-#include
-// now using OpenCore library to avoid multiple definition of functions
+//
+// Since this driver will only ever produce one instance of the Logging Hub
+// protocol you are not required to dynamically allocate the PrivateData.
+//
+DATA_HUB_INSTANCE mPrivateData;
+/**
+ Log data record into the data logging hub
+ @param This Protocol instance structure
+ @param DataRecordGuid GUID that defines record contents
+ @param ProducerName GUID that defines the name of the producer of the data
+ @param DataRecordClass Class that defines generic record type
+ @param RawData Data Log record as defined by DataRecordGuid
+ @param RawDataSize Size of Data Log data in bytes
-//
-////
-//// Since this driver will only ever produce one instance of the Logging Hub
-//// protocol you are not required to dynamically allocate the PrivateData.
-////
-//DATA_HUB_INSTANCE mPrivateData;
-//
-///**
-// Log data record into the data logging hub
-//
-// @param This Protocol instance structure
-// @param DataRecordGuid GUID that defines record contents
-// @param ProducerName GUID that defines the name of the producer of the data
-// @param DataRecordClass Class that defines generic record type
-// @param RawData Data Log record as defined by DataRecordGuid
-// @param RawDataSize Size of Data Log data in bytes
-//
-// @retval EFI_SUCCESS If data was logged
-// @retval EFI_OUT_OF_RESOURCES If data was not logged due to lack of system
-// resources.
-//**/
-//EFI_STATUS
-//EFIAPI
-//DataHubLogData (
-// IN EFI_DATA_HUB_PROTOCOL *This,
-// IN EFI_GUID *DataRecordGuid,
-// IN EFI_GUID *ProducerName,
-// IN UINT64 DataRecordClass,
-// IN VOID *RawData,
-// IN UINT32 RawDataSize
-// )
-//{
-// EFI_STATUS Status;
-// DATA_HUB_INSTANCE *Private;
-// EFI_DATA_ENTRY *LogEntry;
-// UINT32 TotalSize;
-// UINT32 RecordSize;
-// EFI_DATA_RECORD_HEADER *Record;
-// VOID *Raw;
-// DATA_HUB_FILTER_DRIVER *FilterEntry;
-// LIST_ENTRY *Link;
-// LIST_ENTRY *Head;
-// EFI_TIME LogTime;
-//
-// Private = DATA_HUB_INSTANCE_FROM_THIS (This);
-//
-// //
-// // Combine the storage for the internal structs and a copy of the log record.
-// // Record follows PrivateLogEntry. The consumer will be returned a pointer
-// // to Record so we don't what it to be the thing that was allocated from
-// // pool, so the consumer can't free an data record by mistake.
-// //
-// RecordSize = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize;
-// TotalSize = sizeof (EFI_DATA_ENTRY) + RecordSize;
-//
-// //
-// // First try to get log time at TPL level <= TPL_CALLBACK.
-// //
-// ZeroMem (&LogTime, sizeof (LogTime));
-// if (EfiGetCurrentTpl() <= TPL_CALLBACK) {
-// gRT->GetTime (&LogTime, NULL);
-// }
-//
-// //
-// // The Logging action is the critical section, so it is locked.
-// // The MTC asignment & update and logging must be an
-// // atomic operation, so use the lock.
-// //
-// Status = EfiAcquireLockOrFail (&Private->DataLock);
-// if (EFI_ERROR(Status)) {
-// //
-// // Reentrancy detected so exit!
-// //
-// return Status;
-// }
-//
-// LogEntry = AllocatePool (TotalSize);
-//
-// if (LogEntry == NULL) {
-// EfiReleaseLock (&Private->DataLock);
-// return EFI_OUT_OF_RESOURCES;
-// }
-//
-// ZeroMem (LogEntry, TotalSize);
-//
-// Record = (EFI_DATA_RECORD_HEADER *) (LogEntry + 1);
-// Raw = (VOID *) (Record + 1);
-//
-// //
-// // Build Standard Log Header
-// //
-// Record->Version = EFI_DATA_RECORD_HEADER_VERSION;
-// Record->HeaderSize = (UINT16) sizeof (EFI_DATA_RECORD_HEADER);
-// Record->RecordSize = RecordSize;
-// CopyMem(&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID));
-// CopyMem(&Record->ProducerName, ProducerName, sizeof (EFI_GUID));
-// Record->DataRecordClass = DataRecordClass;
-//
-// //
-// // Ensure LogMonotonicCount is not zero
-// //
-// Record->LogMonotonicCount = ++Private->GlobalMonotonicCount;
-//
-// CopyMem(&Record->LogTime, &LogTime, sizeof (LogTime));
-//
-// //
-// // Insert log into the internal linked list.
-// //
-// LogEntry->Signature = EFI_DATA_ENTRY_SIGNATURE;
-// LogEntry->Record = Record;
-// LogEntry->RecordSize = sizeof (EFI_DATA_ENTRY) + RawDataSize;
-// InsertTailList (&Private->DataListHead, &LogEntry->Link);
-//
-// CopyMem(Raw, RawData, RawDataSize);
-//
-// EfiReleaseLock (&Private->DataLock);
-//
-// //
-// // Send Signal to all the filter drivers which are interested
-// // in the record's class and guid.
-// //
-// Head = &Private->FilterDriverListHead;
-// for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
-// FilterEntry = FILTER_ENTRY_FROM_LINK (Link);
-// if (((FilterEntry->ClassFilter & DataRecordClass) != 0) &&
-// (IsZeroGuid (&FilterEntry->FilterDataRecordGuid) ||
-// CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid))) {
-// gBS->SignalEvent (FilterEntry->Event);
-// }
-// }
-//
-// return EFI_SUCCESS;
-//}
-//
-///**
-// Search the Head doubly linked list for the passed in MTC. Return the
-// matching element in Head and the MTC on the next entry.
-//
-// @param Head Head of Data Log linked list.
-// @param ClassFilter Only match the MTC if it is in the same Class as the
-// ClassFilter.
-// @param PtrCurrentMTC On IN contians MTC to search for. On OUT contians next
-// MTC in the data log list or zero if at end of the list.
-//
-// @retval EFI_DATA_LOG_ENTRY Return pointer to data log data from Head list.
-// @retval NULL If no data record exists.
-//
-//**/
-//EFI_DATA_RECORD_HEADER *
-//GetNextDataRecord (
-// IN LIST_ENTRY *Head,
-// IN UINT64 ClassFilter,
-// IN OUT UINT64 *PtrCurrentMTC
-// )
-//
-//{
-// EFI_DATA_ENTRY *LogEntry;
-// LIST_ENTRY *Link;
-// BOOLEAN ReturnFirstEntry;
-// EFI_DATA_RECORD_HEADER *Record;
-// EFI_DATA_ENTRY *NextLogEntry;
-//
-// //
-// // If MonotonicCount == 0 just return the first one
-// //
-// ReturnFirstEntry = (BOOLEAN) (*PtrCurrentMTC == 0);
-//
-// Record = NULL;
-// for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
-// LogEntry = DATA_ENTRY_FROM_LINK (Link);
-// if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) {
-// //
-// // Skip any entry that does not have the correct ClassFilter
-// //
-// continue;
-// }
-//
-// if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) {
-// //
-// // Return record to the user
-// //
-// Record = LogEntry->Record;
-//
-// //
-// // Calculate the next MTC value. If there is no next entry set
-// // MTC to zero.
-// //
-// *PtrCurrentMTC = 0;
-// for (Link = GetNextNode(Head, Link); Link != Head; Link = GetNextNode(Head, Link)) {
-// NextLogEntry = DATA_ENTRY_FROM_LINK (Link);
-// if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) {
-// //
-// // Return the MTC of the next thing to search for if found
-// //
-// *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount;
-// break;
-// }
-// }
-// //
-// // Record found exit loop and return
-// //
-// break;
-// }
-// }
-//
-// return Record;
-//}
-//
-///**
-// Search the Head list for a EFI_DATA_HUB_FILTER_DRIVER member that
-// represents Event and return it.
-//
-// @param Head Pointer to head of dual linked list of EFI_DATA_HUB_FILTER_DRIVER structures.
-// @param Event Event to be search for in the Head list.
-//
-// @retval EFI_DATA_HUB_FILTER_DRIVER Returned if Event stored in the Head doubly linked list.
-// @retval NULL If Event is not in the list
-//
-//**/
-//DATA_HUB_FILTER_DRIVER *
-//FindFilterDriverByEvent (
-// IN LIST_ENTRY *Head,
-// IN EFI_EVENT Event
-// )
-//{
-// DATA_HUB_FILTER_DRIVER *FilterEntry;
-// LIST_ENTRY *Link;
-//
-// for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
-// FilterEntry = FILTER_ENTRY_FROM_LINK (Link);
-// if (FilterEntry->Event == Event) {
-// return FilterEntry;
-// }
-// }
-//
-// return NULL;
-//}
-//
-///**
-//
-// Get a previously logged data record and the MonotonicCount for the next
-// available Record. This allows all records or all records later
-// than a give MonotonicCount to be returned. If an optional FilterDriverEvent
-// is passed in with a MonotonicCout of zero return the first record
-// not yet read by the filter driver. If FilterDriverEvent is NULL and
-// MonotonicCount is zero return the first data record.
-//
-// @param This Pointer to the EFI_DATA_HUB_PROTOCOL instance.
-// @param MonotonicCount Specifies the Record to return. On input, zero means
-// return the first record. On output, contains the next
-// record to available. Zero indicates no more records.
-// @param FilterDriverEvent If FilterDriverEvent is not passed in a MonotonicCount
-// of zero, it means to return the first data record.
-// If FilterDriverEvent is passed in, then a MonotonicCount
-// of zero means to return the first data not yet read by
-// FilterDriverEvent.
-// @param Record Returns a dynamically allocated memory buffer with a data
-// record that matches MonotonicCount.
-//
-// @retval EFI_SUCCESS Data was returned in Record.
-// @retval EFI_INVALID_PARAMETER FilterDriverEvent was passed in but does not exist.
-// @retval EFI_NOT_FOUND MonotonicCount does not match any data record in the
-// system. If a MonotonicCount of zero was passed in, then
-// no data records exist in the system.
-// @retval EFI_OUT_OF_RESOURCES Record was not returned due to lack of system resources.
-//
-//**/
-//EFI_STATUS
-//EFIAPI
-//DataHubGetNextRecord (
-// IN EFI_DATA_HUB_PROTOCOL *This,
-// IN OUT UINT64 *MonotonicCount,
-// IN EFI_EVENT *FilterDriverEvent, OPTIONAL
-// OUT EFI_DATA_RECORD_HEADER **Record
-// )
-//{
-// DATA_HUB_INSTANCE *Private;
-// DATA_HUB_FILTER_DRIVER *FilterDriver;
-// UINT64 ClassFilter;
-//
-// Private = DATA_HUB_INSTANCE_FROM_THIS (This);
-//
-// FilterDriver = NULL;
-// ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |
-// EFI_DATA_RECORD_CLASS_ERROR |
-// EFI_DATA_RECORD_CLASS_DATA |
-// EFI_DATA_RECORD_CLASS_PROGRESS_CODE;
-//
-// //
-// // If FilterDriverEvent is NULL, then return the next record
-// //
-// if (FilterDriverEvent == NULL) {
-// *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
-// if (*Record == NULL) {
-// return EFI_NOT_FOUND;
-// }
-// return EFI_SUCCESS;
-// }
-//
-// //
-// // For events the beginning is the last unread record. This info is
-// // stored in the instance structure, so we must look up the event
-// // to get the data.
-// //
-// FilterDriver = FindFilterDriverByEvent (
-// &Private->FilterDriverListHead,
-// *FilterDriverEvent
-// );
-// if (FilterDriver == NULL) {
-// return EFI_INVALID_PARAMETER;
-// }
-// //
-// // Use the Class filter the event was created with.
-// //
-// ClassFilter = FilterDriver->ClassFilter;
-//
-// //
-// // Retrieve the next record or the first record.
-// //
-// if (*MonotonicCount != 0 || FilterDriver->GetNextMonotonicCount == 0) {
-// *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
-// if (*Record == NULL) {
-// return EFI_NOT_FOUND;
-// }
-//
-// if (*MonotonicCount != 0) {
-// //
-// // If this was not the last record then update the count associated with the filter
-// //
-// FilterDriver->GetNextMonotonicCount = *MonotonicCount;
-// } else {
-// //
-// // Save the MonotonicCount of the last record which has been read
-// //
-// FilterDriver->GetNextMonotonicCount = (*Record)->LogMonotonicCount;
-// }
-// return EFI_SUCCESS;
-// }
-//
-// //
-// // This is a request to read the first record that has not been read yet.
-// // Set MonotoicCount to the last record successfuly read
-// //
-// *MonotonicCount = FilterDriver->GetNextMonotonicCount;
-//
-// //
-// // Retrieve the last record successfuly read again, but do not return it since
-// // it has already been returned before.
-// //
-// *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
-// if (*Record == NULL) {
-// return EFI_NOT_FOUND;
-// }
-//
-// if (*MonotonicCount != 0) {
-// //
-// // Update the count associated with the filter
-// //
-// FilterDriver->GetNextMonotonicCount = *MonotonicCount;
-//
-// //
-// // Retrieve the record after the last record successfuly read
-// //
-// *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
-// if (*Record == NULL) {
-// return EFI_NOT_FOUND;
-// }
-// }
-//
-// return EFI_SUCCESS;
-//}
-//
-///**
-// This function registers the data hub filter driver that is represented
-// by FilterEvent. Only one instance of each FilterEvent can be registered.
-// After the FilterEvent is registered, it will be signaled so it can sync
-// with data records that have been recorded prior to the FilterEvent being
-// registered.
-//
-// @param This Pointer to The EFI_DATA_HUB_PROTOCOL instance.
-// @param FilterEvent The EFI_EVENT to signal whenever data that matches
-// FilterClass is logged in the system.
-// @param FilterTpl The maximum EFI_TPL at which FilterEvent can be
-// signaled. It is strongly recommended that you use the
-// lowest EFI_TPL possible.
-// @param FilterClass FilterEvent will be signaled whenever a bit in
-// EFI_DATA_RECORD_HEADER.DataRecordClass is also set in
-// FilterClass. If FilterClass is zero, no class-based
-// filtering will be performed.
-// @param FilterDataRecordGuid FilterEvent will be signaled whenever FilterDataRecordGuid
-// matches EFI_DATA_RECORD_HEADER.DataRecordGuid. If
-// FilterDataRecordGuid is NULL, then no GUID-based filtering
-// will be performed.
-//
-// @retval EFI_SUCCESS The filter driver event was registered.
-// @retval EFI_ALREADY_STARTED FilterEvent was previously registered and cannot be
-// registered again.
-// @retval EFI_OUT_OF_RESOURCES The filter driver event was not registered due to lack of
-// system resources.
-//
-//**/
-//EFI_STATUS
-//EFIAPI
-//DataHubRegisterFilterDriver (
-// IN EFI_DATA_HUB_PROTOCOL * This,
-// IN EFI_EVENT FilterEvent,
-// IN EFI_TPL FilterTpl,
-// IN UINT64 FilterClass,
-// IN EFI_GUID * FilterDataRecordGuid OPTIONAL
-// )
-//
-//{
-// DATA_HUB_INSTANCE *Private;
-// DATA_HUB_FILTER_DRIVER *FilterDriver;
-//
-// Private = DATA_HUB_INSTANCE_FROM_THIS (This);
-//
-// FilterDriver = (DATA_HUB_FILTER_DRIVER *) AllocateZeroPool(sizeof (DATA_HUB_FILTER_DRIVER));
-// if (FilterDriver == NULL) {
-// return EFI_OUT_OF_RESOURCES;
-// }
-// //
-// // Initialize filter driver info
-// //
-// FilterDriver->Signature = EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE;
-// FilterDriver->Event = FilterEvent;
-// FilterDriver->Tpl = FilterTpl;
-// FilterDriver->GetNextMonotonicCount = 0;
-// if (FilterClass == 0) {
-// FilterDriver->ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |
-// EFI_DATA_RECORD_CLASS_ERROR |
-// EFI_DATA_RECORD_CLASS_DATA |
-// EFI_DATA_RECORD_CLASS_PROGRESS_CODE;
-// } else {
-// FilterDriver->ClassFilter = FilterClass;
-// }
-//
-// if (FilterDataRecordGuid != NULL) {
-// CopyMem(&FilterDriver->FilterDataRecordGuid, FilterDataRecordGuid, sizeof (EFI_GUID));
-// }
-// //
-// // Search for duplicate entries
-// //
-// if (FindFilterDriverByEvent (&Private->FilterDriverListHead, FilterEvent) != NULL) {
-// FreePool(FilterDriver);
-// return EFI_ALREADY_STARTED;
-// }
-// //
-// // Make insertion an atomic operation with the lock.
-// //
-// EfiAcquireLock (&Private->DataLock);
-// InsertTailList (&Private->FilterDriverListHead, &FilterDriver->Link);
-// EfiReleaseLock (&Private->DataLock);
-//
-// //
-// // Signal the Filter driver we just loaded so they will recieve all the
-// // previous history. If we did not signal here we would have to wait until
-// // the next data was logged to get the history. In a case where no next
-// // data was logged we would never get synced up.
-// //
-// gBS->SignalEvent (FilterEvent);
-//
-// return EFI_SUCCESS;
-//}
-//
-///**
-// Remove a Filter Driver, so it no longer gets called when data
-// information is logged.
-//
-// @param This Protocol instance structure
-//
-// @param FilterEvent Event that represents a filter driver that is to be
-// Unregistered.
-//
-// @retval EFI_SUCCESS If FilterEvent was unregistered
-// @retval EFI_NOT_FOUND If FilterEvent does not exist
-//**/
-//EFI_STATUS
-//EFIAPI
-//DataHubUnregisterFilterDriver (
-// IN EFI_DATA_HUB_PROTOCOL *This,
-// IN EFI_EVENT FilterEvent
-// )
-//{
-// DATA_HUB_INSTANCE *Private;
-// DATA_HUB_FILTER_DRIVER *FilterDriver;
-//
-// Private = DATA_HUB_INSTANCE_FROM_THIS (This);
-//
-// //
-// // Search for duplicate entries
-// //
-// FilterDriver = FindFilterDriverByEvent (
-// &Private->FilterDriverListHead,
-// FilterEvent
-// );
-// if (FilterDriver == NULL) {
-// return EFI_NOT_FOUND;
-// }
-// //
-// // Make removal an atomic operation with the lock
-// //
-// EfiAcquireLock (&Private->DataLock);
-// RemoveEntryList (&FilterDriver->Link);
-// EfiReleaseLock (&Private->DataLock);
-//
-// return EFI_SUCCESS;
-//}
-//
-//
-//
-///**
-// Driver's Entry point routine that install Driver to produce Data Hub protocol.
-//
-// @param ImageHandle Module's image handle
-// @param SystemTable Pointer of EFI_SYSTEM_TABLE
-//
-// @retval EFI_SUCCESS Logging Hub protocol installed
-// @retval Other No protocol installed, unload driver.
-//
-//**/
-//EFI_STATUS
-//EFIAPI
-//DataHubInstall (
-// IN EFI_HANDLE ImageHandle,
-// IN EFI_SYSTEM_TABLE *SystemTable
-// )
-//{
-// EFI_STATUS Status;
-// UINT32 HighMontonicCount;
-//
-// mPrivateData.Signature = DATA_HUB_INSTANCE_SIGNATURE;
-// mPrivateData.DataHub.LogData = DataHubLogData;
-// mPrivateData.DataHub.GetNextRecord = DataHubGetNextRecord;
-// mPrivateData.DataHub.RegisterFilterDriver = DataHubRegisterFilterDriver;
-// mPrivateData.DataHub.UnregisterFilterDriver = DataHubUnregisterFilterDriver;
-//
-// //
-// // Initialize Private Data in CORE_LOGGING_HUB_INSTANCE that is
-// // required by this protocol
-// //
-// InitializeListHead (&mPrivateData.DataListHead);
-// InitializeListHead (&mPrivateData.FilterDriverListHead);
-//
-// EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);
-//
-// //
-// // Make sure we get a bigger MTC number on every boot!
-// //
-// Status = gRT->GetNextHighMonotonicCount (&HighMontonicCount);
-// if (EFI_ERROR(Status)) {
-// //
-// // if system service fails pick a sane value.
-// //
-// mPrivateData.GlobalMonotonicCount = 0;
-// } else {
-// mPrivateData.GlobalMonotonicCount = LShiftU64 ((UINT64) HighMontonicCount, 32);
-// }
-// //
-// // Make a new handle and install the protocol
-// //
-// mPrivateData.Handle = NULL;
-// Status = gBS->InstallProtocolInterface (
-// &mPrivateData.Handle,
-// &gEfiDataHubProtocolGuid,
-// EFI_NATIVE_INTERFACE,
-// &mPrivateData.DataHub
-// );
-// return Status;
-//}
-
-EFI_DATA_HUB_PROTOCOL *
-DataHubInstall (
- VOID
- );
+ @retval EFI_SUCCESS If data was logged
+ @retval EFI_OUT_OF_RESOURCES If data was not logged due to lack of system
+ resources.
+**/
+EFI_STATUS
+EFIAPI
+DataHubLogData (
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN EFI_GUID *DataRecordGuid,
+ IN EFI_GUID *ProducerName,
+ IN UINT64 DataRecordClass,
+ IN VOID *RawData,
+ IN UINT32 RawDataSize
+ )
+{
+ EFI_STATUS Status;
+ DATA_HUB_INSTANCE *Private;
+ EFI_DATA_ENTRY *LogEntry;
+ UINT32 TotalSize;
+ UINT32 RecordSize;
+ EFI_DATA_RECORD_HEADER *Record;
+ VOID *Raw;
+ DATA_HUB_FILTER_DRIVER *FilterEntry;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Head;
+ EFI_TIME LogTime;
+
+ Private = DATA_HUB_INSTANCE_FROM_THIS (This);
+
+ //
+ // Combine the storage for the internal structs and a copy of the log record.
+ // Record follows PrivateLogEntry. The consumer will be returned a pointer
+ // to Record so we don't what it to be the thing that was allocated from
+ // pool, so the consumer can't free an data record by mistake.
+ //
+ RecordSize = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize;
+ TotalSize = sizeof (EFI_DATA_ENTRY) + RecordSize;
+
+ //
+ // First try to get log time at TPL level <= TPL_CALLBACK.
+ //
+ ZeroMem (&LogTime, sizeof (LogTime));
+ if (EfiGetCurrentTpl() <= TPL_CALLBACK) {
+ gRT->GetTime (&LogTime, NULL);
+ }
+
+ //
+ // The Logging action is the critical section, so it is locked.
+ // The MTC asignment & update and logging must be an
+ // atomic operation, so use the lock.
+ //
+ Status = EfiAcquireLockOrFail (&Private->DataLock);
+ if (EFI_ERROR (Status)) {
+ //
+ // Reentrancy detected so exit!
+ //
+ return Status;
+ }
+
+ LogEntry = AllocatePool (TotalSize);
+
+ if (LogEntry == NULL) {
+ EfiReleaseLock (&Private->DataLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (LogEntry, TotalSize);
+
+ Record = (EFI_DATA_RECORD_HEADER *) (LogEntry + 1);
+ Raw = (VOID *) (Record + 1);
+
+ //
+ // Build Standard Log Header
+ //
+ Record->Version = EFI_DATA_RECORD_HEADER_VERSION;
+ Record->HeaderSize = (UINT16) sizeof (EFI_DATA_RECORD_HEADER);
+ Record->RecordSize = RecordSize;
+ CopyMem (&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID));
+ CopyMem (&Record->ProducerName, ProducerName, sizeof (EFI_GUID));
+ Record->DataRecordClass = DataRecordClass;
+ //
+ // Ensure LogMonotonicCount is not zero
+ //
+ Record->LogMonotonicCount = ++Private->GlobalMonotonicCount;
+
+ CopyMem (&Record->LogTime, &LogTime, sizeof (LogTime));
+
+ //
+ // Insert log into the internal linked list.
+ //
+ LogEntry->Signature = EFI_DATA_ENTRY_SIGNATURE;
+ LogEntry->Record = Record;
+ LogEntry->RecordSize = sizeof (EFI_DATA_ENTRY) + RawDataSize;
+ InsertTailList (&Private->DataListHead, &LogEntry->Link);
+
+ CopyMem (Raw, RawData, RawDataSize);
+
+ EfiReleaseLock (&Private->DataLock);
+
+ //
+ // Send Signal to all the filter drivers which are interested
+ // in the record's class and guid.
+ //
+ Head = &Private->FilterDriverListHead;
+ for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
+ FilterEntry = FILTER_ENTRY_FROM_LINK (Link);
+ if (((FilterEntry->ClassFilter & DataRecordClass) != 0) &&
+ (IsZeroGuid (&FilterEntry->FilterDataRecordGuid) ||
+ CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid))) {
+ gBS->SignalEvent (FilterEntry->Event);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search the Head doubly linked list for the passed in MTC. Return the
+ matching element in Head and the MTC on the next entry.
+
+ @param Head Head of Data Log linked list.
+ @param ClassFilter Only match the MTC if it is in the same Class as the
+ ClassFilter.
+ @param PtrCurrentMTC On IN contians MTC to search for. On OUT contians next
+ MTC in the data log list or zero if at end of the list.
+
+ @retval EFI_DATA_LOG_ENTRY Return pointer to data log data from Head list.
+ @retval NULL If no data record exists.
+
+**/
+EFI_DATA_RECORD_HEADER *
+GetNextDataRecord (
+ IN LIST_ENTRY *Head,
+ IN UINT64 ClassFilter,
+ IN OUT UINT64 *PtrCurrentMTC
+ )
+
+{
+ EFI_DATA_ENTRY *LogEntry;
+ LIST_ENTRY *Link;
+ BOOLEAN ReturnFirstEntry;
+ EFI_DATA_RECORD_HEADER *Record;
+ EFI_DATA_ENTRY *NextLogEntry;
+
+ //
+ // If MonotonicCount == 0 just return the first one
+ //
+ ReturnFirstEntry = (BOOLEAN) (*PtrCurrentMTC == 0);
+
+ Record = NULL;
+ for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
+ LogEntry = DATA_ENTRY_FROM_LINK (Link);
+ if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) {
+ //
+ // Skip any entry that does not have the correct ClassFilter
+ //
+ continue;
+ }
+
+ if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) {
+ //
+ // Return record to the user
+ //
+ Record = LogEntry->Record;
+
+ //
+ // Calculate the next MTC value. If there is no next entry set
+ // MTC to zero.
+ //
+ *PtrCurrentMTC = 0;
+ for (Link = GetNextNode(Head, Link); Link != Head; Link = GetNextNode(Head, Link)) {
+ NextLogEntry = DATA_ENTRY_FROM_LINK (Link);
+ if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) {
+ //
+ // Return the MTC of the next thing to search for if found
+ //
+ *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount;
+ break;
+ }
+ }
+ //
+ // Record found exit loop and return
+ //
+ break;
+ }
+ }
+
+ return Record;
+}
+
+/**
+ Search the Head list for a EFI_DATA_HUB_FILTER_DRIVER member that
+ represents Event and return it.
+
+ @param Head Pointer to head of dual linked list of EFI_DATA_HUB_FILTER_DRIVER structures.
+ @param Event Event to be search for in the Head list.
+
+ @retval EFI_DATA_HUB_FILTER_DRIVER Returned if Event stored in the Head doubly linked list.
+ @retval NULL If Event is not in the list
+
+**/
+DATA_HUB_FILTER_DRIVER *
+FindFilterDriverByEvent (
+ IN LIST_ENTRY *Head,
+ IN EFI_EVENT Event
+ )
+{
+ DATA_HUB_FILTER_DRIVER *FilterEntry;
+ LIST_ENTRY *Link;
+
+ for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
+ FilterEntry = FILTER_ENTRY_FROM_LINK (Link);
+ if (FilterEntry->Event == Event) {
+ return FilterEntry;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+
+ Get a previously logged data record and the MonotonicCount for the next
+ available Record. This allows all records or all records later
+ than a give MonotonicCount to be returned. If an optional FilterDriverEvent
+ is passed in with a MonotonicCout of zero return the first record
+ not yet read by the filter driver. If FilterDriverEvent is NULL and
+ MonotonicCount is zero return the first data record.
+
+ @param This Pointer to the EFI_DATA_HUB_PROTOCOL instance.
+ @param MonotonicCount Specifies the Record to return. On input, zero means
+ return the first record. On output, contains the next
+ record to available. Zero indicates no more records.
+ @param FilterDriverEvent If FilterDriverEvent is not passed in a MonotonicCount
+ of zero, it means to return the first data record.
+ If FilterDriverEvent is passed in, then a MonotonicCount
+ of zero means to return the first data not yet read by
+ FilterDriverEvent.
+ @param Record Returns a dynamically allocated memory buffer with a data
+ record that matches MonotonicCount.
+
+ @retval EFI_SUCCESS Data was returned in Record.
+ @retval EFI_INVALID_PARAMETER FilterDriverEvent was passed in but does not exist.
+ @retval EFI_NOT_FOUND MonotonicCount does not match any data record in the
+ system. If a MonotonicCount of zero was passed in, then
+ no data records exist in the system.
+ @retval EFI_OUT_OF_RESOURCES Record was not returned due to lack of system resources.
+
+**/
+EFI_STATUS
+EFIAPI
+DataHubGetNextRecord (
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN OUT UINT64 *MonotonicCount,
+ IN EFI_EVENT *FilterDriverEvent, OPTIONAL
+ OUT EFI_DATA_RECORD_HEADER **Record
+ )
+{
+ DATA_HUB_INSTANCE *Private;
+ DATA_HUB_FILTER_DRIVER *FilterDriver;
+ UINT64 ClassFilter;
+
+ Private = DATA_HUB_INSTANCE_FROM_THIS (This);
+
+ FilterDriver = NULL;
+ ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |
+ EFI_DATA_RECORD_CLASS_ERROR |
+ EFI_DATA_RECORD_CLASS_DATA |
+ EFI_DATA_RECORD_CLASS_PROGRESS_CODE;
+
+ //
+ // If FilterDriverEvent is NULL, then return the next record
+ //
+ if (FilterDriverEvent == NULL) {
+ *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
+ if (*Record == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+ }
+
+ //
+ // For events the beginning is the last unread record. This info is
+ // stored in the instance structure, so we must look up the event
+ // to get the data.
+ //
+ FilterDriver = FindFilterDriverByEvent (
+ &Private->FilterDriverListHead,
+ *FilterDriverEvent
+ );
+ if (FilterDriver == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Use the Class filter the event was created with.
+ //
+ ClassFilter = FilterDriver->ClassFilter;
+
+ //
+ // Retrieve the next record or the first record.
+ //
+ if (*MonotonicCount != 0 || FilterDriver->GetNextMonotonicCount == 0) {
+ *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
+ if (*Record == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*MonotonicCount != 0) {
+ //
+ // If this was not the last record then update the count associated with the filter
+ //
+ FilterDriver->GetNextMonotonicCount = *MonotonicCount;
+ } else {
+ //
+ // Save the MonotonicCount of the last record which has been read
+ //
+ FilterDriver->GetNextMonotonicCount = (*Record)->LogMonotonicCount;
+ }
+ return EFI_SUCCESS;
+ }
+
+ //
+ // This is a request to read the first record that has not been read yet.
+ // Set MonotoicCount to the last record successfuly read
+ //
+ *MonotonicCount = FilterDriver->GetNextMonotonicCount;
+
+ //
+ // Retrieve the last record successfuly read again, but do not return it since
+ // it has already been returned before.
+ //
+ *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
+ if (*Record == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*MonotonicCount != 0) {
+ //
+ // Update the count associated with the filter
+ //
+ FilterDriver->GetNextMonotonicCount = *MonotonicCount;
+
+ //
+ // Retrieve the record after the last record successfuly read
+ //
+ *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
+ if (*Record == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function registers the data hub filter driver that is represented
+ by FilterEvent. Only one instance of each FilterEvent can be registered.
+ After the FilterEvent is registered, it will be signaled so it can sync
+ with data records that have been recorded prior to the FilterEvent being
+ registered.
+
+ @param This Pointer to The EFI_DATA_HUB_PROTOCOL instance.
+ @param FilterEvent The EFI_EVENT to signal whenever data that matches
+ FilterClass is logged in the system.
+ @param FilterTpl The maximum EFI_TPL at which FilterEvent can be
+ signaled. It is strongly recommended that you use the
+ lowest EFI_TPL possible.
+ @param FilterClass FilterEvent will be signaled whenever a bit in
+ EFI_DATA_RECORD_HEADER.DataRecordClass is also set in
+ FilterClass. If FilterClass is zero, no class-based
+ filtering will be performed.
+ @param FilterDataRecordGuid FilterEvent will be signaled whenever FilterDataRecordGuid
+ matches EFI_DATA_RECORD_HEADER.DataRecordGuid. If
+ FilterDataRecordGuid is NULL, then no GUID-based filtering
+ will be performed.
+
+ @retval EFI_SUCCESS The filter driver event was registered.
+ @retval EFI_ALREADY_STARTED FilterEvent was previously registered and cannot be
+ registered again.
+ @retval EFI_OUT_OF_RESOURCES The filter driver event was not registered due to lack of
+ system resources.
+
+**/
+EFI_STATUS
+EFIAPI
+DataHubRegisterFilterDriver (
+ IN EFI_DATA_HUB_PROTOCOL * This,
+ IN EFI_EVENT FilterEvent,
+ IN EFI_TPL FilterTpl,
+ IN UINT64 FilterClass,
+ IN EFI_GUID * FilterDataRecordGuid OPTIONAL
+ )
+
+{
+ DATA_HUB_INSTANCE *Private;
+ DATA_HUB_FILTER_DRIVER *FilterDriver;
+
+ Private = DATA_HUB_INSTANCE_FROM_THIS (This);
+
+ FilterDriver = (DATA_HUB_FILTER_DRIVER *) AllocateZeroPool (sizeof (DATA_HUB_FILTER_DRIVER));
+ if (FilterDriver == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Initialize filter driver info
+ //
+ FilterDriver->Signature = EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE;
+ FilterDriver->Event = FilterEvent;
+ FilterDriver->Tpl = FilterTpl;
+ FilterDriver->GetNextMonotonicCount = 0;
+ if (FilterClass == 0) {
+ FilterDriver->ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |
+ EFI_DATA_RECORD_CLASS_ERROR |
+ EFI_DATA_RECORD_CLASS_DATA |
+ EFI_DATA_RECORD_CLASS_PROGRESS_CODE;
+ } else {
+ FilterDriver->ClassFilter = FilterClass;
+ }
+
+ if (FilterDataRecordGuid != NULL) {
+ CopyMem (&FilterDriver->FilterDataRecordGuid, FilterDataRecordGuid, sizeof (EFI_GUID));
+ }
+ //
+ // Search for duplicate entries
+ //
+ if (FindFilterDriverByEvent (&Private->FilterDriverListHead, FilterEvent) != NULL) {
+ FreePool (FilterDriver);
+ return EFI_ALREADY_STARTED;
+ }
+ //
+ // Make insertion an atomic operation with the lock.
+ //
+ EfiAcquireLock (&Private->DataLock);
+ InsertTailList (&Private->FilterDriverListHead, &FilterDriver->Link);
+ EfiReleaseLock (&Private->DataLock);
+
+ //
+ // Signal the Filter driver we just loaded so they will recieve all the
+ // previous history. If we did not signal here we would have to wait until
+ // the next data was logged to get the history. In a case where no next
+ // data was logged we would never get synced up.
+ //
+ gBS->SignalEvent (FilterEvent);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Remove a Filter Driver, so it no longer gets called when data
+ information is logged.
+
+ @param This Protocol instance structure
+
+ @param FilterEvent Event that represents a filter driver that is to be
+ Unregistered.
+
+ @retval EFI_SUCCESS If FilterEvent was unregistered
+ @retval EFI_NOT_FOUND If FilterEvent does not exist
+**/
+EFI_STATUS
+EFIAPI
+DataHubUnregisterFilterDriver (
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN EFI_EVENT FilterEvent
+ )
+{
+ DATA_HUB_INSTANCE *Private;
+ DATA_HUB_FILTER_DRIVER *FilterDriver;
+
+ Private = DATA_HUB_INSTANCE_FROM_THIS (This);
+
+ //
+ // Search for duplicate entries
+ //
+ FilterDriver = FindFilterDriverByEvent (
+ &Private->FilterDriverListHead,
+ FilterEvent
+ );
+ if (FilterDriver == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Make removal an atomic operation with the lock
+ //
+ EfiAcquireLock (&Private->DataLock);
+ RemoveEntryList (&FilterDriver->Link);
+ EfiReleaseLock (&Private->DataLock);
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Driver's Entry point routine that install Driver to produce Data Hub protocol.
+
+ @param ImageHandle Module's image handle
+ @param SystemTable Pointer of EFI_SYSTEM_TABLE
+
+ @retval EFI_SUCCESS Logging Hub protocol installed
+ @retval Other No protocol installed, unload driver.
+
+**/
EFI_STATUS
EFIAPI
-CloverDataHubInstall (
+DataHubInstall (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- if ( DataHubInstall() != EFI_SUCCESS) return EFI_NOT_FOUND;
- return EFI_SUCCESS;
+ EFI_STATUS Status;
+ UINT32 HighMontonicCount;
+
+ mPrivateData.Signature = DATA_HUB_INSTANCE_SIGNATURE;
+ mPrivateData.DataHub.LogData = DataHubLogData;
+ mPrivateData.DataHub.GetNextRecord = DataHubGetNextRecord;
+ mPrivateData.DataHub.RegisterFilterDriver = DataHubRegisterFilterDriver;
+ mPrivateData.DataHub.UnregisterFilterDriver = DataHubUnregisterFilterDriver;
+
+ //
+ // Initialize Private Data in CORE_LOGGING_HUB_INSTANCE that is
+ // required by this protocol
+ //
+ InitializeListHead (&mPrivateData.DataListHead);
+ InitializeListHead (&mPrivateData.FilterDriverListHead);
+
+ EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);
+
+ //
+ // Make sure we get a bigger MTC number on every boot!
+ //
+ Status = gRT->GetNextHighMonotonicCount (&HighMontonicCount);
+ if (EFI_ERROR (Status)) {
+ //
+ // if system service fails pick a sane value.
+ //
+ mPrivateData.GlobalMonotonicCount = 0;
+ } else {
+ mPrivateData.GlobalMonotonicCount = LShiftU64 ((UINT64) HighMontonicCount, 32);
+ }
+ //
+ // Make a new handle and install the protocol
+ //
+ mPrivateData.Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &mPrivateData.Handle,
+ &gEfiDataHubProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.DataHub
+ );
+ return Status;
}
diff --git a/Protocols/DataHubDxe/DataHub.h b/Protocols/DataHubDxe/DataHub.h
old mode 100644
new mode 100755
index 11c98ac46c..7770c438da
--- a/Protocols/DataHubDxe/DataHub.h
+++ b/Protocols/DataHubDxe/DataHub.h
@@ -13,121 +13,117 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
-#ifndef _CLOVER_DATA_HUB_H_
-#define _CLOVER_DATA_HUB_H_
+#ifndef _DATA_HUB_H_
+#define _DATA_HUB_H_
-// now using OpenCore library to avoid multiple definition of functions
-#include "../../OpenCorePkg/Library/OcDataHubLib/DataHub.h"
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DATA_HUB_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', 'u', 'b')
+typedef struct {
+ UINT32 Signature;
+
+ EFI_HANDLE Handle;
+
+ //
+ // Produced protocol(s)
+ //
+ EFI_DATA_HUB_PROTOCOL DataHub;
+
+ //
+ // Private Data
+ //
+ //
+ // Updates to GlobalMonotonicCount, LogListHead, and FilterDriverListHead
+ // must be locked.
+ //
+ EFI_LOCK DataLock;
+
+ //
+ // Runing Monotonic Count to use for each error record.
+ // Increment AFTER use in an error record.
+ //
+ UINT64 GlobalMonotonicCount;
+
+ //
+ // List of EFI_DATA_ENTRY structures. This is the data log! The list
+ // must be in assending order of LogMonotonicCount.
+ //
+ LIST_ENTRY DataListHead;
+
+ //
+ // List of EFI_DATA_HUB_FILTER_DRIVER structures. Represents all
+ // the registered filter drivers.
+ //
+ LIST_ENTRY FilterDriverListHead;
+
+} DATA_HUB_INSTANCE;
+
+#define DATA_HUB_INSTANCE_FROM_THIS(this) CR (this, DATA_HUB_INSTANCE, DataHub, DATA_HUB_INSTANCE_SIGNATURE)
//
-//#include
-//
-//#include
-//
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-//
-//#define DATA_HUB_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', 'u', 'b')
-//typedef struct {
-// UINT32 Signature;
-//
-// EFI_HANDLE Handle;
-//
-// //
-// // Produced protocol(s)
-// //
-// EFI_DATA_HUB_PROTOCOL DataHub;
-//
-// //
-// // Private Data
-// //
-// //
-// // Updates to GlobalMonotonicCount, LogListHead, and FilterDriverListHead
-// // must be locked.
-// //
-// EFI_LOCK DataLock;
-//
-// //
-// // Runing Monotonic Count to use for each error record.
-// // Increment AFTER use in an error record.
-// //
-// UINT64 GlobalMonotonicCount;
-//
-// //
-// // List of EFI_DATA_ENTRY structures. This is the data log! The list
-// // must be in assending order of LogMonotonicCount.
-// //
-// LIST_ENTRY DataListHead;
-//
-// //
-// // List of EFI_DATA_HUB_FILTER_DRIVER structures. Represents all
-// // the registered filter drivers.
-// //
-// LIST_ENTRY FilterDriverListHead;
-//
-//} DATA_HUB_INSTANCE;
-//
-//#define DATA_HUB_INSTANCE_FROM_THIS(this) CR (this, DATA_HUB_INSTANCE, DataHub, DATA_HUB_INSTANCE_SIGNATURE)
-//
-////
-//// Private data structure to contain the data log. One record per
-//// structure. Head pointer to the list is the Log member of
-//// EFI_DATA_ENTRY. Record is a copy of the data passed in.
-////
-//#define EFI_DATA_ENTRY_SIGNATURE SIGNATURE_32 ('D', 'r', 'e', 'c')
-//typedef struct {
-// UINT32 Signature;
-// LIST_ENTRY Link;
-//
-// EFI_DATA_RECORD_HEADER *Record;
-//
-// UINTN RecordSize;
-//
-//} EFI_DATA_ENTRY;
-//
-//#define DATA_ENTRY_FROM_LINK(link) CR (link, EFI_DATA_ENTRY, Link, EFI_DATA_ENTRY_SIGNATURE)
-//
-////
-//// Private data to contain the filter driver Event and it's
-//// associated EFI_TPL.
-////
-//#define EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE SIGNATURE_32 ('D', 'h', 'F', 'd')
-//
-//typedef struct {
-// UINT32 Signature;
-// LIST_ENTRY Link;
-//
-// //
-// // Store Filter Driver Event and Tpl level it can be Signaled at.
-// //
-// EFI_EVENT Event;
-// EFI_TPL Tpl;
-//
-// //
-// // Monotonic count on the get next operation for Event.
-// // Zero indicates get next has not been called for this event yet.
-// //
-// UINT64 GetNextMonotonicCount;
-//
-// //
-// // Filter driver will register what class filter should be used.
-// //
-// UINT64 ClassFilter;
+// Private data structure to contain the data log. One record per
+// structure. Head pointer to the list is the Log member of
+// EFI_DATA_ENTRY. Record is a copy of the data passed in.
//
-// //
-// // Filter driver will register what record guid filter should be used.
-// //
-// EFI_GUID FilterDataRecordGuid;
+#define EFI_DATA_ENTRY_SIGNATURE SIGNATURE_32 ('D', 'r', 'e', 'c')
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ EFI_DATA_RECORD_HEADER *Record;
+
+ UINTN RecordSize;
+
+} EFI_DATA_ENTRY;
+
+#define DATA_ENTRY_FROM_LINK(link) CR (link, EFI_DATA_ENTRY, Link, EFI_DATA_ENTRY_SIGNATURE)
+
//
-//} DATA_HUB_FILTER_DRIVER;
+// Private data to contain the filter driver Event and it's
+// associated EFI_TPL.
//
-//#define FILTER_ENTRY_FROM_LINK(link) CR (link, DATA_HUB_FILTER_DRIVER, Link, EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE)
+#define EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE SIGNATURE_32 ('D', 'h', 'F', 'd')
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ //
+ // Store Filter Driver Event and Tpl level it can be Signaled at.
+ //
+ EFI_EVENT Event;
+ EFI_TPL Tpl;
+
+ //
+ // Monotonic count on the get next operation for Event.
+ // Zero indicates get next has not been called for this event yet.
+ //
+ UINT64 GetNextMonotonicCount;
+
+ //
+ // Filter driver will register what class filter should be used.
+ //
+ UINT64 ClassFilter;
+
+ //
+ // Filter driver will register what record guid filter should be used.
+ //
+ EFI_GUID FilterDataRecordGuid;
+
+} DATA_HUB_FILTER_DRIVER;
+
+#define FILTER_ENTRY_FROM_LINK(link) CR (link, DATA_HUB_FILTER_DRIVER, Link, EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE)
#endif
diff --git a/Protocols/DataHubDxe/DataHubDxe.inf b/Protocols/DataHubDxe/DataHubDxe.inf
old mode 100644
new mode 100755
index 338a114bc3..d2c6b04f23
--- a/Protocols/DataHubDxe/DataHubDxe.inf
+++ b/Protocols/DataHubDxe/DataHubDxe.inf
@@ -40,7 +40,7 @@
FILE_GUID = 53BCC14F-C24F-434C-B294-8ED2D4CC1860
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
- ENTRY_POINT = CloverDataHubInstall
+ ENTRY_POINT = DataHubInstall
#
# The following information is for reference only and not required by the build tools.
@@ -67,7 +67,7 @@
BaseLib
UefiLib
UefiDriverEntryPoint
- OcDataHubLib
+ DebugLib
[Protocols]
diff --git a/Protocols/DataHubDxe/DataHubDxe.uni b/Protocols/DataHubDxe/DataHubDxe.uni
old mode 100644
new mode 100755
diff --git a/Protocols/DataHubDxe/DataHubDxeExtra.uni b/Protocols/DataHubDxe/DataHubDxeExtra.uni
old mode 100644
new mode 100755
diff --git a/buildme b/buildme
index c75a7fdf3e..72a8b9c44d 100755
--- a/buildme
+++ b/buildme
@@ -157,7 +157,7 @@ else
./ebuild.sh -fr -D NO_GRUB_DRIVERS_EMBEDDED -D USE_APPLE_HFSPLUS_DRIVER -t $MYTOOLCHAIN
else
./ebuild.sh -fr -mc --no-usb -D NO_GRUB_DRIVERS_EMBEDDED -t $MYTOOLCHAIN
- ./ebuild.sh -fr -D NO_GRUB_DRIVERS_EMBEDDED -t $MYTOOLCHAIN
+ ./ebuild.sh -fr -D NO_GRUB_DRIVERS_EMBEDDED -D LESS_DEBUG -t $MYTOOLCHAIN
fi
fi