diff options
Diffstat (limited to 'Core/EM/CSM/thunk/x86')
-rw-r--r-- | Core/EM/CSM/thunk/x86/thunk.c | 793 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/x86/x86thunk.asm | 828 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/x86/x86thunk.cif | 10 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/x86/x86thunk.mak | 67 |
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 ** +#** ** +#********************************************************************** +#********************************************************************** |