diff options
Diffstat (limited to 'ReferenceCode/Haswell/Library/ThunkLib')
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); +} |