summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/Library/ThunkLib
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Haswell/Library/ThunkLib
downloadzprj-master.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/Haswell/Library/ThunkLib')
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm238
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif9
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c245
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf67
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm45
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm45
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm216
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif11
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c272
9 files changed, 1148 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm
new file mode 100644
index 0000000..af9d34c
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm
@@ -0,0 +1,238 @@
+;/*++
+; This file contains an 'Intel Peripheral Driver' and is
+; licensed for Intel CPUs and chipsets under the terms of your
+; license agreement with Intel or your vendor. This file may
+; be modified by the user, subject to additional terms of the
+; license agreement
+;--*/
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+;
+; Module Name:
+;
+; Thunk.asm
+;
+; Abstract:
+;
+; Real mode thunk
+;
+;------------------------------------------------------------------------------
+
+ .686p
+ .model flat,C
+ .const
+
+EXTERNDEF mCode16Size:DWORD
+mCode16Size DD _Code16End - _Code16Addr
+
+ .data
+ ALIGN 10h
+
+NullSegSel DQ 0
+_16CsSegSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 9Bh
+ DB 8Fh ; 16-bit segment, 4GB limit
+ DB 0
+;_16DsSegSel LABEL QWORD
+; DW -1
+; DW 0
+; DB 0
+; DB 93h
+; DB 8Fh ; 16-bit segment, 4GB limit
+; DB 0
+_16Gdtr LABEL FWORD
+ DW $ - offset NullSegSel - 1
+ DD offset NullSegSel
+
+ .code
+
+IA32_REGS STRUC 4t
+_EDI DD ?
+_ESI DD ?
+_EBP DD ?
+_ESP DD ?
+_EBX DD ?
+_EDX DD ?
+_ECX DD ?
+_EAX DD ?
+_DS DW ?
+_ES DW ?
+_FS DW ?
+_GS DW ?
+_EFLAGS DD ?
+_EIP DD ?
+_CS DW ?
+_SS DW ?
+IA32_REGS ENDS
+
+_STK16 STRUC 1t
+RetEip DD ?
+RetCs DW ?
+ThunkFlags DW ?
+SavedGdtr FWORD ?
+Resvd1 DW ?
+SavedCr0 DD ?
+SavedCr4 DD ?
+_STK16 ENDS
+
+; IA32_REGISTER_SET *
+; EFIAPI
+; _Thunk16 (
+; IN OUT IA32_REGISTER_SET *RegisterSet,
+; IN UINT32 ThunkFlags,
+; IN UINT32 RealModeCs
+; );
+_Thunk16 PROC USES DS ES FS GS EDI ESI EBP EBX EDX ECX ; 10 dwords will be pushed
+ mov ebp, esp
+ add ebp, 40
+ mov ORG_SS, ss ; preserve SS & ESP
+ mov ORG_ESP, esp
+
+ mov esi, [ebp + 4] ; esi <- RegisterSet
+ movzx edx, (IA32_REGS ptr [esi])._SS ; find 16-bit stack linear address
+ shl edx, 4
+ add edx, (IA32_REGS ptr [esi])._ESP
+ add edx, - sizeof (IA32_REGS) - sizeof (_STK16) ; edx <- 16-bit stack linear address
+
+ mov edi, edx ; [RealMode.IA32_REGS] <- RegisterSet
+ push sizeof (IA32_REGS) / 4
+ pop ecx
+ rep movsd
+ lea eax, @F ; [RealMode._STK16.RetEip] <- ReturnOffset
+ stosd
+ mov eax, cs ; [RealMode._STK16.RetCs] <- ReturnSegment
+ stosw
+ mov eax, [ebp + 8] ; [RealMode._STK16.ThunkFlags] <- ThunkFlags
+ stosw
+ sgdt dword ptr [edi] ; [RealMode._STK16.SavedGdtr] <- GDTR
+ add edi, 8
+ mov eax, cr0 ; [RealMode._STK16.SavedCr0] <- CR0
+ stosd
+ mov esi, eax ; esi <- CR0 to set
+ and esi, 07FFFFFFEh ; clear BIT[24, 0]: PE & PG bits
+ mov eax, cr4 ; [RealMode._STK16.SavedCr4] <- CR4
+ stosd
+
+ push word ptr [ebp + 12] ; [STACK] <- RealModeCs, far jump address for into RealMode
+ pushw 0
+ pushd 8 ; transfer program control to a readable segment that has a limit of 64KB
+ pushd offset @16Bit
+ mov edi, edx ; edi <- 16-bit stack linear address
+
+ sidt fword ptr [ebp + 8] ; save IDTR
+ lgdt _16Gdtr
+ retf
+@16Bit:
+ mov cr0, esi ; disable PE & PG
+; db 066h
+; mov ecx, 0C0000080h
+; rdmsr
+; and ah, NOT 1
+; wrmsr ; clear LME bit
+ mov eax, cr4
+ and al, not 030h ; clear PAE & PSE
+ mov cr4, eax
+ retf
+@@:
+ xor eax, eax
+ mov eax, ss
+ shl eax, 4
+ add eax, esp ; [EAX] <- RegisterSet after x86 call..to return the execution result
+ mov ss, cs:word ptr [ORG_SS] ; restore SS & ESP
+ mov esp, cs:dword ptr [ORG_ESP]
+ lidt fword ptr [ebp + 8] ; restore IDTR
+
+ ret
+
+ORG_SS DW ?
+ORG_ESP DD ?
+
+_Thunk16 ENDP
+
+ ALIGN 10h
+
+; VOID
+; EFIAPI
+; _Code16Addr (
+; VOID
+; );
+_Code16Addr PROC
+_Code16Addr ENDP
+
+; Input: EDI <- 16-bit stack linear address
+RealMode PROC
+ db 066h ; movzx esp, di
+ movzx esp, di
+ db 033h, 0FFh ; xor di, di
+ db 066h ; shr edi, 4
+ shr edi, 4
+ mov ss, di ; mov ss, di
+
+ db 02Eh, 00Fh, 001, 01Eh ; lidt cs:[_16Idtr]
+ dw (_16Idtr - _Code16Addr)
+ db 066h ; popad
+ popa
+ pop ds
+ pop es
+ pop fs
+ pop gs
+ add esp, 4 ; skip EFLAGS
+
+ ; test if EFLAGS with _THUNK_INTERRUPT
+ db 067h, 00F7h, 044h, 024h, 00Eh, 001h, 000h ; test [esp + 0Eh]
+ jz @F
+ db 09Ch ; pushf
+@@:
+ push cs
+ db 068h ; pushw
+ dw (@FarCallRet - _Code16Addr)
+ jz @F
+ db 066h, 067h
+ jmp fword ptr [esp + 6]
+@@:
+ db 066h, 067h
+ jmp fword ptr [esp + 4]
+@FarCallRet:
+ pushf ; pushfd actually
+ push gs
+ push fs
+ push es
+ push ds
+ db 066h ; pushad
+ pusha
+ cli
+
+ db 066h, 067h
+ lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr
+ db 066h, 067h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4
+ mov cr4, eax
+; db 066h
+; mov ecx, 0C0000080h
+; rdmsr
+; or ah, 1
+; wrmsr ; set LME
+ db 066h, 067h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0
+ mov cr0, eax
+ db 066h, 067h
+ jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip
+
+RealMode ENDP
+
+_16Idtr FWORD (1 shl 10) - 1
+
+_Code16End:
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif
new file mode 100644
index 0000000..e0204e7
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif
@@ -0,0 +1,9 @@
+<component>
+ name = "ThunkLib Ia32"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\ThunkLib\Ia32"
+ RefName = "ThunkLibIa32"
+[files]
+"x86Thunk.c"
+"Thunk16.asm"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c
new file mode 100644
index 0000000..ec1045f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c
@@ -0,0 +1,245 @@
+/** @file
+ Real Mode Thunk Functions for IA32 and X64
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "ThunkLib.h"
+#define _THUNK_INTERRUPT 0x10000
+#endif
+
+extern const UINTN mCode16Size;
+
+extern
+IA32_REGISTER_SET *
+EFIAPI
+_Thunk16 (
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags,
+ IN UINT32 RealModeCs
+ );
+
+extern
+VOID
+EFIAPI
+_Code16Addr (
+ VOID
+ );
+
+/**
+ Returns the properties of this real mode thunk implementation. Currently
+ there are 2 properties has been defined, the minimum real mode buffer size
+ and the minimum stack size.
+
+ @param[in] MinimumStackSize - The minimum size required for a 16-bit stack.
+
+ @retval The minimum size of the real mode buffer needed by this thunk implementation
+ @retval is returned.
+**/
+UINTN
+EFIAPI
+R8AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize
+ )
+{
+ ///
+ /// This size should be large enough to hold the register set as well as saved
+ /// CPU contexts including GDTR, CR0 and CR4
+ ///
+ if (MinimumStackSize) {
+ *MinimumStackSize = sizeof (IA32_REGISTER_SET) + 0x200;
+ }
+
+ return mCode16Size;
+}
+
+/**
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+ @param[in] ThunkContext - The thunk context whose properties to set.
+ @param[in] RealModeBuffer - The address of the buffer allocated by caller. It should be
+ aligned on a 16-byte boundary.
+ This buffer must be in identity mapped pages.
+ @param[in] BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by R8AsmThunk16GetProperties().
+**/
+THUNK16_CONTEXT *
+EFIAPI
+R8AsmThunk16SetProperties (
+ OUT THUNK16_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ )
+{
+ BufferSize &= ~3;
+
+ ASSERT ((UINTN) RealModeBuffer < 0x100000);
+ ASSERT (((UINTN) RealModeBuffer & 0xf) == 0);
+ ASSERT (BufferSize >= mCode16Size);
+
+ ThunkContext->RealModeBuffer = (UINT32) ((UINTN) RealModeBuffer);
+ ThunkContext->DefaultStack = (UINT32) (ThunkContext->RealModeBuffer + BufferSize);
+ CopyMem (RealModeBuffer, (VOID *) (UINTN) _Code16Addr, mCode16Size);
+ return ThunkContext;
+}
+
+/**
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+ @param[in] ThunkContext - The thunk context to destroy.
+**/
+VOID
+EFIAPI
+R8AsmThunk16Destroy (
+ IN OUT THUNK16_CONTEXT *ThunkContext
+ )
+{
+ ThunkContext->RealModeBuffer = 0;
+}
+
+/**
+ Do the 16-bit thunk code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+static
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+{
+ ASSERT (ThunkContext->RealModeBuffer != 0);
+ ASSERT ((ThunkContext->RealModeBuffer & 0xf) == 0);
+
+ if (!(ThunkFlags & THUNK_USER_STACK)) {
+ RegisterSet->E.ESP = (UINT16) ThunkContext->DefaultStack;
+ RegisterSet->E.SS = (UINT16) ((ThunkContext->DefaultStack >> 4) & 0xf000);
+ }
+
+ ASSERT ((RegisterSet->E.ESP >> 16) == 0);
+
+ CopyMem (
+ RegisterSet,
+ _Thunk16 (RegisterSet,
+ (UINT16) (ThunkFlags >> 16),
+ ThunkContext->RealModeBuffer >> 4),
+ sizeof (IA32_REGISTER_SET)
+ );
+
+ return RegisterSet;
+}
+
+/**
+ Make a far call to 16-bit code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ CS:EIP points to the real mode code being called on input.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16FarCall86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags);
+}
+
+/**
+ Invoke a 16-bit interrupt handler.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16Int86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ RegisterSet->E.Eip = (UINT16) ((UINT32 *) NULL)[IntNumber];
+ RegisterSet->E.CS = (UINT16) (((UINT32 *) NULL)[IntNumber] >> 16);
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags | _THUNK_INTERRUPT);
+}
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf b/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf
new file mode 100644
index 0000000..8f760df
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf
@@ -0,0 +1,67 @@
+## @file
+# @todo ADD DESCRIPTION
+#
+#@copyright
+# Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains an 'Intel Peripheral Driver' and uniquely
+# identified as "Intel Reference Module" and is
+# licensed for Intel CPUs and chipsets under the terms of your
+# license agreement with Intel or your vendor. This file may
+# be modified by the user, subject to additional terms of the
+# license agreement
+#
+
+[defines]
+BASE_NAME = ThunkLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+
+[sources.ia32]
+ Ia32/x86Thunk.c
+ Ia32/Thunk16.asm
+
+[sources.x64]
+ x64/x86Thunk.c
+ x64/Thunk16.asm
+ x64/FxSave.asm
+ x64/FxRestore.asm
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+
+[nmake.common]
+ C_FLAGS = $(C_FLAGS)
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm
new file mode 100644
index 0000000..54bab05
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm
@@ -0,0 +1,45 @@
+;/*++
+; This file contains an 'Intel Peripheral Driver' and is
+; licensed for Intel CPUs and chipsets under the terms of your
+; license agreement with Intel or your vendor. This file may
+; be modified by the user, subject to additional terms of the
+; license agreement
+;--*/
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 2010 Intel Corporation. All rights reserved
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+;
+; Module Name:
+;
+; FxRestore.Asm
+;
+; Abstract:
+;
+; AsmFxRestore function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; AsmFxRestore (
+; IN CONST IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxRestore PROC
+ fxrstor [rcx]
+ ret
+AsmFxRestore ENDP
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm
new file mode 100644
index 0000000..c95ba0b
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm
@@ -0,0 +1,45 @@
+;/*++
+; This file contains an 'Intel Peripheral Driver' and is
+; licensed for Intel CPUs and chipsets under the terms of your
+; license agreement with Intel or your vendor. This file may
+; be modified by the user, subject to additional terms of the
+; license agreement
+;--*/
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 2010 Intel Corporation. All rights reserved
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+;
+; Module Name:
+;
+; FxSave.Asm
+;
+; Abstract:
+;
+; AsmFxSave function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; AsmFxSave (
+; OUT IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxSave PROC
+ fxsave [rcx]
+ ret
+AsmFxSave ENDP
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm
new file mode 100644
index 0000000..89bb447
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm
@@ -0,0 +1,216 @@
+;/*++
+; This file contains an 'Intel Peripheral Driver' and is
+; licensed for Intel CPUs and chipsets under the terms of your
+; license agreement with Intel or your vendor. This file may
+; be modified by the user, subject to additional terms of the
+; license agreement
+;--*/
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 2010 Intel Corporation. All rights reserved
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+;
+; Module Name:
+;
+; Thunk.asm
+;
+; Abstract:
+;
+; Real mode thunk
+;
+;------------------------------------------------------------------------------
+
+EXTERNDEF mCode16Size:QWORD
+
+ .const
+
+mCode16Size DQ _Code16End - _Code16Addr
+
+ .data
+
+NullSegSel DQ 0
+_16CsSegSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 9bh
+ DB 8fh ; 16-bit segment
+ DB 0
+
+_16Gdtr LABEL FWORD
+ DW $ - offset NullSegSel - 1
+ DQ offset NullSegSel
+
+ .code
+
+IA32_REGS STRUC 4t
+_EDI DD ?
+_ESI DD ?
+_EBP DD ?
+_ESP DD ?
+_EBX DD ?
+_EDX DD ?
+_ECX DD ?
+_EAX DD ?
+_DS DW ?
+_ES DW ?
+_FS DW ?
+_GS DW ?
+_RFLAGS DQ ?
+_EIP DD ?
+_CS DW ?
+_SS DW ?
+IA32_REGS ENDS
+
+_STK16 STRUC 1t
+RetEip DD ?
+RetCs DW ?
+ThunkFlags DW ?
+SavedGdtr FWORD ?
+Resvd1 DW ?
+SavedCr0 DD ?
+SavedCr4 DD ?
+_STK16 ENDS
+
+_Thunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15
+
+ push fs
+ push gs
+
+ mov r12d, ds
+ mov r13d, es
+ mov r14d, ss
+ mov r15, rsp
+ mov rsi, rcx
+ movzx r10, (IA32_REGS ptr [rsi])._SS
+ xor rdi, rdi
+ mov edi, (IA32_REGS ptr [rsi])._ESP
+ add rdi, - sizeof (IA32_REGS) - sizeof (_STK16)
+ push rdi
+ imul rax, r10, 16
+ add rdi, rax
+ push sizeof (IA32_REGS) / 4
+ pop rcx
+ rep movsd
+ pop rbx ; rbx <- 16-bit stack offset
+ lea eax, @F ; return offset
+ stosd
+ mov eax, cs ; return segment
+ stosw
+ mov eax, edx ; THUNK Flags
+ stosw
+ sgdt fword ptr [rsp + 58h] ; save GDTR
+ mov rax, [rsp + 58h]
+ stosq
+ mov rax, cr0 ; save CR0
+ mov esi, eax ; esi <- CR0 to set
+ stosd
+ mov rax, cr4 ; save CR4
+ stosd
+ sidt fword ptr [rsp + 58h] ; save IDTR
+ and esi, 07ffffffeh ;NOT 080000001h ; clear PE & PG bits
+ mov rdi, r10 ; rdi <- 16-bit stack segment
+
+ shl r8, 16
+ push r8 ; far jmp address
+ lea eax, @16Bit
+ push rax
+ mov word ptr [rsp + 4], 8
+ lgdt _16Gdtr
+ retf
+@16Bit:
+ mov cr0, rsi ; disable PE & PG
+ DB 66h
+ mov ecx, 0c0000080h
+ rdmsr
+ and ah, NOT 1
+ wrmsr ; clear LME bit
+ mov rax, cr4
+ and al, NOT 30h ; clear PAE & PSE
+ mov cr4, rax
+ retf
+@@:
+ xor rax, rax
+ mov eax, ss
+ shl eax, 4
+ add eax, esp ; rax <- address of 16-bit stack
+ mov rsp, r15
+ lidt fword ptr [rsp + 58h] ; restore IDTR
+ mov ds, r12d
+ mov es, r13d
+ mov ss, r14d
+ pop gs
+ pop fs
+ ret
+_Thunk16 ENDP
+
+ ALIGN 10h
+
+_Code16Addr PROC
+_Code16Addr ENDP
+
+RealMode PROC
+ mov ss, edi
+ mov sp, bx ; set up 16-bit stack
+ DB 2eh, 0fh, 1, 1eh
+ DW _16Idtr - _Code16Addr ; lidt _16Idtr
+ DB 66h, 61h ; popad
+ DB 1fh ; pop ds
+ DB 7 ; pop es
+ pop fs
+ pop gs
+
+ add esp, 8 ; skip RFLAGS
+ DB 67h, 0f7h, 44h, 24h, 0eh, 1, 0 ; test [esp + 0eh], 1
+ jz @F
+ pushfq ; pushf, actually
+@@:
+ DB 0eh ; push cs
+ DB 68h ; push /iw
+ DW @FarCallRet - _Code16Addr
+ jz @F
+ DB 66h
+ jmp fword ptr [esp + 6]
+@@:
+ DB 66h
+ jmp fword ptr [esp + 4]
+@FarCallRet:
+ DB 66h
+ push 0 ; push a dword of zero
+ pushf ; pushfd, actually
+ push gs
+ push fs
+ DB 6 ; push es
+ DB 1eh ; push ds
+ DB 66h, 60h ; pushad
+ cli
+
+ DB 66h
+ lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr
+ DB 66h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4
+ mov cr4, rax
+ DB 66h
+ mov ecx, 0c0000080h
+ rdmsr
+ or ah, 1
+ wrmsr ; set LME
+ DB 66h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0
+ mov cr0, rax
+ DB 66h
+ jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip
+
+RealMode ENDP
+
+_16Idtr FWORD (1 SHL 10) - 1
+
+_Code16End:
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif b/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif
new file mode 100644
index 0000000..aa6ac0f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "ThunkLib x64"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\ThunkLib\x64"
+ RefName = "ThunkLibx64"
+[files]
+"x86Thunk.c"
+"Thunk16.asm"
+"FxSave.asm"
+"FxRestore.asm"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c b/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c
new file mode 100644
index 0000000..dadb37e
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c
@@ -0,0 +1,272 @@
+/** @file
+ Real Mode Thunk Functions for IA32 and X64
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "ThunkLib.h"
+#define _THUNK_INTERRUPT 0x10000
+#endif
+
+extern const UINTN mCode16Size;
+
+extern
+IA32_REGISTER_SET *
+EFIAPI
+_Thunk16 (
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags,
+ IN UINT32 RealModeCs
+ );
+
+extern
+VOID
+EFIAPI
+_Code16Addr (
+ VOID
+ );
+
+extern
+void
+EFIAPI
+AsmFxRestore (
+ IN CONST IA32_FX_BUFFER *Buffer
+ );
+
+extern
+void
+EFIAPI
+AsmFxSave (
+ OUT IA32_FX_BUFFER *Buffer
+ );
+
+/**
+ Returns the properties of this real mode thunk implementation. Currently
+ there are 2 properties has been defined, the minimum real mode buffer size
+ and the minimum stack size.
+
+ @param[in] MinimumStackSize - The minimum size required for a 16-bit stack.
+
+ @retval The minimum size of the real mode buffer needed by this thunk implementation
+ @retval is returned.
+**/
+UINTN
+EFIAPI
+R8AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize
+ )
+{
+ ///
+ /// This size should be large enough to hold the register set as well as saved
+ /// CPU contexts including GDTR, CR0 and CR4
+ ///
+ if (MinimumStackSize) {
+ *MinimumStackSize = sizeof (IA32_REGISTER_SET) + 0x200;
+ }
+
+ return mCode16Size;
+}
+
+/**
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+ @param[in] ThunkContext - The thunk context whose properties to set.
+ @param[in] RealModeBuffer - The address of the buffer allocated by caller. It should be
+ aligned on a 16-byte boundary.
+ This buffer must be in identity mapped pages.
+ @param[in] BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by R8AsmThunk16GetProperties().
+**/
+THUNK16_CONTEXT *
+EFIAPI
+R8AsmThunk16SetProperties (
+ OUT THUNK16_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ )
+{
+ BufferSize &= ~3;
+
+ ASSERT ((UINTN) RealModeBuffer < 0x100000);
+ ASSERT (((UINTN) RealModeBuffer & 0xf) == 0);
+ ASSERT (BufferSize >= mCode16Size);
+
+ ThunkContext->RealModeBuffer = (UINT32) (UINTN) RealModeBuffer;
+ ThunkContext->DefaultStack = (UINT32) (ThunkContext->RealModeBuffer + BufferSize);
+ CopyMem (RealModeBuffer, (VOID *) (UINTN) _Code16Addr, mCode16Size);
+ return ThunkContext;
+}
+
+/**
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+ @param[in] ThunkContext - The thunk context to destroy.
+**/
+VOID
+EFIAPI
+R8AsmThunk16Destroy (
+ IN OUT THUNK16_CONTEXT *ThunkContext
+ )
+{
+ ThunkContext->RealModeBuffer = 0;
+}
+
+/**
+ Do the 16-bit thunk code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+static
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+{
+ IA32_FX_BUFFER *FpSavedState;
+ UINT8 FpBuffer[sizeof (*FpSavedState) + 0x10];
+
+ ASSERT (ThunkContext->RealModeBuffer != 0);
+ ASSERT ((ThunkContext->RealModeBuffer & 0xf) == 0);
+
+ FpSavedState = (IA32_FX_BUFFER *) (((UINTN) FpBuffer + 0xf) &~0xf);
+
+ if (!(ThunkFlags & THUNK_USER_STACK)) {
+ RegisterSet->E.ESP = (UINT16) ThunkContext->DefaultStack;
+ RegisterSet->E.SS = (UINT16) ((ThunkContext->DefaultStack >> 4) & 0xf000);
+ }
+
+ if (ThunkFlags & THUNK_SAVE_FP_STATE) {
+ AsmFxSave (FpSavedState);
+ }
+
+ ASSERT ((RegisterSet->E.ESP >> 16) == 0);
+
+ CopyMem (
+ RegisterSet,
+ _Thunk16 (RegisterSet,
+ (UINT16) (ThunkFlags >> 16),
+ ThunkContext->RealModeBuffer >> 4),
+ sizeof (*RegisterSet)
+ );
+
+ if (ThunkFlags & THUNK_SAVE_FP_STATE) {
+ AsmFxRestore (FpSavedState);
+ }
+
+ return RegisterSet;
+}
+
+/**
+ Make a far call to 16-bit code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ CS:EIP points to the real mode code being called on input.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16FarCall86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags);
+}
+
+/**
+ Invoke a 16-bit interrupt handler.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16Int86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ RegisterSet->E.Eip = (UINT16) ((UINT32 *) NULL)[IntNumber];
+ RegisterSet->E.CS = (UINT16) (((UINT32 *) NULL)[IntNumber] >> 16);
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags | _THUNK_INTERRUPT);
+}