summaryrefslogtreecommitdiff
path: root/EdkCompatibilityPkg/Foundation/Library/Thunk16
diff options
context:
space:
mode:
authorqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>2007-06-28 07:00:39 +0000
committerqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>2007-06-28 07:00:39 +0000
commit3eb9473ea9a949badfe06ae61d2d3fcfa53651c7 (patch)
treee9d8c368dbb1e58794b2c00acefe4bbad270f8c4 /EdkCompatibilityPkg/Foundation/Library/Thunk16
parent30d4a0c7ec19938196b1308006b990e0945150da (diff)
downloadedk2-platforms-3eb9473ea9a949badfe06ae61d2d3fcfa53651c7.tar.xz
Add in the 1st version of ECP.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2832 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkCompatibilityPkg/Foundation/Library/Thunk16')
-rw-r--r--EdkCompatibilityPkg/Foundation/Library/Thunk16/Ia32/Fx.asm51
-rw-r--r--EdkCompatibilityPkg/Foundation/Library/Thunk16/Ia32/Thunk16.asm199
-rw-r--r--EdkCompatibilityPkg/Foundation/Library/Thunk16/Thunk16Lib.h348
-rw-r--r--EdkCompatibilityPkg/Foundation/Library/Thunk16/Thunk16Lib.inf49
-rw-r--r--EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Fx.asm46
-rw-r--r--EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Thunk16.asm216
-rw-r--r--EdkCompatibilityPkg/Foundation/Library/Thunk16/x86Thunk.c320
7 files changed, 1229 insertions, 0 deletions
diff --git a/EdkCompatibilityPkg/Foundation/Library/Thunk16/Ia32/Fx.asm b/EdkCompatibilityPkg/Foundation/Library/Thunk16/Ia32/Fx.asm
new file mode 100644
index 0000000000..f6e70d2e7c
--- /dev/null
+++ b/EdkCompatibilityPkg/Foundation/Library/Thunk16/Ia32/Fx.asm
@@ -0,0 +1,51 @@
+;*****************************************************************************
+;*
+;* Copyright (c) 2006, 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:
+;*
+;* Fx.asm
+;*
+;* Abstract:
+;*
+;* AsmFxRestore and AsmFxSave function
+;*
+;*****************************************************************************
+
+ .586P
+ .model flat,C
+ .xmm
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; AsmFxSave (
+; OUT IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxSave PROC
+ mov eax, [esp + 4]
+ fxsave [eax]
+ ret
+AsmFxSave ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; AsmFxRestore (
+; IN CONST IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxRestore PROC
+ mov eax, [esp + 4]
+ fxrstor [eax]
+ ret
+AsmFxRestore ENDP
+
+ END
diff --git a/EdkCompatibilityPkg/Foundation/Library/Thunk16/Ia32/Thunk16.asm b/EdkCompatibilityPkg/Foundation/Library/Thunk16/Ia32/Thunk16.asm
new file mode 100644
index 0000000000..b59583effd
--- /dev/null
+++ b/EdkCompatibilityPkg/Foundation/Library/Thunk16/Ia32/Thunk16.asm
@@ -0,0 +1,199 @@
+;*****************************************************************************
+;*
+;* Copyright (c) 2006 - 2007, 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:
+;*
+;* Thunk.asm
+;*
+;* Abstract:
+;*
+;* Real mode thunk
+;*
+;*****************************************************************************
+
+ .686p
+
+EXTERNDEF C mCode16Size:DWORD
+
+CONST SEGMENT FLAT "DATA" READONLY
+
+mCode16Size DD _TEXT16SIZE
+
+CONST ENDS
+
+_DATA SEGMENT FLAT "DATA"
+
+NullSegSel DQ 0
+_16BitCsSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 9bh
+ DB 8fh ; 16-bit segment
+ DB 0
+_16BitSsSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 93h
+ DB 8fh ; 16-bit segment
+ DB 0
+
+_16Gdtr LABEL FWORD
+ DW $ - offset NullSegSel - 1
+ DD offset NullSegSel
+
+_DATA ENDS
+
+_TEXT SEGMENT FLAT "CODE" PARA
+
+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 ?
+SavedEsp DD ?
+SavedSs DW ?
+SavedGdtr FWORD ?
+SavedCr0 DD ?
+SavedCr4 DD ?
+_STK16 ENDS
+
+ ASSUME ds:_DATA
+
+__Thunk16 PROC USES ebp ebx esi edi ds es fs gs
+ ASSUME esi:PTR IA32_REGS
+ mov esi, [esp + 36]
+ movzx edx, [esi]._SS
+ mov edi, [esi]._ESP
+ add edi, - sizeof (_STK16) - sizeof (IA32_REGS)
+ push edi ; save stack offset
+ imul eax, edx, 16 ; eax <- edx*16
+ add edi, eax ; edi <- linear address of 16-bit stack
+ push sizeof (IA32_REGS) / 4
+ pop ecx
+ rep movsd ; copy context to 16-bit stack
+ pop ebx ; ebx <- 16-bit stack offset
+ mov eax, offset @F ; return offset
+ stosd
+ mov eax, cs ; return segment
+ stosw
+ mov eax, [esp + 40] ; THUNK flags
+ stosw
+ mov eax, esp
+ stosd ; save esp
+ mov eax, ss ; save ss
+ stosw
+ sgdt fword ptr [edi] ; save GDTR
+ sidt fword ptr [esp + 36] ; save IDTR
+ mov esi, cr0
+ mov [edi + 6], esi ; save CR0
+ and esi, NOT 80000001h ; esi <- CR0 to set
+ mov eax, cr4
+ mov [edi + 10], eax ; save CR4
+ and al, NOT 30h ; clear PAE & PSE
+ mov edi, edx ; edi <- 16-bit stack segment
+ mov edx, [esp + 44]
+ shl edx, 16
+ push edx
+ pop edx
+ mov dx, _16BitSsSel - NullSegSel
+ lgdt _16Gdtr ; load 16-bit GDTR
+ DB 0eah
+ DD offset @16Bit
+ DW _16BitCsSel - NullSegSel ; jmp far 8:@16Bit
+@16Bit:
+ mov ss, dx
+ mov cr0, esi ; disable protected mode
+ mov cr4, eax ; disable PAE & PSE
+ db 67h, 0FFh, 06Ch, 024h, 0FCh ; jmp dword ptr [esp-4]
+@@:
+ mov eax, ss
+ shl eax, 4
+ add eax, esp ; eax <- address of 16-bit stack
+ lss esp, fword ptr (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedEsp
+ lidt fword ptr [esp + 36] ; restore IDTR
+ ret
+__Thunk16 ENDP
+
+_TEXT ENDS
+
+_TEXT16 SEGMENT USE16 "CODE" PARA
+
+_Code16Addr PROC C
+_Code16Addr ENDP
+
+RealMode PROC
+ mov ss, di ; set up stack
+ mov esp, ebx
+ lidt fword ptr cs:[_16Idtr - _Code16Addr]
+ popad
+ pop ds
+ pop es
+ pop fs
+ pop gs
+ add sp, 4 ; skip EFlags
+ test (_STK16 ptr [esp + 8]).ThunkFlags, 1
+ jz @F
+ pushf
+@@:
+ push cs
+; push @FarCallRet - _Code16Addr
+ DB 68h ; push /iw
+ DW @FarCallRet - _Code16Addr
+ jz @F
+ jmp fword ptr [esp + 6]
+@@:
+ jmp fword ptr [esp + 4]
+@FarCallRet:
+ pushfd
+ push gs
+ push fs
+ push es
+ push ds
+ pushad
+ cli
+ DB 66h
+ lgdt (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedGdtr
+ mov eax, (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedCr4
+ mov cr4, eax
+ mov eax, (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedCr0
+ mov cr0, eax ; restore CR0
+ jmp fword ptr (_STK16 ptr [esp + sizeof (IA32_REGS)]).RetEip
+RealMode ENDP
+
+_16Idtr FWORD (1 SHL 10) - 1
+
+_TEXT16END:
+
+_TEXT16SIZE = _TEXT16END - _Code16Addr
+
+_TEXT16 ENDS
+
+ END
diff --git a/EdkCompatibilityPkg/Foundation/Library/Thunk16/Thunk16Lib.h b/EdkCompatibilityPkg/Foundation/Library/Thunk16/Thunk16Lib.h
new file mode 100644
index 0000000000..226c0160b9
--- /dev/null
+++ b/EdkCompatibilityPkg/Foundation/Library/Thunk16/Thunk16Lib.h
@@ -0,0 +1,348 @@
+/*++
+
+Copyright (c) 2006, 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:
+
+ Thunk16Lib.h
+
+Abstract:
+
+ Real Mode Thunk Header file
+
+--*/
+
+#ifndef __THUNK_16_LIB_H__
+#define __THUNK_16_LIB_H__
+#include "Tiano.h"
+
+//
+// Thunk Flags
+//
+#define THUNK_SAVE_FP_STATE 0x1
+#define THUNK_USER_STACK 0x2
+#define THUNK_INTERRUPT 0x10000
+
+//
+// Byte packed structure for 16-bit Real Mode FLAGS
+//
+typedef union {
+ struct {
+ UINT32 CF:1; // Carry Flag
+ UINT32 Reserved_0:1; // Reserved
+ UINT32 PF:1; // Parity Flag
+ UINT32 Reserved_1:1; // Reserved
+ UINT32 AF:1; // Auxiliary Carry Flag
+ UINT32 Reserved_2:1; // Reserved
+ UINT32 ZF:1; // Zero Flag
+ UINT32 SF:1; // Sign Flag
+ UINT32 TF:1; // Trap Flag
+ UINT32 IF:1; // Interrupt Enable Flag
+ UINT32 DF:1; // Direction Flag
+ UINT32 OF:1; // Overflow Flag
+ UINT32 IOPL:2; // I/O Privilege Level
+ UINT32 NT:1; // Nested Task
+ UINT32 Reserved_3:1; // Reserved
+ } Bits;
+ UINTN UintN;
+} IA32_FLAGS16;
+
+//
+// Byte packed structure for EFLAGS
+// 32-bits on IA32
+// 64-bits on X64
+//
+
+typedef union {
+ struct {
+ UINT32 CF:1; // Carry Flag
+ UINT32 Reserved_0:1; // Reserved
+ UINT32 PF:1; // Parity Flag
+ UINT32 Reserved_1:1; // Reserved
+ UINT32 AF:1; // Auxiliary Carry Flag
+ UINT32 Reserved_2:1; // Reserved
+ UINT32 ZF:1; // Zero Flag
+ UINT32 SF:1; // Sign Flag
+ UINT32 TF:1; // Trap Flag
+ UINT32 IF:1; // Interrupt Enable Flag
+ UINT32 DF:1; // Direction Flag
+ UINT32 OF:1; // Overflow Flag
+ UINT32 IOPL:2; // I/O Privilege Level
+ UINT32 NT:1; // Nested Task
+ UINT32 Reserved_3:1; // Reserved
+ UINT32 RF:1; // Resume Flag
+ UINT32 VM:1; // Virtual 8086 Mode
+ UINT32 AC:1; // Alignment Check
+ UINT32 VIF:1; // Virtual Interrupt Flag
+ UINT32 VIP:1; // Virtual Interrupt Pending
+ UINT32 ID:1; // ID Flag
+ UINT32 Reserved_4:10; // Reserved
+ } Bits;
+ UINTN UintN;
+} IA32_EFLAGS32;
+
+//
+// Byte packed structure for an FP/SSE/SSE2 context
+//
+typedef struct {
+ UINT8 Buffer[512];
+} IA32_FX_BUFFER;
+
+//
+// Structures for the 16-bit real mode thunks
+//
+typedef struct {
+ UINT32 Reserved1;
+ UINT32 Reserved2;
+ UINT32 Reserved3;
+ UINT32 Reserved4;
+ UINT8 BL;
+ UINT8 BH;
+ UINT16 Reserved5;
+ UINT8 DL;
+ UINT8 DH;
+ UINT16 Reserved6;
+ UINT8 CL;
+ UINT8 CH;
+ UINT16 Reserved7;
+ UINT8 AL;
+ UINT8 AH;
+ UINT16 Reserved8;
+} IA32_BYTE_REGS;
+
+typedef struct {
+ UINT16 DI;
+ UINT16 Reserved1;
+ UINT16 SI;
+ UINT16 Reserved2;
+ UINT16 BP;
+ UINT16 Reserved3;
+ UINT16 SP;
+ UINT16 Reserved4;
+ UINT16 BX;
+ UINT16 Reserved5;
+ UINT16 DX;
+ UINT16 Reserved6;
+ UINT16 CX;
+ UINT16 Reserved7;
+ UINT16 AX;
+ UINT16 Reserved8;
+ UINT16 DS;
+ UINT16 ES;
+ UINT16 FS;
+ UINT16 GS;
+ IA32_FLAGS16 Flags;
+ UINT16 IP;
+ UINT16 Reserved10;
+ UINT16 CS;
+ UINT16 SS;
+} IA32_WORD_REGS;
+
+typedef struct {
+ UINT32 EDI;
+ UINT32 ESI;
+ UINT32 EBP;
+ UINT32 ESP;
+ UINT32 EBX;
+ UINT32 EDX;
+ UINT32 ECX;
+ UINT32 EAX;
+ UINT16 DS;
+ UINT16 ES;
+ UINT16 FS;
+ UINT16 GS;
+ IA32_EFLAGS32 EFLAGS;
+ UINT32 EIP;
+ UINT16 CS;
+ UINT16 SS;
+} IA32_DWORD_REGS;
+
+typedef union {
+ IA32_DWORD_REGS E;
+ IA32_WORD_REGS X;
+ IA32_BYTE_REGS H;
+} IA32_REGISTER_SET;
+
+//
+// Byte packed structure for an 16-bit real mode thunks
+//
+typedef struct {
+ UINT32 RealModeBuffer;
+ UINT32 DefaultStack;
+} THUNK_CONTEXT;
+
+//
+// 16-bit thunking services
+//
+
+UINTN
+EFIAPI
+AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+Arguments:
+
+ MinimumStackSize - The minimum size required for a 16-bit stack.
+
+Returns:
+
+ The minimum size of the real mode buffer needed by this thunk implementation
+ is returned.
+
+--*/
+;
+
+THUNK_CONTEXT *
+EFIAPI
+AsmThunk16SetProperties (
+ OUT THUNK_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+Arguments:
+
+ ThunkContext - The thunk context whose properties to set.
+ 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.
+ BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by AsmThunk16GetProperties().
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+EFIAPI
+AsmThunk16Destroy (
+ IN OUT THUNK_CONTEXT *ThunkContext
+ )
+/*++
+
+Routine Description:
+
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+Arguments:
+
+ ThunkContext - The thunk context to destroy.
+
+Returns:
+
+ None
+
+--*/
+;
+
+IA32_REGISTER_SET *
+EFIAPI
+AsmThunk16FarCall86 (
+ IN THUNK_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+Arguments:
+
+ ThunkContext - Thunk context to use.
+ 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.
+ 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.
+
+Returns:
+
+ RegisterSet is returned.
+
+--*/
+;
+
+IA32_REGISTER_SET *
+EFIAPI
+AsmThunk16Int86 (
+ IN THUNK_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+Arguments:
+
+ ThunkContext - Thunk context to use.
+ IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ 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.
+ 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.
+
+Returns:
+
+ RegisterSet is returned.
+
+--*/
+;
+
+#endif
diff --git a/EdkCompatibilityPkg/Foundation/Library/Thunk16/Thunk16Lib.inf b/EdkCompatibilityPkg/Foundation/Library/Thunk16/Thunk16Lib.inf
new file mode 100644
index 0000000000..5134caf080
--- /dev/null
+++ b/EdkCompatibilityPkg/Foundation/Library/Thunk16/Thunk16Lib.inf
@@ -0,0 +1,49 @@
+#/*++
+#
+# Copyright (c) 2006, 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:
+#
+# Thunk16Lib.inf
+#
+# Abstract:
+#
+#--*/
+
+[defines]
+BASE_NAME = Thunk16Lib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ x86Thunk.c
+
+[sources.ia32]
+ Ia32\Thunk16.asm
+ Ia32\Fx.asm
+
+[sources.x64]
+ X64\Thunk16.asm
+ X64\Fx.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
+ $(EDK_SOURCE)\Foundation\Include\IndustryStandard
+ $(EDK_SOURCE)\Foundation\Library\Dxe\Include
+
+[libraries.common]
+
+
+[nmake.common]
diff --git a/EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Fx.asm b/EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Fx.asm
new file mode 100644
index 0000000000..77490b44b5
--- /dev/null
+++ b/EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Fx.asm
@@ -0,0 +1,46 @@
+;*****************************************************************************
+;*
+;* Copyright (c) 2006, 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:
+;*
+;* Fx.asm
+;*
+;* Abstract:
+;*
+;* AsmFxRestore and AsmFxSave function
+;*
+;*****************************************************************************
+
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; AsmFxSave (
+; OUT IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxSave PROC
+ fxsave [rcx]
+ ret
+AsmFxSave ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; AsmFxRestore (
+; IN CONST IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxRestore PROC
+ fxrstor [rcx]
+ ret
+AsmFxRestore ENDP
+
+ END
diff --git a/EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Thunk16.asm b/EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Thunk16.asm
new file mode 100644
index 0000000000..641e8d285f
--- /dev/null
+++ b/EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Thunk16.asm
@@ -0,0 +1,216 @@
+;*****************************************************************************
+;*
+;* Copyright (c) 2006, 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:
+;*
+;* 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
+_16DsSegSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 93h
+ 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 ; 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:
+ DB 66h
+ mov ecx, 0c0000080h
+ mov cr0, rsi ; disable PE & PG
+ 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/EdkCompatibilityPkg/Foundation/Library/Thunk16/x86Thunk.c b/EdkCompatibilityPkg/Foundation/Library/Thunk16/x86Thunk.c
new file mode 100644
index 0000000000..9bd77e24ca
--- /dev/null
+++ b/EdkCompatibilityPkg/Foundation/Library/Thunk16/x86Thunk.c
@@ -0,0 +1,320 @@
+/*++
+
+Copyright (c) 2006, 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:
+
+ x86Thunk.c
+
+Abstract:
+
+ Real Mode Thunk Functions
+
+--*/
+
+#include "Thunk16Lib.h"
+#include "EfiCommonLib.h"
+
+#define IA32API __cdecl
+
+extern CONST UINTN mCode16Size;
+
+extern
+IA32_REGISTER_SET *
+IA32API
+_Thunk16 (
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags,
+ IN UINT32 RealModeCs
+ );
+
+extern
+VOID
+IA32API
+_Code16Addr (
+ VOID
+ );
+
+VOID
+IA32API
+AsmFxRestore (
+ IN CONST IA32_FX_BUFFER *Buffer
+ );
+
+VOID
+IA32API
+AsmFxSave (
+ OUT IA32_FX_BUFFER *Buffer
+ );
+
+//
+// Implementation
+//
+STATIC
+IA32_REGISTER_SET *
+AsmThunk16 (
+ IN THUNK_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+Arguments:
+
+ ThunkContext - Thunk context to use.
+ 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.
+ 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.
+
+Returns:
+
+ RegisterSet is returned.
+
+--*/
+{
+ IA32_FX_BUFFER *FpSavedState;
+ UINT8 FpBuffer[sizeof (*FpSavedState) + 0x10];
+
+ 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);
+ }
+
+ EfiCommonLibCopyMem (
+ RegisterSet,
+ _Thunk16 (
+ RegisterSet,
+ (UINT16)(ThunkFlags >> 16),
+ ThunkContext->RealModeBuffer >> 4
+ ),
+ sizeof (*RegisterSet)
+ );
+
+ if (ThunkFlags & THUNK_SAVE_FP_STATE) {
+ AsmFxRestore (FpSavedState);
+ }
+
+ return RegisterSet;
+}
+
+UINTN
+EFIAPI
+AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+Arguments:
+
+ MinimumStackSize - The minimum size required for a 16-bit stack.
+
+Returns:
+
+ The minimum size of the real mode buffer needed by this thunk implementation
+ is returned.
+
+--*/
+{
+ //
+ // 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;
+}
+
+THUNK_CONTEXT *
+EFIAPI
+AsmThunk16SetProperties (
+ OUT THUNK_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+Arguments:
+
+ ThunkContext - The thunk context whose properties to set.
+ 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.
+ BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by AsmThunk16GetProperties().
+
+Returns:
+
+ None
+
+--*/
+{
+ BufferSize &= ~3;
+
+ ThunkContext->RealModeBuffer = (UINT32)(UINTN)RealModeBuffer;
+ ThunkContext->DefaultStack = (UINT32)(ThunkContext->RealModeBuffer + BufferSize);
+ EfiCommonLibCopyMem (RealModeBuffer, (VOID*)(UINTN)_Code16Addr, mCode16Size);
+
+ return ThunkContext;
+}
+
+VOID
+EFIAPI
+AsmThunk16Destroy (
+ IN OUT THUNK_CONTEXT *ThunkContext
+ )
+/*++
+
+Routine Description:
+
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+Arguments:
+
+ ThunkContext - The thunk context to destroy.
+
+Returns:
+
+ None
+
+--*/
+{
+ ThunkContext->RealModeBuffer = 0;
+}
+
+IA32_REGISTER_SET *
+EFIAPI
+AsmThunk16FarCall86 (
+ IN THUNK_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+Arguments:
+
+ ThunkContext - Thunk context to use.
+ 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.
+ 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.
+
+Returns:
+
+ RegisterSet is returned.
+
+--*/
+{
+ return AsmThunk16 (ThunkContext, RegisterSet, Flags);
+}
+
+IA32_REGISTER_SET *
+EFIAPI
+AsmThunk16Int86 (
+ IN THUNK_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+Arguments:
+
+ ThunkContext - Thunk context to use.
+ IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ 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.
+ 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.
+
+Returns:
+
+ RegisterSet is returned.
+
+--*/
+{
+ RegisterSet->E.EIP = (UINT16)((UINT32 *)NULL)[IntNumber];
+ RegisterSet->E.CS = (UINT16)(((UINT32 *)NULL)[IntNumber] >> 16);
+
+ return AsmThunk16 (ThunkContext, RegisterSet, Flags | THUNK_INTERRUPT);
+}