diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c')
-rw-r--r-- | ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c | 245 |
1 files changed, 245 insertions, 0 deletions
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); +} |