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/x64 | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/Haswell/Library/ThunkLib/x64')
5 files changed, 589 insertions, 0 deletions
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); +} |