summaryrefslogtreecommitdiff
path: root/Core/EM/CSM/thunk/x86
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/CSM/thunk/x86')
-rw-r--r--Core/EM/CSM/thunk/x86/thunk.c793
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.asm828
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.cif10
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.mak67
4 files changed, 1698 insertions, 0 deletions
diff --git a/Core/EM/CSM/thunk/x86/thunk.c b/Core/EM/CSM/thunk/x86/thunk.c
new file mode 100644
index 0000000..57233e4
--- /dev/null
+++ b/Core/EM/CSM/thunk/x86/thunk.c
@@ -0,0 +1,793 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/thunk.c 49 10/07/13 9:41a Olegi $
+//
+// $Revision: 49 $
+//
+// $Date: 10/07/13 9:41a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/thunk.c $
+//
+// 49 10/07/13 9:41a Olegi
+// Undone previous checkin related to EIP125856 as it is causing assert
+// during boot.
+//
+// 48 8/30/13 4:25a Srikantakumarp
+// [TAG] EIP125856
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Assert came in SetKbcPresenceInMiscInfo() when FarCall86()
+// function is called first time in POST.
+// [RootCause] BiosLessThan1MB value is used in
+// SetKbcPresenceInMiscInfo(); and this has been initialized only after
+// the function 0 csm16 call.
+// [Solution] Returned from SetKbcPresenceInMiscInfo() if
+// BiosLessThan1MB value is not initialized.
+// [Files] thunk.c
+//
+// 47 9/12/12 1:45a Srikantakumarp
+// [TAG] EIP99561
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] KbcEmulation enabled in Int86 call but NO_KBC_PRESENT_BIT
+// bit not set properly.
+// [RootCause] Incase of INT86 , it directly calls the interrupt service
+// routine and it might be that the NO_KBC_PRESENT_BIT is not set
+// according to the KbcEmulation enabled or disabled.
+// [Solution] The NO_KBC_PRESENT_BIT is set according to the
+// KbcEmulation enabled or disabled before the call to thunk in Int86
+// function in thunk.c.
+// [Files] thunk.c
+//
+// 46 3/02/12 3:24a Rameshr
+// [TAG] EIP81041
+// [Category] Improvement
+// [Description] Re-entrance support for Farcall86 and Int86 protocol
+// function
+// [Files] thunk.c
+//
+// 45 10/19/11 3:31p Olegi
+// [TAG] EIP72642, 72645, 72810
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Adaptec x805 SAS Option ROM code hangs
+// [RootCause] Adaptec ROM has a code that directly access KBC during
+// INT handler. We did not have KBC emulation enabled for Int86 function.
+// [Solution] Added enabling KBC emulation in Int86 function.
+// [Files] thunk.c
+//
+// 44 9/29/11 11:00a Olegi
+// [TAG] EIP70382
+// [Category] Improvement
+// [Description] Clear keyboard status in BDA after FarCall86 execution.
+// [Files] thunk.c
+//
+// 43 12/14/10 4:46p Olegi
+// [TAG] EIP50111
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] TPL asserts in some cases during LegacyBoot
+// [RootCause] TPL.C asserts during LocateHandleBuffer call executed
+// during LegacyBoot from FarCall86.
+// [Solution] removed a call GetPs2SimpleTextInProtocolInterface
+// execution during FarCall86. The existing handle of Ps2SimpleTextIn will
+// be used.
+// [Files] thunk.c
+//
+// 42 10/23/10 3:22p Olegi
+// Undone the changes related to moving TPL raising/lowering outside of
+// FarCall86. This made the IF to be active during thunk that caused
+// various problems.
+//
+// 41 8/17/10 2:26p Olegi
+// Reset PS/2 keyboard before legacy boot. EIP40711
+//
+// 40 7/25/10 2:43p Olegi
+// RaiseTPL/RestroreTPL are moved from FarCall86 to the ASM area.
+//
+// 39 7/19/10 4:44p Olegi
+//
+// 38 6/28/10 5:04p Olegi
+// EIP26277: Added a callback notification on
+// NonSmmEmul6064TrapProtocolGuid installation.
+//
+// 37 6/19/10 12:32p Olegi
+// Temporary undone the resolution for EIP26277 until the final resolution
+// is found. Current changes causes ASSERT due to LocateHandle is executed
+// on TPL_LEVEL_HIGH.
+//
+// 36 2/22/10 9:46a Olegi
+// Fixed the problem where some keys pressed on USB keyboard are lost
+// during the transition to OpROM. EIP26277
+//
+// 35 1/18/10 3:41a Rameshr
+// NumLock,Capslock,Scroll Lock LED's synced properly between EFI and
+// Legacy Mode.
+// EIP 27917
+//
+// 34 1/12/10 11:47a Olegi
+// Copyright message updated.
+//
+// 33 9/23/09 11:13a Olegi
+// Changed the global variable name according to the coding standard.
+//
+// 32 9/09/09 3:11p Davidd
+// Fixed hanging problem when USB is disabled by the newly added "USB
+// Support" setup question - EIP 25360
+//
+// 31 2/05/09 12:28p Olegi
+//
+// 30 2/04/09 5:30p Olegi
+// Several modifications in FarCall86:
+// - PIC SetMode is moved after raising TPL to highest level (cli)
+// - Set Pmode interrupt mask to FF before setting Rmode mask. That avoids
+// the problem where IVT is not yet set in real mode (before Func#0) and
+// some HW interrupt is pending.
+//
+// 29 11/13/08 10:00a Olegi
+// Reverse thunk implementation started.
+//
+// 28 11/07/08 4:04p Rameshraju
+// Removed unused code.
+//
+// 27 11/07/08 4:01p Rameshraju
+// BugFix- Sometime system hangs on S4 resume.
+// Fix Reason : If the Timer interrupt generates between CLI and Timer
+// Interrupt mask code, Next STI instruction try to services the Timer
+// interrupt.In this case before setting IVT system will hang
+// EIP:17401
+//
+// 26 6/12/08 8:14a Olegi
+// Modified FarCall86 to execute USB keyboard change mode code for CSM16
+// function #5 (EIP14051).
+//
+// 25 8/27/07 12:44p Olegi
+//
+// 23 6/28/07 4:14p Olegi
+//
+// 22 6/25/07 12:27p Olegi
+//
+// 21 6/18/07 5:54p Olegi
+//
+// 20 5/29/07 6:17p Olegi
+// Added UsbChangeEfiToLegacy call.
+//
+// 19 4/27/07 5:14p Olegi
+// CSM.CHM file preparation.
+//
+// 18 8/24/06 6:56p Felixp
+//
+// 17 8/24/06 6:55p Felixp
+// x64 support (warnings/errors fixed)
+//
+// 16 8/24/06 3:11p Felixp
+// Preliminary x64 support (work in progress)
+//
+// 15 7/28/06 4:45p Olegi
+//
+// 14 5/19/06 11:22p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 13 3/13/06 2:35p Felixp
+//
+// 12 10/13/05 6:19p Olegi
+// Added condition to a previous change.
+//
+// 11 10/11/05 4:20p Srinin
+// PS2 KBD reset function is called after CM16 function 2, 3 and 5 are
+// called.
+//
+// 10 8/25/05 10:28a Olegi
+// Previous changes undone - instead the vector base for the master 8259
+// is changed from 0x68 to 0x58; with this there is no need to preserve
+// and restore IVT.
+//
+// 8 3/04/05 1:47p Mandal
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Thunk.c
+//
+// Description: 32/64 bit to 16 bit code thunk implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Protocol\DevicePath.h>
+#include <Protocol\LegacyBios.h>
+#include <Protocol\Legacy8259.h>
+#include <Protocol\SimpleTextin.h>
+#include <protocol\FirmwareVolume.h >
+#include <Ffs.h>
+#include "csm.h"
+#include <AmiDxeLib.h>
+#include "token.h"
+#if defined(AMIUSB_SUPPORT)
+#include <protocol\amiusbcontroller.h>
+#endif
+#include <Protocol\SimpleTextInEx.h>
+#include <Protocol\AmiKeycode.h>
+
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Offset;
+ UINT16 Segment;
+} FAR_CALL_PTR_16;
+
+typedef struct {
+ UINT32 Stack;
+ UINT32 StackSize;
+} STACK;
+
+typedef struct {
+ FAR_CALL_PTR_16 FarCall;
+ EFI_IA32_REGISTER_SET Regs;
+ STACK Stack;
+ BOOLEAN isFarCall; //if false, then INT86.
+ UINT8 BiosInt;
+} THUNK_DATA;
+
+typedef struct _ACPI_PNPID {
+ UINT32 Signature :16;
+ UINT32 PnpID :16;
+} ACPI_PNPID;
+#pragma pack()
+
+
+#if defined(AMIUSB_SUPPORT)
+EFI_USB_PROTOCOL *gUsbProtocol = NULL;
+#endif
+AMI_EFIKEYCODE_PROTOCOL *pKeyCodeProtocol=NULL;
+
+EFI_SIMPLE_TEXT_INPUT_PROTOCOL *gPS2KBDInterface = NULL;
+EFI_GUID gCsmThunkGuid = {
+ 0xA08276EC,0xA0FE,0x4e06,0x86,0x70,0x38,0x53,0x36,0xC7,0xD0,0x93
+};
+
+EFI_LEGACY_8259_PROTOCOL *gLegacy8259;
+extern BIOS_INFO *CoreBiosInfo;
+
+UINTN gThunkAsmAddr;
+extern BOOLEAN gIsBootPrepared;
+BOOLEAN gInsideThunk = FALSE;
+
+EFI_STATUS GetPs2SimpleTextInProtocolInterface(
+ BIOS_INFO *This,
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL **PS2KBDInterface
+);
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SetKbcPresenceInMiscInfo
+//
+// Description: Updates CSM16_NO_KBC_PRESENT_BIT of MiscInfoAddress accordingly
+// by checking if the KbcEmulation is Enabled or Disabled.
+//
+// Input:
+//
+// Output:
+// EFI_STATUS
+//
+// Referrals:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SetKbcPresenceInMiscInfo()
+{
+ EFI_TO_COMPATIBILITY16_INIT_TABLE *Csm16InitTable;
+ LEGACY16_TO_EFI_DATA_TABLE_STRUC *Csm16Data;
+ UINT8 KbcSupport,KbcCheck=0;
+ EFI_STATUS Status;
+
+ //
+ // Retrieving the Data at MiscInfoAddress
+ //
+ Csm16InitTable = &CoreBiosInfo->Thunk->Csm16InitTable;
+ Csm16Data = (LEGACY16_TO_EFI_DATA_TABLE_STRUC*)(UINTN)Csm16InitTable->BiosLessThan1MB;
+
+ KbcCheck = *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress;
+
+ //
+ // Setting/Resetting the CSM16_NO_KBC_PRESENT_BIT according to the KbcEmulation
+ //
+ KbcSupport = IoRead8(0x64);
+ if (KbcSupport != 0xff) {
+ KbcCheck &= ~(CSM16_NO_KBC_PRESENT_BIT);
+ }
+ else {
+ KbcCheck |= (CSM16_NO_KBC_PRESENT_BIT);
+ }
+ //
+ // Checking if the Data at MiscInfoAddress is already updated
+ //
+ if((*(UINT8*)(UINTN)Csm16Data->MiscInfoAddress) != KbcCheck){
+ //
+ // Checking if F0000 region is writable
+ //
+ *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress = KbcCheck;
+
+ if((*(UINT8*)(UINTN)Csm16Data->MiscInfoAddress) == KbcCheck){
+ return;
+ }
+ else{
+ //
+ // Unlocking the region 0xE0000 - 0xFFFFF
+ //
+ Status = CoreBiosInfo->iRegion->UnLock (CoreBiosInfo->iRegion,
+ 0xE0000,
+ 0x20000,
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Updating the Data at MiscInfoAddress
+ //
+ *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress = KbcCheck;
+
+ //
+ // Locking the region 0xE0000 - 0xFFFFF
+ //
+ CoreBiosInfo->iRegion->Lock (CoreBiosInfo->iRegion,
+ 0xE0000,
+ 0x20000,
+ NULL);
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: Int86
+//
+// Description: Executes BIOS interrupt routine
+//
+// Input:
+// LegacyBios protocol instance pointer
+// BiosInt Interrupt number
+// Regs CPU register values to pass to the interrupt handler
+//
+// Output:
+// TRUE Interrupt was not executed
+// FALSE INT completed. Caller will see Regs for status
+//
+// Referrals: EFI_IA32_REGISTER_SET
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN Int86(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT8 BiosInt,
+ IN OUT EFI_IA32_REGISTER_SET *Regs
+)
+{
+ EFI_TPL OldTpl;
+
+ THUNK_DATA *ThunkData = (THUNK_DATA*)(gThunkAsmAddr+6);
+ //
+ // To avoid reentrance in Int86
+ //
+ if(gInsideThunk){
+ return FALSE;
+ }
+ gInsideThunk = TRUE;
+ ThunkData->isFarCall = FALSE;
+ ThunkData->BiosInt = BiosInt;
+ ThunkData->Stack.StackSize = 0; //This is required
+
+
+ //Copy thunk registers.
+ ThunkData->Regs = *Regs;
+
+#if defined(AMIUSB_SUPPORT)
+{
+ EFI_STATUS Status;
+
+ if (gUsbProtocol == NULL) {
+ Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &gUsbProtocol);
+ if (EFI_ERROR(Status)) {
+ gUsbProtocol=NULL; // To be used later, after returning from INT
+ }
+ }
+ if (gUsbProtocol != NULL) {
+ gUsbProtocol->UsbChangeEfiToLegacy(1);
+ }
+}
+#endif
+
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ gLegacy8259->SetMode(gLegacy8259,Efi8259LegacyMode,NULL,NULL);
+
+ SetKbcPresenceInMiscInfo();
+
+ ((void(*)(UINTN))gThunkAsmAddr)(gThunkAsmAddr);
+
+#if defined(AMIUSB_SUPPORT)
+ if (gUsbProtocol) {
+ gUsbProtocol->UsbChangeEfiToLegacy(0);
+ }
+#endif
+
+ gLegacy8259->SetMode(gLegacy8259,Efi8259ProtectedMode,NULL,NULL);
+ pBS->RestoreTPL(OldTpl);
+
+ //Restore thunk registers.
+ *Regs = ThunkData->Regs;
+ gInsideThunk = FALSE;
+
+ return FALSE; // INT completed. Caller will see Regs for status.
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: FarCall86
+//
+// Description: Executes 16 bit code starting from a given address
+//
+// Input:
+// This LegacyBiosProtocol instance pointer
+// Segment, Offset Starting address of the 16 bit routine
+// Regs CPU register values to pass to the routine
+// Stack Stack pointer with the possible data to be passed to the routine
+// StackSize Size of the stack passed to the routine
+//
+// Output:
+// TRUE Call was not executed
+// FALSE Call completed. Caller will see Regs for status
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN FarCall86(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN EFI_IA32_REGISTER_SET *Regs,
+ IN VOID *Stack,
+ IN UINTN StackSize
+)
+{
+ EFI_TPL OldTpl;
+ UINT16 IrqMask, SaveIrqMask;
+ UINT16 ProtectedIrqMask, ProtectedSaveIrqMask;
+ THUNK_DATA *ThunkData = (THUNK_DATA*)(gThunkAsmAddr+6);
+ UINT16 FuncNumber;
+ BOOLEAN IsCsm16Call =
+ Segment == CoreBiosInfo->Csm16EntrySeg &&
+ CoreBiosInfo->Csm16EntryOfs == Offset;
+ BOOLEAN IsCsm16DispatchOpRom = IsCsm16Call &&
+ Regs->X.AX == Compatibility16DispatchOprom;
+
+ BOOLEAN IsCsm16LegacyBoot = IsCsm16Call &&
+ Regs->X.AX == Compatibility16Boot;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_KEY_TOGGLE_STATE KeyToggleState=0;
+ //
+ // To avoid reentrance in FarCall86
+ //
+ if(gInsideThunk){
+ return FALSE;
+ }
+
+ gInsideThunk = TRUE;
+
+ //
+ // Change USB operation mode indicator from EFI to Legacy
+ //
+#if defined(AMIUSB_SUPPORT)
+ if (IsCsm16LegacyBoot == FALSE) {
+ if (gUsbProtocol == NULL) {
+ Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &gUsbProtocol);
+ if (EFI_ERROR(Status)) {
+ gUsbProtocol=NULL; // To be used later, after FarCall execution
+ }
+ }
+ }
+ if (gUsbProtocol != NULL) {
+ gUsbProtocol->UsbChangeEfiToLegacy(1);
+ }
+#endif
+
+ ThunkData->isFarCall = TRUE;
+
+ //Copy address for thunk.
+ ThunkData->FarCall.Segment = Segment;
+ ThunkData->FarCall.Offset = Offset;
+
+ //Copy address for stack
+ if (Stack)
+ {
+ ThunkData->Stack.Stack = (UINT32)Stack;
+ ThunkData->Stack.StackSize = (UINT32)StackSize;
+ } else ThunkData->Stack.StackSize = 0;
+
+ //Copy thunk registers.
+ ThunkData->Regs = *Regs;
+
+ // Reset the PS/2 keyboard before legacy boot
+ if (IsCsm16LegacyBoot == TRUE) {
+ if (gPS2KBDInterface) gPS2KBDInterface->Reset(gPS2KBDInterface, FALSE);
+ }
+
+ FuncNumber = Regs->X.AX;
+
+ if (IsCsm16Call) {
+ if (FuncNumber != 05 && FuncNumber != 02 && FuncNumber != 03) {
+ gLegacy8259->GetMask(gLegacy8259, &SaveIrqMask, NULL, NULL, NULL); // Save current Mask
+
+ IrqMask = -1;
+ gLegacy8259->SetMask(gLegacy8259, &IrqMask, NULL, NULL, NULL); // Set new Mask
+ }
+ }
+
+ //
+ // Mask all HW interrupts for real mode for CSM16 function #0 (InitializeYourself).
+ // This is needed since IVT is not installed before executing function #0.
+ //
+ // TODO: Explore the possibility of IVT installation from CSM32; in this case the
+ // code that is updating and using ProtectedIrqMask can be removed.
+ //
+ if (IsCsm16Call && FuncNumber == 00 ) {
+ gLegacy8259->GetMask(gLegacy8259, NULL, NULL, &ProtectedSaveIrqMask, NULL); // Save current Mask
+ ProtectedIrqMask = -1;
+ gLegacy8259->SetMask(gLegacy8259, NULL , NULL, &ProtectedIrqMask, NULL); // Set new Mask
+ }
+
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ //
+ // The following call will change the PIC settings to real mode; this includes
+ // unmasking all real mode interrupts. Note, that at this point HW interrupts
+ // must be disabled. This is done by the previous RaiseTPL call.
+ //
+ gLegacy8259->SetMode(gLegacy8259,Efi8259LegacyMode,NULL,NULL);
+
+ ((void(*)(UINTN))gThunkAsmAddr)(gThunkAsmAddr);
+
+#if defined(AMIUSB_SUPPORT)
+ if (gUsbProtocol) {
+ gUsbProtocol->UsbChangeEfiToLegacy(0);
+ }
+#endif
+
+ if (IsCsm16Call && FuncNumber == 00 ) {
+ gLegacy8259->SetMask(gLegacy8259, NULL , NULL, &ProtectedSaveIrqMask, NULL); // Set new Mask
+ }
+
+ gLegacy8259->SetMode(gLegacy8259,Efi8259ProtectedMode,NULL,NULL);
+
+ //Restore thunk registers.
+ *Regs = ThunkData->Regs;
+ pBS->RestoreTPL(OldTpl);
+
+ //
+ // Change USB operation mode indicator back to EFI
+ //
+
+ if (!IsCsm16Call ||
+ (IsCsm16Call &&
+ (FuncNumber == 05 || FuncNumber == 02 || FuncNumber == 03))) {
+// Reset PS2 Mouse
+ if (!gPS2KBDInterface) {
+ GetPs2SimpleTextInProtocolInterface((BIOS_INFO *)This, &gPS2KBDInterface);
+ }
+
+ if (gPS2KBDInterface) gPS2KBDInterface->Reset(gPS2KBDInterface, FALSE);
+
+ }
+ else gLegacy8259->SetMask(gLegacy8259, &SaveIrqMask, NULL, NULL, NULL); // Restore mask
+
+ if(IsCsm16DispatchOpRom) {
+ if((pKeyCodeProtocol == NULL && IsCsm16LegacyBoot == FALSE)) {
+ pBS->HandleProtocol(pST->ConsoleInHandle, &gAmiEfiKeycodeProtocolGuid, (void*)&pKeyCodeProtocol);
+ }
+ if(pKeyCodeProtocol != NULL) {
+ UINT8 KeyState;
+ KeyState = *(UINT8*)(UINTN)0x417;
+ if(KeyState & 0x10) {
+ KeyToggleState |= SCROLL_LOCK_ACTIVE;
+ }
+ if(KeyState & 0x20) {
+ KeyToggleState |= NUM_LOCK_ACTIVE;
+ }
+ if(KeyState & 0x40) {
+ KeyToggleState |= CAPS_LOCK_ACTIVE;
+ }
+ KeyToggleState |= TOGGLE_STATE_VALID;
+ pKeyCodeProtocol->SetState((EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL*)pKeyCodeProtocol,&KeyToggleState);
+ }
+ }
+
+ *(UINT8*)(UINTN)0x417 &= 0x70; // Clear key modifiers status in BDA
+
+ gInsideThunk = FALSE;
+
+ return FALSE; // CALL completed. Caller will see Regs for status.
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: LoadRealModeFile
+//
+// Description: Code that loads 16-bit thunk code at a particular address
+//
+// Input:
+// 16-bit binary file GUID
+// Address to load the binary to
+//
+// Output:
+// Status of the load operation
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS LoadRealModeFile(EFI_GUID *Guid, VOID *Address)
+{
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ UINT32 Authentication;
+ VOID *BufferAddr=0;
+ UINTN BufferSize=0;
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN i;
+
+ Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiFirmwareVolumeProtocolGuid,NULL,&NumHandles,&HandleBuffer);
+ if (EFI_ERROR(Status)) return Status;
+
+ for (i = 0; i< NumHandles; ++i)
+ {
+ Status = pBS->HandleProtocol(HandleBuffer[i],&guidFV,&Fv);
+ if (EFI_ERROR(Status)) continue;
+
+ Status = Fv->ReadSection(Fv,
+ Guid,
+ EFI_SECTION_RAW,
+ 0,
+ &BufferAddr,
+ &BufferSize,
+ &Authentication);
+
+ if (Status == EFI_SUCCESS)
+ {
+ MemCpy(
+ Address,
+ (UINT8*)BufferAddr,
+ BufferSize
+ );
+ pBS->FreePool(BufferAddr);
+ break;
+ }
+ }
+
+ pBS->FreePool(HandleBuffer);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitializeThunk
+//
+// Description: 16-bit thunk initialization routine. It calls 16 bit code to
+// do the address fixups within 16-bit code.
+//
+// Input: The instance of BIOS_INFO pointer
+//
+// Output: Status of the initialization completion
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InitializeThunk(
+ BIOS_INFO* CoreBiosInfo
+)
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Thunkaddr = (EFI_PHYSICAL_ADDRESS)CoreBiosInfo->Thunk;
+ UINT16 ThunkFixupsOffset;
+
+ //Locate Legacy8259 Protocol
+ gLegacy8259 = CoreBiosInfo->i8259;
+
+ //Copy ThunkAsm to memory.
+ Status = LoadRealModeFile(&gCsmThunkGuid, (VOID*)Thunkaddr);
+ if (EFI_ERROR(Status)) return Status;
+
+ gThunkAsmAddr = (UINT32)Thunkaddr;
+
+ //Call fixups
+ ThunkFixupsOffset = *(UINT16*)(gThunkAsmAddr+2);
+ ((void(*)(UINTN))(gThunkAsmAddr+ThunkFixupsOffset))(gThunkAsmAddr);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetPs2SimpleTextInProtocolInterface
+//
+// Description: This function returns the SimpleTextIn protocol interface
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GetPs2SimpleTextInProtocolInterface(
+ BIOS_INFO *This,
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL **PS2KBDInterface
+)
+{
+ EFI_STATUS Status;
+ UINTN i,cnt;
+ ACPI_HID_DEVICE_PATH *siodp;
+ ACPI_PNPID *pnpid;
+ EFI_HANDLE *hbuff = NULL;
+ EFI_DEVICE_PATH_PROTOCOL *dp;
+ BOOLEAN bIsConnected = FALSE;
+
+ Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiSimpleTextInProtocolGuid, NULL, &cnt, &hbuff);
+
+ if (EFI_ERROR(Status)) return Status;
+
+ for(i=0; i<cnt; i++){
+ Status=pBS->HandleProtocol(hbuff[i],&gEfiDevicePathProtocolGuid,&dp);
+ if(EFI_ERROR(Status)) continue;
+
+ siodp=DPGetLastNode(dp);
+ if(siodp->Header.Type!=ACPI_DEVICE_PATH
+ || siodp->Header.SubType!=ACPI_DP
+ || NODE_LENGTH(&siodp->Header) != ACPI_DEVICE_PATH_LENGTH) continue;
+
+ pnpid=(ACPI_PNPID*)&siodp->HID;
+ if (pnpid->PnpID == 0x0303) {
+// Status = pBS->OpenProtocol (hbuff[i], &gEfiSimpleTextInProtocolGuid, &PS2KBDInterface, This->hBios, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ Status = pBS->HandleProtocol(hbuff[i],&gEfiSimpleTextInProtocolGuid, PS2KBDInterface);
+ break;
+ }
+ Status = EFI_NOT_FOUND;
+ }
+ pBS->FreePool(hbuff);
+ return Status;
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/x86/x86thunk.asm b/Core/EM/CSM/thunk/x86/x86thunk.asm
new file mode 100644
index 0000000..9a5a781
--- /dev/null
+++ b/Core/EM/CSM/thunk/x86/x86thunk.asm
@@ -0,0 +1,828 @@
+;**********************************************************************
+;**********************************************************************
+;** **
+;** (C)Copyright 1985-2012, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;**********************************************************************
+;**********************************************************************
+
+;**********************************************************************
+; $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/x86thunk.asm 37 10/07/13 9:01a Olegi $
+;
+; $Revision: 37 $
+;
+; $Date: 10/07/13 9:01a $
+;**********************************************************************
+; Revision History
+; ----------------
+; $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/x86thunk.asm $
+;
+; 37 10/07/13 9:01a Olegi
+; EIP135289
+; Legacy2Efi changes - CR4 save/restore
+;
+; 36 12/14/12 6:19p Olegi
+; [TAG] EIP109554
+; [Category] Improvement
+; [Description] Aptio4: Update CSM thunk to use private GDT instead of
+; GDT on entry point
+; [Files] x86thunk.asm
+;
+; 35 7/23/12 12:59p Olegi
+; [TAG] EIP95386
+; [Category] Improvement
+; [Description] CR3 register save/restore
+;
+; 34 6/13/12 12:49p Olegi
+; [TAG] EIP92524
+; [Category] Improvement
+; [Description] IDT location is limited to 4GB in CSM thunk
+;
+; 33 12/05/11 5:53p Olegi
+; [TAG] EIP77045
+; [Category] Improvement
+; [Description] Changed the values to be loaded to the segment
+; registers from static number (8) to a dynamic number that represents a
+; valid descriptor.
+; [Files] x86thunk.asm
+;
+; 32 12/01/10 9:37a Olegi
+; FarCall86 is modified to return data in stack when expected.
+;
+; 31 11/15/10 6:21p Olegi
+; [TAG] EIP48242
+; [Category] Bug Fix
+; [Severity] Critical
+; [Symptom] thunk problems for IA32 projects
+; [RootCause] wrong paths in thunk code for IA32 projects
+; [Solution] fixed the thunk code
+; [Files] x86thunk.asm
+;
+; 30 9/15/10 1:40p Olegi
+; Reverse thunk stack usage modified: stack for the PM operations will be
+; allocated externally.
+;
+; 29 9/13/10 5:26p Vyacheslava
+; Added variable PmStackPtr to use a new stack space.
+;
+; 28 9/08/10 6:16p Vyacheslava
+; Bugfix in reverse thunk: there was wrong assumption about stack
+; re-assignment. When caller (OptionROM) reassignes stack, reverse thunk
+; was failing.
+;
+; 27 7/26/10 2:23p Vyacheslava
+;
+; 26 7/25/10 2:44p Olegi
+;
+; 25 7/25/10 1:07p Olegi
+; Bugfixes in the reverse thunk implementation.
+;
+; 24 7/24/10 12:38p Olegi
+;
+; 23 7/23/10 4:09p Olegi
+; Initial reverse thunk implementation.
+;
+; 22 7/19/10 4:44p Olegi
+;
+; 21 1/12/10 11:47a Olegi
+; Copyright message updated.
+;
+; 20 11/12/08 5:02p Olegi
+;
+; 19 5/11/07 11:12a Markw
+; Save ss and set it to a flat descriptor in 64-bit mode.
+;
+; 18 4/27/07 5:14p Olegi
+; CSM.CHM file preparation.
+;
+; 17 9/15/06 12:02p Markw
+; Disable PAE when thunking because windows expects PAE in CR4 to be
+; disabled after calling INT19h to boot.
+;
+; 16 8/24/06 3:11p Felixp
+; Preliminary x64 support (work in progress)
+;
+; 15 5/25/06 2:23p Olegi
+;
+; 14 3/03/06 11:09a Markw
+; Removed some duplicate code.
+;
+; 13 10/14/05 10:16a Markw
+; Removed previous changes.
+;
+; 11 8/02/05 4:24p Markw
+; Removed some db66 from sgdt and sidt. It was instructing the CPU to do
+; a 24-bit load. However, the CPU was loading 32-bit that was needed, so
+; it worked even though the spec described the operation differently.
+;
+; 10 5/12/05 12:57p Markw
+; Fixed lidt in portected mode. It was only loading 24 of 32 bits.
+;
+; 9 4/18/05 10:54a Markw
+; Remove pushing/popping ebx (entry point).
+; make segments equal segement instead of fixup.
+;
+; 8 3/04/05 1:48p Mandal
+;
+;**********************************************************************
+;<AMI_FHDR_START>
+;
+; Name: x86Thunk.asm
+;
+; Description: x86 CPU thunk functions
+;
+;<AMI_FHDR_END>
+;**********************************************************************
+
+.586P
+.model small
+
+;STACK_SIZE equ 8192
+STACK_TOP equ (4096 * 3)
+
+FAR_CALL_PTR_16 struct
+ ptr_offset dw ?
+ seg_offset dw ?
+FAR_CALL_PTR_16 ends
+
+REGISTERS struct
+ reg_eax dd ?
+ reg_ebx dd ?
+ reg_ecx dd ?
+ reg_edx dd ?
+ reg_esi dd ?
+ reg_edi dd ?
+ reg_eflags dd ?
+ reg_es dw ?
+ reg_cs dw ?
+ reg_ss dw ?
+ reg_ds dw ?
+ reg_fs dw ?
+ reg_gs dw ?
+ reg_ebp dd ?
+REGISTERS ends
+
+STACK_PARAM struct
+ StackPtr dd ?
+ StackSize dd ?
+STACK_PARAM ends
+
+THUNK_DATA struct
+ FarCallPtr16 FAR_CALL_PTR_16 <>
+ Regs REGISTERS <>
+ StackParm STACK_PARAM<>
+ isFarCall db 0
+ BiosInt db 0
+THUNK_DATA ends
+
+
+ASSUME ds:THUNK_SEG
+
+THUNK_SEG SEGMENT USE32 'CODE'
+
+THUNK proc
+ jmp over_data
+; The following data must be here. Don't move. These are used by the Thunk C driver.
+ dw LOWWORD offset Fixups
+ dw LOWWORD offset ReverseThunk
+ ThunkData THUNK_DATA <>
+over_data:
+ cli
+;--------------------------------------------------------------------------------
+; The following code switches from protected mode (from x64 if EFIx64 is defined,
+; otherwise from 32-bit protected mode) to 16-bit real mode.
+;--------------------------------------------------------------------------------
+; Calculate entry point and load EBX/RBX with it.
+
+ push ebx
+
+ call @f
+@@:
+ pop ebx
+ sub ebx, @b ; RBX/EBX - physical address of CSM16 entry point
+
+ mov DWORD PTR [RtReturnResult+ebx], eax
+
+ sidt fword ptr [IdtSave+ebx] ;Save IDT
+ sgdt fword ptr [GdtSave+ebx] ;Save GDT
+ lgdt fword ptr [GdtDescriptor+ebx]
+
+ mov eax, cr3 ;;Save CR3, CR4
+ mov [CR3Save+ebx], eax
+ mov eax, cr4
+ mov [CR4Save+ebx], eax
+
+ ;Save segement registers.
+ mov ax, ds
+ push eax ;64-bit doesn't support push ds, es, ss
+ mov ax, es
+ push eax
+ mov ax, ss
+ push eax
+ push fs
+ push gs
+ mov ax, cs ;This must be last for cs restore.
+ push eax
+
+ mov eax, DATA_SEL ;make sure segments are approriate for 32-bit mode.
+ mov ds, ax ; Load SS with the known descriptor value
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+
+ifdef EFIx64
+;---Jump from long mode to compatiblity mode---
+ ;jmp far ptr [ComModeAdr]
+ db 0ffh,2dh
+ dd ComModeAdr - $ - 4
+
+ComMode:
+;---Go to protected mode---
+ mov eax, cr0
+ btr eax, 31
+ mov cr0, eax ;Now in protected mode.
+ jmp $+2
+
+ mov ecx, 0c0000080h
+ rdmsr
+ btr eax, 8
+ wrmsr
+
+ mov eax, cr4
+ btr eax, 5
+ mov cr4, eax ;Turn off PAE bit. Windows expects when calling INT19h.
+endif
+
+ cmp BYTE PTR [IsReverseThunk+ebx], 1
+ je no_stack_to_copy
+
+ pushad
+ pushfd
+
+;--Save Data--
+ mov [StackSave+ebx], esp ;Save 32 bit stack address of this module.
+
+ ;---Copy Stack parameters of LegacyBiosFarCall---
+ mov ecx, [ThunkData.StackParm.StackSize+ebx]
+ or ecx, ecx
+ jz no_stack_to_copy
+
+ mov esi, [ThunkData.StackParm.StackPtr+ebx]
+ mov edi, ebx
+ add edi, STACK_TOP
+ sub edi, ecx
+ rep movsb
+no_stack_to_copy:
+;--Switch to real mode--
+ lidt fword ptr [LegacyLdtDescriptor+ebx]
+
+ mov ax, DATA_SEL_16
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+ ;jmp CODE_SEL_16:next
+ db 0eah
+ dd offset next
+ dw CODE_SEL_16
+next:
+ mov eax, cr0
+ and al, 0feh
+ mov cr0, eax
+
+ ;--ITP doesn't display disassebly correctly until jump to real mode.
+
+ ;jmp CS_SEGMENT:RealModeAddr
+ db 0eah
+ dw LOWWORD offset RealMode
+RealModeFixUp:
+ dw 0
+RealMode:
+ db 8ch, 0c8h ;mov ax, cs
+ db 8eh, 0d8h ;mov ds, ax
+ db 8eh, 0c0h ;mov es, ax
+ db 8eh, 0d0h ;mov ss, ax
+ db 8eh, 0e0h ;mov fs, ax
+ db 8eh, 0e8h ;mov gs, ax
+
+; sti
+;---------------Real mode operations-----------
+ db 2eh, 80h, 3eh
+ dw LOWWORD offset IsReverseThunk
+ db 1 ;cmp cs:IsReverseThunk, 1
+
+ jnz @f
+
+ db 2eh, 0c6h, 6
+ dw LOWWORD offset IsReverseThunk
+ db 0 ;mov cs:IsReverseThunk, 0
+
+ ; Restore the registers from RtRegs
+ push cs
+ pop ss
+
+ db 0bch ; mov sp, LOWWORD OFFSET RtRegs
+ dw LOWWORD OFFSET RtRegs
+
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ db 66h, 61h ; popad
+
+ ; Restore stack pointer and its contents
+
+ db 2eh, 8eh, 16h ;mov cs:RtStackSave+4, ss
+ dw LOWWORD offset RtStackSave+4
+
+ db 66h, 2eh, 8bh, 26h ;mov sp, cs:RtStackSave
+ dw LOWWORD offset RtStackSave
+
+ ; Restore flags
+ db 66h, 2eh, 0ffh, 36h ; push DWORD PTR cs:RtSavedFlags
+ dw LOWWORD OFFSET RtSavedFlags
+ db 66h, 9dh ; popfd
+
+ db 83h, 0c4h, 4 ; add sp, 4: prepare stack for a push
+
+ db 66h, 2eh, 0ffh, 36h ; push dword ptr cs:RtRetAddressSave
+ dw LOWWORD offset RtRetAddressSave
+
+ db 66h, 2eh, 0a1h ;mov eax, RtReturnResult
+ dw LOWWORD offset RtReturnResult
+
+ db 0cbh ;retf ; reverse thunk call returns control
+
+@@:
+ db 66h
+ mov esp, STACK_TOP ;This is the top stack for real mode.
+
+ db 2bh, 26h ;sub sp, word ptr ThunkData.StackParm.StackSize
+ dw LOWWORD offset ThunkData.StackParm.StackSize
+
+ ;---copy registers for FarCall and BIOS INT---
+
+ db 66h, 8bh, 1eh ;mov ebx, ThunkData.regs.reg_ebx
+ dw LOWWORD offset ThunkData.regs.reg_ebx
+ db 66h, 8bh, 0eh ;mov ecx, ThunkData.regs.reg_ecx
+ dw LOWWORD offset ThunkData.regs.reg_ecx
+ db 66h, 8bh, 16h ;mov edx, ThunkData.regs.reg_edx
+ dw LOWWORD offset ThunkData.regs.reg_edx
+ db 66h, 8bh, 36h ;mov esi, ThunkData.regs.reg_esi
+ dw LOWWORD offset ThunkData.regs.reg_esi
+ db 66h, 8bh, 3eh ;mov edi, ThunkData.regs.reg_edi
+ dw LOWWORD offset ThunkData.regs.reg_edi
+ db 66h, 8bh, 2eh ;mov ebp, ThunkData.regs.reg_ebp
+ dw LOWWORD offset ThunkData.regs.reg_ebp
+
+ db 0a1h ;mov ax, ThunkData.regs.reg_es
+ dw LOWWORD offset ThunkData.regs.reg_es
+
+ db 08eh, 0c0h ;mov es, ax
+
+ db 66h, 0a1h ;mov eax, ThunkData.regs.reg_eax
+ dw LOWWORD offset ThunkData.regs.reg_eax
+
+ ;Change ds last, since above operations depend on ds.
+ db 0ffh, 36h ;push ThunkData.regs.reg_ds
+ dw LOWWORD offset ThunkData.regs.reg_ds
+ pop ds
+
+ ;Don't load the flags! They aren't needed, and if they aren't
+ ;initialized properly, the system hangs.
+
+ ;--Call real mode function or interrupt--
+ sti
+
+ db 2eh, 80h, 3eh ;cmp cs:ThunkData.isFarCall, 0
+ dw LOWWORD offset ThunkData.isFarCall
+ db 0
+
+ jnz FarCall
+
+ db 66h
+ pushad
+
+ db 2eh, 0a0h ;mov al, cs:ThunkData.BiosInt
+ dw LOWWORD offset ThunkData.BiosInt
+
+ db 2eh, 0a2h ;mov cs:intxx, al ;Sets the intermediate value for intxx below.
+ dw LOWWORD offset intxx
+
+ db 66h
+ mov eax, 1
+ cpuid ;serializing instruction because of runtime code modification.
+
+ db 66h
+ popad
+
+ db 0cdh ;Execute int x
+intxx label byte
+ db 0
+
+ jmp @f
+FarCall:
+ ;call dword ptr cs:[ThunkData.FarCallPtr16]
+ db 02eh, 0ffh, 1eh ;Execute far call
+ dw LOWWORD offset ThunkData.FarCallPtr16
+@@:
+
+ cli
+ ;--Copy registers back for FarCall and BIOS INT---
+
+ db 66h, 2eh, 0a3h ;mov cs:ThunkData.regs.reg_eax, eax
+ dw LOWWORD offset ThunkData.regs.reg_eax
+
+ push ds
+
+ db 2eh, 08fh, 6 ;pop cs:ThunkData.regs.reg_ds
+ dw LOWWORD offset ThunkData.regs.reg_ds
+
+ db 8ch, 0c8h ;mov ax, cs
+ db 8eh, 0d8h ;mov ds, ax
+
+ db 66h, 89h, 1eh ;mov ThunkData.regs.reg_ebx, ebx
+ dw LOWWORD offset ThunkData.regs.reg_ebx
+
+ db 66h, 89h, 0eh ;mov ThunkData.regs.reg_ecx, ecx
+ dw LOWWORD offset ThunkData.regs.reg_ecx
+
+ db 66h, 89h, 16h ;mov ThunkData.regs.reg_edx, edx
+ dw LOWWORD offset ThunkData.regs.reg_edx
+
+ db 66h, 89h, 36h ;mov ThunkData.regs.reg_esi, esi
+ dw LOWWORD offset ThunkData.regs.reg_esi
+
+ db 66h, 89h, 3eh ;mov ThunkData.regs.reg_edi, edi
+ dw LOWWORD offset ThunkData.regs.reg_edi
+
+ db 66h, 89h, 2eh ;mov ThunkData.regs.reg_ebp, ebp
+ dw LOWWORD offset ThunkData.regs.reg_ebp
+
+ db 08ch ,0c0h ;mov ax, es
+
+ db 0a3h ;mov ThunkData.regs.reg_es, ax
+ dw LOWWORD offset ThunkData.regs.reg_es
+
+ db 09ch ;pushf
+ db 08fh, 6 ;pop ThunkData.regs.reg_eflags
+ dw LOWWORD offset ThunkData.regs.reg_eflags
+
+;--------------End Real Mode operations---------
+RealToPm:
+ db 66h
+ xor ebx, ebx
+ db 8ch, 0cbh ;mov bx, cs
+ db 66h
+ shl ebx, 4 ;ebx = entry point
+
+ ;--Switch to protected mode--
+; cli
+
+ ;Reload GDT in case it was changed.
+ ;lgdt fword ptr cs:[GdtDescriptor]
+ db 66h,02eh,0fh,1,16h
+ dw LOWWORD offset GdtDescriptor
+
+ mov eax, cr0
+ or al, 1 ;Set PE bit
+ mov cr0, eax ;Turn on Protected Mode
+
+ ;jmp CODE_SEL:P32MODE
+ db 66h, 0eah
+P32ModeFixUp:
+ dd offset P32Mode
+ dw CODE_SEL
+
+P32Mode::
+ mov ax, DATA_SEL
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+ cmp BYTE PTR [IsReverseThunk + ebx], 1
+ je CreateReverseThunkESP
+ mov esp, [StackSave + ebx] ;Get original stack back.
+ ;---Copy Stack parameters of LegacyBiosFarCall---;
+ mov ecx, [ThunkData.StackParm.StackSize+ebx]
+ or ecx, ecx
+ jz @F
+ mov edi, [ThunkData.StackParm.StackPtr+ebx]
+ mov esi, ebx
+ add esi, STACK_TOP
+ sub esi, ecx
+ rep movsb
+@@:
+ popfd
+ popad
+ jmp DonePreparingESP
+
+CreateReverseThunkESP: ; EBX = ThunkStart code segment << 4
+ mov [ThunkStart + ebx], ebx
+ mov esp, [PmStackPtr + ebx]
+
+ifdef EFIx64
+ sub esp, 20h ; allocate 20h bytes in stack (x64 calling convention)
+endif
+ mov [esp], ebx
+ifdef EFIx64
+ mov DWORD PTR [esp+4], 0
+endif
+ sub esp, 4
+ mov [esp], esi ; Function pointer (DWORD)
+ifdef EFIx64
+ mov DWORD PTR [esp], 0
+ sub esp, 4
+ mov [esp], esi ; Function pointer (QWORD)
+endif
+
+DonePreparingESP:
+ xor eax, eax ; short/quick way to set EAX = 0
+ lldt ax ; (source operand == 0) => LDTR is invalid
+
+ifdef EFIx64
+ mov eax, cr4
+ bts eax, 5
+ mov cr4, eax ;Enable PAE
+
+ mov ecx, 0c0000080h
+ rdmsr
+ bts eax, 8
+ wrmsr
+
+ mov eax, cr0
+ bts eax, 31
+ mov cr0, eax ;Now in compatibility mode.
+ jmp $+2
+
+ pushd CODE_SEL_64
+ call @f ;push rip/eip
+@@:
+ add dword ptr [esp], @f - $
+ retf
+@@:
+
+ ;--In long mode.
+endif
+
+ lgdt fword ptr [GdtSave + ebx] ;Restore GDT
+ lidt fword ptr [IdtSave+ebx] ;Restore IDT
+
+ ;restore original cs
+ ;rsp/esp = cs
+ call @f ;push rip/eip
+@@:
+ add dword ptr [esp], @f - $
+ifdef EFIx64
+ db 48h
+endif
+ retf ;pop cs and eip.
+@@:
+
+ pop gs
+ pop fs
+ pop eax
+ mov ss, ax
+ pop eax
+ mov es, ax
+ pop eax
+ mov ds, ax
+
+ifdef EFIx64
+ ;TODO: Double check Reverse Thunk code.
+ cmp BYTE PTR [IsReverseThunk+ebx], 1
+ jne @f
+; Reverse thunk - copy parameters to RCX, RDX, R8, R9
+ db 48h, 8bh, 4ch, 24h, 28h ; mov rcx, [rsp + 28h]
+ db 48h, 8bh, 54h, 24h, 30h ; mov rdx, [rsp + 30h]
+ db 67h, 4ch, 8bh, 44h, 24h, 38h ; mov r8d, [rsp + 38h]
+ db 67h, 4ch, 8bh, 4ch, 24h, 40h ; mov r9d, [rsp + 40h]
+
+ jmp RealToPm_Exit
+@@:
+endif
+
+ mov eax, cs:[CR3Save + ebx]
+ mov cr3, eax
+ mov eax, cs:[CR4Save + ebx]
+ mov cr4, eax
+ pop ebx
+RealToPm_Exit:
+ ret
+
+;-----------------------------------------------------------
+ReverseThunk:
+ ; Save flags
+ db 66h, 9ch ; pushfd
+ db 66h, 2eh, 8fh, 6 ; pop DWORD PTR cs:RtSavedFlags
+ dw LOWWORD OFFSET RtSavedFlags
+
+ cli
+
+ db 66h, 2eh, 89h, 26h ;mov cs:RtStackSave, esp
+ dw LOWWORD offset RtStackSave
+
+ db 2eh, 8ch, 16h ;mov cs:RtStackSave+4, ss
+ dw LOWWORD offset RtStackSave+4
+
+ ; Get the PM stack pointer from the stack
+ db 89h, 0e5h ; mov bp, sp
+ db 66h, 8bh, 46h, 4 ; mov eax, [bp+4]
+ db 66h, 2eh, 0a3h ; mov cs:PmStackPtr, eax
+ dw LOWWORD offset PmStackPtr
+
+ ; Get return address and store it in cs:RtRetAddressSave
+ db 66h, 8bh, 46h, 0 ; mov eax, [bp+0]
+ db 66h, 2eh, 0a3h ; mov cs:RtRetAddressSave, eax
+ dw LOWWORD offset RtRetAddressSave
+
+ ; Save the registers in RtRegs
+ push cs
+ pop ss
+
+ db 0bch ; mov sp, LOWWORD OFFSET RtRegs+28h
+ dw LOWWORD OFFSET RtRegs+28h
+
+ db 66h, 60h ; pushad
+ push ds
+ push es
+ push fs
+ push gs
+
+ ; Restore SS:ESP
+ db 66h, 2eh, 8bh, 26h ;mov esp, cs:RtStackSave
+ dw LOWWORD offset RtStackSave
+
+ db 2eh, 8eh, 16h ;mov ss, cs:RtStackSave+4
+ dw LOWWORD offset RtStackSave+4
+
+ db 2eh, 0c6h, 06h ;mov cs:[IsReverseThunk], 1
+ dw LOWWORD offset IsReverseThunk
+ db 1
+
+ db 0e9h
+ dw RealToPm - ($+2) ;jmp NEAR RealToPm
+
+;-----------------------------------------------------------
+ reg_gs dw ?
+ reg_fs dw ?
+ reg_es dw ?
+ reg_ds dw ?
+ reg_eflags dd ?
+
+Fixups:
+ifdef EFIx64
+ ;In 64 bit mode, but compiled under 32-bit mode.
+ push ebx ;(push rbx) cpuid changes ebx
+ mov edx, ecx
+ shr edx, 4 ;Get segment
+
+;--Fixups---
+ ;add ComModeFixup, ecx
+ db 01, 0dh
+ dd ComModeFixup - $ - 4
+ ;add P32ModeFixUp, ecx
+ db 01, 0dh
+ dd P32ModeFixUp - $ - 4
+ ;add GdtDescriptorFixUp, ecx
+ db 01, 0dh
+ dd GdtDescriptorFixUp - $ - 4
+; add CODE_SEL_BASE_FIXUP, ecx ;must use add because upper 8 bit shouldn't change. Only 20 bit number.
+ db 01, 0dh
+ dd CODE_SEL_BASE_FIXUP - $ - 4
+; mov word ptr RealModeFixUp, dx
+ db 66h, 89h, 15h
+ dd RealModeFixUp - $ - 4
+ mov eax, 1
+ cpuid ;serialization for fixups
+ pop ebx ;pop rbx
+else
+ push ebp
+ mov ebp, esp
+
+ push ebx
+ push edx
+
+ mov ebx, [ebp+8] ;Get base address of this module
+ mov edx, ebx
+ shr edx, 4 ;Get segment
+
+;--Fixups---
+ add [P32ModeFixUp+ebx], ebx
+ add [GdtDescriptorFixUp+ebx], ebx
+ add [CODE_SEL_BASE_FIXUP+ebx], ebx ;must use add because upper 8 bit shouldn't change. Only 20 bit number.
+ mov word ptr [RealModeFixUp+ebx], dx
+
+ mov eax, 1
+ cpuid ;serialization for fixups
+ mov ebx, [ebp + 8] ;restore ebx
+
+ pop edx
+ pop ebx
+ pop ebp
+endif
+ ret
+
+align 16
+GDT_BASE:
+NULL_SEL equ $-GDT_BASE ;NULL Selector 0
+ dq 0
+DATA_SEL equ $-GDT_BASE
+ dq 00cf93000000ffffh
+CODE_SEL equ $-GDT_BASE
+ dq 00cf9b000000ffffh
+CODE_SEL_64 equ $-GDT_BASE
+ dq 00af9b000000ffffh
+DATA_SEL_16 equ $-GDT_BASE
+ dq 008f93000000ffffh
+
+CODE_SEL_16 equ $-GDT_BASE
+ dw 0ffffh
+CODE_SEL_BASE_FIXUP: ;Only 20 bits max
+ dw 0
+ db 0
+
+ db 09ah
+ db 0
+ db 0
+
+GDT_SIZE equ $-GDT_BASE ;Size of Descriptor Table
+GdtDescriptor:
+ dw GDT_SIZE - 1 ; GDT limit
+GdtDescriptorFixUp:
+ dq OFFSET GDT_BASE ; GDT base
+
+ifdef EFIx64
+align 8
+ComModeFixup equ $
+ComModeAdr equ $
+ dd offset ComMode
+ dw CODE_SEL
+endif
+
+ public StackSave
+StackSave label dword
+ dd 0
+align 8
+ public CR3Save
+CR3Save label dword
+ dq 0
+align 8
+ public CR4Save
+CR4Save label dword
+ dq 0
+align 8
+ public GdtSave
+GdtSave label fword
+ dw 0
+ dq 0
+
+align 8
+ public IdtSave
+IdtSave label fword
+ dw 0
+ dq 0
+align 8
+ public LegacyLdtDescriptor
+LegacyLdtDescriptor label fword
+ dw 3ffh
+ dq 0
+
+;------Reverse thunk data------------
+IsReverseThunk db 0
+RtReturnResult dd 0
+RtSavedFlags dd 0
+RtStackSave db 6 dup (0) ; DW for SS, DD for ESP
+PmStackPtr dd 0
+RtRetAddressSave dd 0
+ThunkStart dd 0
+RtRegs REGISTERS <>
+
+THUNK endp
+THUNK_SEG ENDS
+end
+
+;**********************************************************************
+;**********************************************************************
+;** **
+;** (C)Copyright 1985-2012, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;**********************************************************************
+;**********************************************************************
diff --git a/Core/EM/CSM/thunk/x86/x86thunk.cif b/Core/EM/CSM/thunk/x86/x86thunk.cif
new file mode 100644
index 0000000..61600c3
--- /dev/null
+++ b/Core/EM/CSM/thunk/x86/x86thunk.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "x86Thunk"
+ category = ModulePart
+ LocalRoot = "core\em\csm\thunk\x86"
+ RefName = "x86THUNK"
+[files]
+"\thunk.c"
+"\x86thunk.asm"
+"\x86thunk.mak"
+<endComponent>
diff --git a/Core/EM/CSM/thunk/x86/x86thunk.mak b/Core/EM/CSM/thunk/x86/x86thunk.mak
new file mode 100644
index 0000000..724023f
--- /dev/null
+++ b/Core/EM/CSM/thunk/x86/x86thunk.mak
@@ -0,0 +1,67 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/x86thunk.mak 7 1/12/10 11:47a Olegi $
+#
+# $Revision: 7 $
+#
+# $Date: 1/12/10 11:47a $
+#**********************************************************************
+
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: x86Thunk.mak
+#
+# Description: This file has a set of rules to create a binary that will
+# be copied into lower memory that will give control to CSM16
+# code.
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+
+all: CREATE_THUNK_FFS
+
+CREATE_THUNK_FFS: $(BUILD_DIR)\x86Thunk.ffs
+
+$(BUILD_DIR)\x86Thunk.ffs : $(BUILD_DIR)\x86Thunk.bin
+ $(MAKE) /f Core\FFS.mak \
+ BUILD_DIR=$(BUILD_DIR) SOURCE_DIR=$(CSM_THUNKASM_DIR) \
+ GUID=A08276EC-A0FE-4e06-8670-385336C7D093 \
+ TYPE=EFI_FV_FILETYPE_FREEFORM \
+ BINFILE=$** FFSFILE=$@ COMPRESS=0 NAME=$(**B)
+
+$(BUILD_DIR)\x86Thunk.bin: $(X86THUNK_DIR)\x86Thunk.asm
+!IF "$(x64_BUILD)"=="1"
+ $(ASM) /c /nologo /DEFIx64 /Fo$(BUILD_DIR)\x86thunk.obj $(X86THUNK_DIR)\x86Thunk.asm
+!ELSE
+ $(ASM) /c /nologo /Fo$(BUILD_DIR)\x86thunk.obj $(X86THUNK_DIR)\x86Thunk.asm
+!ENDIF
+ $(ASMLINK) /MAP $(BUILD_DIR)\x86thunk.obj, $(BUILD_DIR)\x86thunk.exe, $(BUILD_DIR)\x86thunk.map,,,
+ exe2bin $(BUILD_DIR)\x86thunk.exe $(BUILD_DIR)\x86Thunk.bin
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************