summaryrefslogtreecommitdiff
path: root/EdkCompatibilityPkg/Foundation/Library/Thunk16/X86Thunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'EdkCompatibilityPkg/Foundation/Library/Thunk16/X86Thunk.c')
-rw-r--r--EdkCompatibilityPkg/Foundation/Library/Thunk16/X86Thunk.c320
1 files changed, 320 insertions, 0 deletions
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);
+}