Add Wrapper to indicate it for FspWrapper only. Cc: Giri P Mudusuru <[email protected]> Cc: Maurice Ma <[email protected]> Cc: Ravi P Rangarajan <[email protected]> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <[email protected]> Reviewed-by: Giri P Mudusuru <[email protected]> Reviewed-by: Maurice Ma <[email protected]> Reviewed-by: Ravi P Rangarajan <[email protected]> --- IntelFspWrapperPkg/Include/Library/FspApiLib.h | 109 ---------- IntelFspWrapperPkg/Include/Library/FspWrapperApiLib.h | 88 ++++++++ IntelFspWrapperPkg/Library/BaseFspApiLib/BaseFspApiLib.inf | 67 ------ IntelFspWrapperPkg/Library/BaseFspApiLib/FspApiLib.c | 215 ------------------ IntelFspWrapperPkg/Library/BaseFspApiLib/IA32/DispatchExecute.c | 47 ---- IntelFspWrapperPkg/Library/BaseFspApiLib/X64/DispatchExecute.c | 106 --------- IntelFspWrapperPkg/Library/BaseFspApiLib/X64/Thunk64To32.S | 230 -------------------- IntelFspWrapperPkg/Library/BaseFspApiLib/X64/Thunk64To32.asm | 230 -------------------- IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf | 71 ++++++ IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c | 203 +++++++++++++++++ IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c | 58 +++++ IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c | 108 +++++++++ IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.S | 230 ++++++++++++++++++++ IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.asm | 230 ++++++++++++++++++++ 14 files changed, 988 insertions(+), 1004 deletions(-)
diff --git a/IntelFspWrapperPkg/Include/Library/FspApiLib.h b/IntelFspWrapperPkg/Include/Library/FspApiLib.h deleted file mode 100644 index 160c07f..0000000 --- a/IntelFspWrapperPkg/Include/Library/FspApiLib.h +++ /dev/null @@ -1,109 +0,0 @@ -/** @file - Provide FSP API related function. - - Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __FSP_API_LIB_H__ -#define __FSP_API_LIB_H__ - -#include <FspApi.h> -#include <FspInfoHeader.h> - -/** - Find FSP header pointer. - - @param[in] FlashFvFspBase Flash address of FSP FV. - - @return FSP header pointer. -**/ -FSP_INFO_HEADER * -EFIAPI -FspFindFspHeader ( - IN EFI_PHYSICAL_ADDRESS FlashFvFspBase - ); - -/** - Call FSP API - FspInit. - - @param[in] FspHeader FSP header pointer. - @param[in] FspInitParams Address pointer to the FSP_INIT_PARAMS structure. - - @return EFI status returned by FspInit API. -**/ -EFI_STATUS -EFIAPI -CallFspInit ( - IN FSP_INFO_HEADER *FspHeader, - IN FSP_INIT_PARAMS *FspInitParams - ); - -/** - Call FSP API - FspNotifyPhase. - - @param[in] FspHeader FSP header pointer. - @param[in] NotifyPhaseParams Address pointer to the NOTIFY_PHASE_PARAMS structure. - - @return EFI status returned by FspNotifyPhase API. -**/ -EFI_STATUS -EFIAPI -CallFspNotifyPhase ( - IN FSP_INFO_HEADER *FspHeader, - IN NOTIFY_PHASE_PARAMS *NotifyPhaseParams - ); - -/** - Call FSP API - FspMemoryInit. - - @param[in] FspHeader FSP header pointer. - @param[in,out] FspMemoryInitParams Address pointer to the FSP_MEMORY_INIT_PARAMS structure. - - @return EFI status returned by FspMemoryInit API. -**/ -EFI_STATUS -EFIAPI -CallFspMemoryInit ( - IN FSP_INFO_HEADER *FspHeader, - IN OUT FSP_MEMORY_INIT_PARAMS *FspMemoryInitParams - ); - -/** - Call FSP API - TempRamExit. - - @param[in] FspHeader FSP header pointer. - @param[in,out] TempRamExitParam Address pointer to the TempRamExit parameters structure. - - @return EFI status returned by TempRamExit API. -**/ -EFI_STATUS -EFIAPI -CallTempRamExit ( - IN FSP_INFO_HEADER *FspHeader, - IN OUT VOID *TempRamExitParam - ); - -/** - Call FSP API - FspSiliconInit. - - @param[in] FspHeader FSP header pointer. - @param[in,out] FspSiliconInitParam Address pointer to the Silicon Init parameters structure. - - @return EFI status returned by FspSiliconInit API. -**/ -EFI_STATUS -EFIAPI -CallFspSiliconInit ( - IN FSP_INFO_HEADER *FspHeader, - IN OUT VOID *FspSiliconInitParam - ); - -#endif diff --git a/IntelFspWrapperPkg/Include/Library/FspWrapperApiLib.h b/IntelFspWrapperPkg/Include/Library/FspWrapperApiLib.h new file mode 100644 index 0000000..e4291a7 --- /dev/null +++ b/IntelFspWrapperPkg/Include/Library/FspWrapperApiLib.h @@ -0,0 +1,88 @@ +/** @file + Provide FSP wrapper API related function. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __FSP_WRAPPER_API_LIB_H__ +#define __FSP_WRAPPER_API_LIB_H__ + +#include <FspApi.h> +#include <FspInfoHeader.h> + +/** + Find FSP header pointer. + + @param[in] FlashFvFspBase Flash address of FSP FV. + + @return FSP header pointer. +**/ +FSP_INFO_HEADER * +EFIAPI +FspFindFspHeader ( + IN EFI_PHYSICAL_ADDRESS FlashFvFspBase + ); + +/** + Call FSP API - FspNotifyPhase. + + @param[in] NotifyPhaseParams Address pointer to the NOTIFY_PHASE_PARAMS structure. + + @return EFI status returned by FspNotifyPhase API. +**/ +EFI_STATUS +EFIAPI +CallFspNotifyPhase ( + IN NOTIFY_PHASE_PARAMS *NotifyPhaseParams + ); + +/** + Call FSP API - FspMemoryInit. + + @param[in] FspmUpdDataPtr Pointer to the FSPM_UPD data sructure. + @param[out] HobListPtr Pointer to receive the address of the HOB list. + + @return EFI status returned by FspMemoryInit API. +**/ +EFI_STATUS +EFIAPI +CallFspMemoryInit ( + IN VOID *FspmUpdDataPtr, + OUT VOID **HobListPtr + ); + +/** + Call FSP API - TempRamExit. + + @param[in] TempRamExitParam Address pointer to the TempRamExit parameters structure. + + @return EFI status returned by TempRamExit API. +**/ +EFI_STATUS +EFIAPI +CallTempRamExit ( + IN VOID *TempRamExitParam + ); + +/** + Call FSP API - FspSiliconInit. + + @param[in] FspsUpdDataPtr Pointer to the FSPS_UPD data structure. + + @return EFI status returned by FspSiliconInit API. +**/ +EFI_STATUS +EFIAPI +CallFspSiliconInit ( + IN VOID *FspsUpdDataPtr + ); + +#endif diff --git a/IntelFspWrapperPkg/Library/BaseFspApiLib/BaseFspApiLib.inf b/IntelFspWrapperPkg/Library/BaseFspApiLib/BaseFspApiLib.inf deleted file mode 100644 index 2df1683..0000000 --- a/IntelFspWrapperPkg/Library/BaseFspApiLib/BaseFspApiLib.inf +++ /dev/null @@ -1,67 +0,0 @@ -## @file -# Provide FSP API related function. -# -# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> -# -# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php. -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -## - -################################################################################ -# -# Defines Section - statements that will be processed to create a Makefile. -# -################################################################################ -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = BaseFspApiLib - FILE_GUID = 6E4CB8C5-6144-4ae3-BA52-B6AFBCB2B2F5 - MODULE_TYPE = BASE - VERSION_STRING = 1.0 - LIBRARY_CLASS = FspApiLib - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 -# - -################################################################################ -# -# Sources Section - list of files that are required for the build to succeed. -# -################################################################################ - -[Sources] - FspApiLib.c - -[Sources.IA32] - IA32/DispatchExecute.c - -[Sources.X64] - X64/DispatchExecute.c - X64/Thunk64To32.asm - X64/Thunk64To32.S - -################################################################################ -# -# Package Dependency Section - list of Package files that are required for -# this module. -# -################################################################################ - -[Packages] - MdePkg/MdePkg.dec - IntelFspPkg/IntelFspPkg.dec - IntelFspWrapperPkg/IntelFspWrapperPkg.dec - -[LibraryClasses] - BaseLib - -[Guids] - gFspHeaderFileGuid ## CONSUMES ## GUID diff --git a/IntelFspWrapperPkg/Library/BaseFspApiLib/FspApiLib.c b/IntelFspWrapperPkg/Library/BaseFspApiLib/FspApiLib.c deleted file mode 100644 index 162d244..0000000 --- a/IntelFspWrapperPkg/Library/BaseFspApiLib/FspApiLib.c +++ /dev/null @@ -1,215 +0,0 @@ -/** @file - Provide FSP API related function. - - Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include <PiPei.h> - -#include <Guid/FspHeaderFile.h> - -#include <Library/FspApiLib.h> -#include <Library/BaseLib.h> -#include <Library/BaseMemoryLib.h> - -/** - Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to - long mode. - - @param[in] Function The 32bit code entry to be executed. - @param[in] Param1 The first parameter to pass to 32bit code. - - @return EFI_STATUS. -**/ -EFI_STATUS -Execute32BitCode ( - IN UINT64 Function, - IN UINT64 Param1 - ); - -/** - Find FSP header pointer. - - @param[in] FlashFvFspBase Flash address of FSP FV. - - @return FSP header pointer. -**/ -FSP_INFO_HEADER * -EFIAPI -FspFindFspHeader ( - IN EFI_PHYSICAL_ADDRESS FlashFvFspBase - ) -{ - UINT8 *CheckPointer; - - CheckPointer = (UINT8 *) (UINTN) FlashFvFspBase; - - if (((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->Signature != EFI_FVH_SIGNATURE) { - return NULL; - } - - if (((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->ExtHeaderOffset != 0) { - CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->ExtHeaderOffset; - CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_EXT_HEADER *)CheckPointer)->ExtHeaderSize; - CheckPointer = (UINT8 *) ALIGN_POINTER (CheckPointer, 8); - } else { - CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->HeaderLength; - } - - if (!CompareGuid (&((EFI_FFS_FILE_HEADER *)CheckPointer)->Name, &gFspHeaderFileGuid)) { - return NULL; - } - - CheckPointer = CheckPointer + sizeof (EFI_FFS_FILE_HEADER); - - if (((EFI_RAW_SECTION *)CheckPointer)->Type != EFI_SECTION_RAW) { - return NULL; - } - - CheckPointer = CheckPointer + sizeof (EFI_RAW_SECTION); - - return (FSP_INFO_HEADER *)CheckPointer; -} - -/** - Call FSP API - FspInit. - - @param[in] FspHeader FSP header pointer. - @param[in] FspInitParams Address pointer to the FSP_INIT_PARAMS structure. - - @return EFI status returned by FspInit API. -**/ -EFI_STATUS -EFIAPI -CallFspInit ( - IN FSP_INFO_HEADER *FspHeader, - IN FSP_INIT_PARAMS *FspInitParams - ) -{ - FSP_INIT FspInitApi; - EFI_STATUS Status; - BOOLEAN InterruptState; - - FspInitApi = (FSP_INIT)(UINTN)(FspHeader->ImageBase + FspHeader->FspInitEntryOffset); - InterruptState = SaveAndDisableInterrupts (); - Status = Execute32BitCode ((UINTN)FspInitApi, (UINTN)FspInitParams); - SetInterruptState (InterruptState); - - return Status; -} - -/** - Call FSP API - FspNotifyPhase. - - @param[in] FspHeader FSP header pointer. - @param[in] NotifyPhaseParams Address pointer to the NOTIFY_PHASE_PARAMS structure. - - @return EFI status returned by FspNotifyPhase API. -**/ -EFI_STATUS -EFIAPI -CallFspNotifyPhase ( - IN FSP_INFO_HEADER *FspHeader, - IN NOTIFY_PHASE_PARAMS *NotifyPhaseParams - ) -{ - FSP_NOTIFY_PHASE NotifyPhaseApi; - EFI_STATUS Status; - BOOLEAN InterruptState; - - NotifyPhaseApi = (FSP_NOTIFY_PHASE)(UINTN)(FspHeader->ImageBase + FspHeader->NotifyPhaseEntryOffset); - InterruptState = SaveAndDisableInterrupts (); - Status = Execute32BitCode ((UINTN)NotifyPhaseApi, (UINTN)NotifyPhaseParams); - SetInterruptState (InterruptState); - - return Status; -} - -/** - Call FSP API - FspMemoryInit. - - @param[in] FspHeader FSP header pointer. - @param[in,out] FspMemoryInitParams Address pointer to the FSP_MEMORY_INIT_PARAMS structure. - - @return EFI status returned by FspMemoryInit API. -**/ -EFI_STATUS -EFIAPI -CallFspMemoryInit ( - IN FSP_INFO_HEADER *FspHeader, - IN OUT FSP_MEMORY_INIT_PARAMS *FspMemoryInitParams - ) -{ - FSP_MEMORY_INIT FspMemoryInitApi; - EFI_STATUS Status; - BOOLEAN InterruptState; - - FspMemoryInitApi = (FSP_MEMORY_INIT)(UINTN)(FspHeader->ImageBase + FspHeader->FspMemoryInitEntryOffset); - InterruptState = SaveAndDisableInterrupts (); - Status = Execute32BitCode ((UINTN)FspMemoryInitApi, (UINTN)FspMemoryInitParams); - SetInterruptState (InterruptState); - - return Status; -} - -/** - Call FSP API - TempRamExit. - - @param[in] FspHeader FSP header pointer. - @param[in,out] TempRamExitParam Address pointer to the TempRamExit parameters structure. - - @return EFI status returned by TempRamExit API. -**/ -EFI_STATUS -EFIAPI -CallTempRamExit ( - IN FSP_INFO_HEADER *FspHeader, - IN OUT VOID *TempRamExitParam - ) -{ - FSP_TEMP_RAM_EXIT TempRamExitApi; - EFI_STATUS Status; - BOOLEAN InterruptState; - - TempRamExitApi = (FSP_TEMP_RAM_EXIT)(UINTN)(FspHeader->ImageBase + FspHeader->TempRamExitEntryOffset); - InterruptState = SaveAndDisableInterrupts (); - Status = Execute32BitCode ((UINTN)TempRamExitApi, (UINTN)TempRamExitParam); - SetInterruptState (InterruptState); - - return Status; -} - -/** - Call FSP API - FspSiliconInit. - - @param[in] FspHeader FSP header pointer. - @param[in,out] FspSiliconInitParam Address pointer to the Silicon Init parameters structure. - - @return EFI status returned by FspSiliconInit API. -**/ -EFI_STATUS -EFIAPI -CallFspSiliconInit ( - IN FSP_INFO_HEADER *FspHeader, - IN OUT VOID *FspSiliconInitParam - ) -{ - FSP_SILICON_INIT FspSiliconInitApi; - EFI_STATUS Status; - BOOLEAN InterruptState; - - FspSiliconInitApi = (FSP_SILICON_INIT)(UINTN)(FspHeader->ImageBase + FspHeader->FspSiliconInitEntryOffset); - InterruptState = SaveAndDisableInterrupts (); - Status = Execute32BitCode ((UINTN)FspSiliconInitApi, (UINTN)FspSiliconInitParam); - SetInterruptState (InterruptState); - - return Status; -} diff --git a/IntelFspWrapperPkg/Library/BaseFspApiLib/IA32/DispatchExecute.c b/IntelFspWrapperPkg/Library/BaseFspApiLib/IA32/DispatchExecute.c deleted file mode 100644 index 8bc3501..0000000 --- a/IntelFspWrapperPkg/Library/BaseFspApiLib/IA32/DispatchExecute.c +++ /dev/null @@ -1,47 +0,0 @@ -/** @file - Execute 32-bit code in Protected Mode. - - Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include <Uefi.h> -#include <FspApi.h> - -typedef -EFI_STATUS -(EFIAPI *FSP_FUNCTION) ( - IN VOID *Param1 - ); - -/** - Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to - long mode. - - @param[in] Function The 32bit code entry to be executed. - @param[in] Param1 The first parameter to pass to 32bit code. - - @return EFI_STATUS. -**/ -EFI_STATUS -Execute32BitCode ( - IN UINT64 Function, - IN UINT64 Param1 - ) -{ - FSP_FUNCTION EntryFunc; - EFI_STATUS Status; - - EntryFunc = (FSP_FUNCTION) (UINTN) (Function); - Status = EntryFunc ((VOID *)(UINTN)Param1); - - return Status; -} - diff --git a/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/DispatchExecute.c b/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/DispatchExecute.c deleted file mode 100644 index 360327e..0000000 --- a/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/DispatchExecute.c +++ /dev/null @@ -1,106 +0,0 @@ -/** @file - Execute 32-bit code in Long Mode. - Provide a thunk function to transition from long mode to compatibility mode to execute 32-bit code and then transit - back to long mode. - - Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include <Uefi.h> -#include <Library/BaseLib.h> -#include <FspApi.h> - -#pragma pack(1) -typedef union { - struct { - UINT32 LimitLow : 16; - UINT32 BaseLow : 16; - UINT32 BaseMid : 8; - UINT32 Type : 4; - UINT32 System : 1; - UINT32 Dpl : 2; - UINT32 Present : 1; - UINT32 LimitHigh : 4; - UINT32 Software : 1; - UINT32 Reserved : 1; - UINT32 DefaultSize : 1; - UINT32 Granularity : 1; - UINT32 BaseHigh : 8; - } Bits; - UINT64 Uint64; -} IA32_GDT; -#pragma pack() - -GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = { - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x0: reserve */ - {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x8: compatibility mode */ - {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}}, /* 0x10: for long mode */ - {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x18: data */ - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x20: reserve */ -}; - -// -// IA32 Gdt register -// -GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = { - sizeof (mGdtEntries) - 1, - (UINTN) mGdtEntries - }; - -/** - Assembly function to transition from long mode to compatibility mode to execute 32-bit code and then transit back to - long mode. - - @param[in] Function The 32bit code entry to be executed. - @param[in] Param1 The first parameter to pass to 32bit code - @param[in] Param2 The second parameter to pass to 32bit code - @param[in] InternalGdtr The GDT and GDT descriptor used by this library - - @return status. -**/ -UINT32 -AsmExecute32BitCode ( - IN UINT64 Function, - IN UINT64 Param1, - IN UINT64 Param2, - IN IA32_DESCRIPTOR *InternalGdtr - ); - -/** - Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to - long mode. - - @param[in] Function The 32bit code entry to be executed. - @param[in] Param1 The first parameter to pass to 32bit code. - - @return EFI_STATUS. -**/ -EFI_STATUS -Execute32BitCode ( - IN UINT64 Function, - IN UINT64 Param1 - ) -{ - EFI_STATUS Status; - IA32_DESCRIPTOR Idtr; - - // - // Idtr might be changed inside of FSP. 32bit FSP only knows the <4G address. - // If IDTR.Base is >4G, FSP can not handle. So we need save/restore IDTR here for X64 only. - // Interrupt is already disabled here, so it is safety to update IDTR. - // - AsmReadIdtr (&Idtr); - Status = AsmExecute32BitCode (Function, Param1, 0, &mGdt); - AsmWriteIdtr (&Idtr); - - return Status; -} - diff --git a/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/Thunk64To32.S b/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/Thunk64To32.S deleted file mode 100644 index b6b5c1a..0000000 --- a/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/Thunk64To32.S +++ /dev/null @@ -1,230 +0,0 @@ -# -# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> -# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php. -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -# -# Module Name: -# -# Thunk64To32.asm -# -# Abstract: -# -# This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then -# transit back to long mode. -# -#------------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Procedure: AsmExecute32BitCode -# -# Input: None -# -# Output: None -# -# Prototype: UINT32 -# AsmExecute32BitCode ( -# IN UINT64 Function, -# IN UINT64 Param1, -# IN UINT64 Param2, -# IN IA32_DESCRIPTOR *InternalGdtr -# ); -# -# -# Description: A thunk function to execute 32-bit code in long mode. -# -#---------------------------------------------------------------------------- - -ASM_GLOBAL ASM_PFX(AsmExecute32BitCode) -ASM_PFX(AsmExecute32BitCode): - # - # save IFLAG and disable it - # - pushfq - cli - - # - # save orignal GDTR and CS - # - movl %ds, %eax - push %rax - movl %cs, %eax - push %rax - subq $0x10, %rsp - sgdt (%rsp) - # - # load internal GDT - # - lgdt (%r9) - # - # Save general purpose register and rflag register - # - pushfq - push %rdi - push %rsi - push %rbp - push %rbx - - # - # save CR3 - # - movq %cr3, %rax - movq %rax, %rbp - - # - # Prepare the CS and return address for the transition from 32-bit to 64-bit mode - # - movq $0x10, %rax # load long mode selector - shl $32, %rax - lea ReloadCS(%rip), %r9 #Assume the ReloadCS is under 4G - orq %r9, %rax - push %rax - # - # Save parameters for 32-bit function call - # - movq %r8, %rax - shl $32, %rax - orq %rdx, %rax - push %rax - # - # save the 32-bit function entry and the return address into stack which will be - # retrieve in compatibility mode. - # - lea ReturnBack(%rip), %rax #Assume the ReloadCS is under 4G - shl $32, %rax - orq %rcx, %rax - push %rax - - # - # let rax save DS - # - movq $0x18, %rax - - # - # Change to Compatible Segment - # - movq $8, %rcx # load compatible mode selector - shl $32, %rcx - lea Compatible(%rip), %rdx # assume address < 4G - orq %rdx, %rcx - push %rcx - .byte 0xcb # retf - -Compatible: - # reload DS/ES/SS to make sure they are correct referred to current GDT - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - - # - # Disable paging - # - movq %cr0, %rcx - btc $31, %ecx - movq %rcx, %cr0 - # - # Clear EFER.LME - # - movl $0xC0000080, %ecx - rdmsr - btc $8, %eax - wrmsr - -# Now we are in protected mode - # - # Call 32-bit function. Assume the function entry address and parameter value is less than 4G - # - pop %rax # Here is the function entry - # - # Now the parameter is at the bottom of the stack, then call in to IA32 function. - # - jmp *%rax -ReturnBack: - movl %eax, %ebx # save return status - pop %rcx # drop param1 - pop %rcx # drop param2 - - # - # restore CR4 - # - movq %cr4, %rax - bts $5, %eax - movq %rax, %cr4 - - # - # restore CR3 - # - movl %ebp, %eax - movq %rax, %cr3 - - # - # Set EFER.LME to re-enable ia32-e - # - movl $0xC0000080, %ecx - rdmsr - bts $8, %eax - wrmsr - # - # Enable paging - # - movq %cr0, %rax - bts $31, %eax - mov %rax, %cr0 -# Now we are in compatible mode - - # - # Reload cs register - # - .byte 0xcb # retf -ReloadCS: - # - # Now we're in Long Mode - # - # - # Restore C register and eax hold the return status from 32-bit function. - # Note: Do not touch rax from now which hold the return value from IA32 function - # - movl %ebx, %eax # put return status to EAX - pop %rbx - pop %rbp - pop %rsi - pop %rdi - popfq - # - # Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor. - # - lgdt (%rsp) - # - # drop GDT descriptor in stack - # - addq $0x10, %rsp - # - # switch to orignal CS and GDTR - # - pop %r9 # get CS - shl $32, %r9 # rcx[32..47] <- Cs - lea ReturnToLongMode(%rip), %rcx - orq %r9, %rcx - push %rcx - .byte 0xcb # retf -ReturnToLongMode: - # - # Reload original DS/ES/SS - # - pop %rcx - movl %ecx, %ds - movl %ecx, %es - movl %ecx, %ss - - # - # Restore IFLAG - # - popfq - - ret - diff --git a/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/Thunk64To32.asm b/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/Thunk64To32.asm deleted file mode 100644 index 70e7b5f..0000000 --- a/IntelFspWrapperPkg/Library/BaseFspApiLib/X64/Thunk64To32.asm +++ /dev/null @@ -1,230 +0,0 @@ -; -; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> -; This program and the accompanying materials -; are licensed and made available under the terms and conditions of the BSD License -; which accompanies this distribution. The full text of the license may be found at -; http://opensource.org/licenses/bsd-license.php. -; -; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -; -; -; Module Name: -; -; Thunk64To32.asm -; -; Abstract: -; -; This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then -; transit back to long mode. -; -;------------------------------------------------------------------------------- - .code -;---------------------------------------------------------------------------- -; Procedure: AsmExecute32BitCode -; -; Input: None -; -; Output: None -; -; Prototype: UINT32 -; AsmExecute32BitCode ( -; IN UINT64 Function, -; IN UINT64 Param1, -; IN UINT64 Param2, -; IN IA32_DESCRIPTOR *InternalGdtr -; ); -; -; -; Description: A thunk function to execute 32-bit code in long mode. -; -;---------------------------------------------------------------------------- -AsmExecute32BitCode PROC - ; - ; save IFLAG and disable it - ; - pushfq - cli - - ; - ; save orignal GDTR and CS - ; - mov rax, ds - push rax - mov rax, cs - push rax - sub rsp, 10h - sgdt fword ptr [rsp] - ; - ; load internal GDT - ; - lgdt fword ptr [r9] - ; - ; Save general purpose register and rflag register - ; - pushfq - push rdi - push rsi - push rbp - push rbx - - ; - ; save CR3 - ; - mov rax, cr3 - mov rbp, rax - - ; - ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode - ; - mov rax, 10h ; load long mode selector - shl rax, 32 - mov r9, OFFSET ReloadCS ;Assume the ReloadCS is under 4G - or rax, r9 - push rax - ; - ; Save parameters for 32-bit function call - ; - mov rax, r8 - shl rax, 32 - or rax, rdx - push rax - ; - ; save the 32-bit function entry and the return address into stack which will be - ; retrieve in compatibility mode. - ; - mov rax, OFFSET ReturnBack ;Assume the ReloadCS is under 4G - shl rax, 32 - or rax, rcx - push rax - - ; - ; let rax save DS - ; - mov rax, 018h - - ; - ; Change to Compatible Segment - ; - mov rcx, 08h ; load compatible mode selector - shl rcx, 32 - mov rdx, OFFSET Compatible ; assume address < 4G - or rcx, rdx - push rcx - retf - -Compatible: - ; reload DS/ES/SS to make sure they are correct referred to current GDT - mov ds, ax - mov es, ax - mov ss, ax - - ; - ; Disable paging - ; - mov rcx, cr0 - btc ecx, 31 - mov cr0, rcx - ; - ; Clear EFER.LME - ; - mov ecx, 0C0000080h - rdmsr - btc eax, 8 - wrmsr - -; Now we are in protected mode - ; - ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G - ; - pop rax ; Here is the function entry - ; - ; Now the parameter is at the bottom of the stack, then call in to IA32 function. - ; - jmp rax -ReturnBack: - mov ebx, eax ; save return status - pop rcx ; drop param1 - pop rcx ; drop param2 - - ; - ; restore CR4 - ; - mov rax, cr4 - bts eax, 5 - mov cr4, rax - - ; - ; restore CR3 - ; - mov eax, ebp - mov cr3, rax - - ; - ; Set EFER.LME to re-enable ia32-e - ; - mov ecx, 0C0000080h - rdmsr - bts eax, 8 - wrmsr - ; - ; Enable paging - ; - mov rax, cr0 - bts eax, 31 - mov cr0, rax -; Now we are in compatible mode - - ; - ; Reload cs register - ; - retf -ReloadCS: - ; - ; Now we're in Long Mode - ; - ; - ; Restore C register and eax hold the return status from 32-bit function. - ; Note: Do not touch rax from now which hold the return value from IA32 function - ; - mov eax, ebx ; put return status to EAX - pop rbx - pop rbp - pop rsi - pop rdi - popfq - ; - ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor. - ; - lgdt fword ptr[rsp] - ; - ; drop GDT descriptor in stack - ; - add rsp, 10h - ; - ; switch to orignal CS and GDTR - ; - pop r9 ; get CS - shl r9, 32 ; rcx[32..47] <- Cs - mov rcx, OFFSET @F - or rcx, r9 - push rcx - retf -@@: - ; - ; Reload original DS/ES/SS - ; - pop rcx - mov ds, rcx - mov es, rcx - mov ss, rcx - - ; - ; Restore IFLAG - ; - popfq - - ret -AsmExecute32BitCode ENDP - - END diff --git a/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf new file mode 100644 index 0000000..df682dc --- /dev/null +++ b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf @@ -0,0 +1,71 @@ +## @file +# Provide FSP API related function. +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseFspWrapperApiLib + FILE_GUID = 6E4CB8C5-6144-4ae3-BA52-B6AFBCB2B2F5 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FspWrapperApiLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources] + FspWrapperApiLib.c + +[Sources.IA32] + IA32/DispatchExecute.c + +[Sources.X64] + X64/DispatchExecute.c + X64/Thunk64To32.asm + X64/Thunk64To32.S + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + IntelFspPkg/IntelFspPkg.dec + IntelFspWrapperPkg/IntelFspWrapperPkg.dec + +[LibraryClasses] + BaseLib + +[Guids] + gFspHeaderFileGuid ## CONSUMES ## GUID + +[Pcd] + gFspWrapperTokenSpaceGuid.PcdFspmBaseAddress ## CONSUMES + gFspWrapperTokenSpaceGuid.PcdFspsBaseAddress ## CONSUMES diff --git a/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c new file mode 100644 index 0000000..0665b59 --- /dev/null +++ b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c @@ -0,0 +1,203 @@ +/** @file + Provide FSP API related function. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <PiPei.h> + +#include <Guid/FspHeaderFile.h> + +#include <Library/FspWrapperApiLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> + +/** + Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to + long mode. + + @param[in] Function The 32bit code entry to be executed. + @param[in] Param1 The first parameter to pass to 32bit code. + + @return EFI_STATUS. +**/ +EFI_STATUS +Execute32BitCode ( + IN UINT64 Function, + IN UINT64 Param1, + IN UINT64 Param2 + ); + +/** + Find FSP header pointer. + + @param[in] FlashFvFspBase Flash address of FSP FV. + + @return FSP header pointer. +**/ +FSP_INFO_HEADER * +EFIAPI +FspFindFspHeader ( + IN EFI_PHYSICAL_ADDRESS FlashFvFspBase + ) +{ + UINT8 *CheckPointer; + + CheckPointer = (UINT8 *) (UINTN) FlashFvFspBase; + + if (((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->Signature != EFI_FVH_SIGNATURE) { + return NULL; + } + + if (((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->ExtHeaderOffset != 0) { + CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->ExtHeaderOffset; + CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_EXT_HEADER *)CheckPointer)->ExtHeaderSize; + CheckPointer = (UINT8 *) ALIGN_POINTER (CheckPointer, 8); + } else { + CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->HeaderLength; + } + + + CheckPointer = CheckPointer + sizeof (EFI_FFS_FILE_HEADER); + + if (((EFI_RAW_SECTION *)CheckPointer)->Type != EFI_SECTION_RAW) { + return NULL; + } + + CheckPointer = CheckPointer + sizeof (EFI_RAW_SECTION); + + return (FSP_INFO_HEADER *)CheckPointer; +} + +/** + Call FSP API - FspNotifyPhase. + + @param[in] NotifyPhaseParams Address pointer to the NOTIFY_PHASE_PARAMS structure. + + @return EFI status returned by FspNotifyPhase API. +**/ +EFI_STATUS +EFIAPI +CallFspNotifyPhase ( + IN NOTIFY_PHASE_PARAMS *NotifyPhaseParams + ) +{ + FSP_INFO_HEADER *FspHeader; + FSP_NOTIFY_PHASE NotifyPhaseApi; + EFI_STATUS Status; + BOOLEAN InterruptState; + + FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddress)); + if (FspHeader == NULL) { + return EFI_DEVICE_ERROR; + } + + NotifyPhaseApi = (FSP_NOTIFY_PHASE)(UINTN)(FspHeader->ImageBase + FspHeader->NotifyPhaseEntryOffset); + InterruptState = SaveAndDisableInterrupts (); + Status = Execute32BitCode ((UINTN)NotifyPhaseApi, (UINTN)NotifyPhaseParams, (UINTN)NULL); + SetInterruptState (InterruptState); + + return Status; +} + +/** + Call FSP API - FspMemoryInit. + + @param[in,out] FspMemoryInitParams Address pointer to the FSP_MEMORY_INIT_PARAMS structure. + + @return EFI status returned by FspMemoryInit API. +**/ +EFI_STATUS +EFIAPI +CallFspMemoryInit ( + IN VOID *FspmUpdDataPtr, + OUT VOID **HobListPtr + ) +{ + FSP_INFO_HEADER *FspHeader; + FSP_MEMORY_INIT FspMemoryInitApi; + EFI_STATUS Status; + BOOLEAN InterruptState; + + FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddress)); + if (FspHeader == NULL) { + return EFI_DEVICE_ERROR; + } + + FspMemoryInitApi = (FSP_MEMORY_INIT)(UINTN)(FspHeader->ImageBase + FspHeader->FspMemoryInitEntryOffset); + InterruptState = SaveAndDisableInterrupts (); + Status = Execute32BitCode ((UINTN)FspMemoryInitApi, (UINTN)FspmUpdDataPtr, (UINTN)HobListPtr); + SetInterruptState (InterruptState); + + return Status; +} + +/** + Call FSP API - TempRamExit. + + @param[in,out] TempRamExitParam Address pointer to the TempRamExit parameters structure. + + @return EFI status returned by TempRamExit API. +**/ +EFI_STATUS +EFIAPI +CallTempRamExit ( + IN VOID *TempRamExitParam + ) +{ + FSP_INFO_HEADER *FspHeader; + FSP_TEMP_RAM_EXIT TempRamExitApi; + EFI_STATUS Status; + BOOLEAN InterruptState; + + FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddress)); + if (FspHeader == NULL) { + return EFI_DEVICE_ERROR; + } + + TempRamExitApi = (FSP_TEMP_RAM_EXIT)(UINTN)(FspHeader->ImageBase + FspHeader->TempRamExitEntryOffset); + InterruptState = SaveAndDisableInterrupts (); + Status = Execute32BitCode ((UINTN)TempRamExitApi, (UINTN)TempRamExitParam, (UINTN)NULL); + SetInterruptState (InterruptState); + + return Status; +} + +/** + Call FSP API - FspSiliconInit. + + @param[in,out] FspSiliconInitParam Address pointer to the Silicon Init parameters structure. + + @return EFI status returned by FspSiliconInit API. +**/ +EFI_STATUS +EFIAPI +CallFspSiliconInit ( + IN VOID *FspsUpdDataPtr + ) +{ + FSP_INFO_HEADER *FspHeader; + FSP_SILICON_INIT FspSiliconInitApi; + EFI_STATUS Status; + BOOLEAN InterruptState; + + FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddress)); + if (FspHeader == NULL) { + return EFI_DEVICE_ERROR; + } + + FspSiliconInitApi = (FSP_SILICON_INIT)(UINTN)(FspHeader->ImageBase + FspHeader->FspSiliconInitEntryOffset); + InterruptState = SaveAndDisableInterrupts (); + Status = Execute32BitCode ((UINTN)FspSiliconInitApi, (UINTN)FspsUpdDataPtr, (UINTN)NULL); + SetInterruptState (InterruptState); + + return Status; +} diff --git a/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c new file mode 100644 index 0000000..82d3d52 --- /dev/null +++ b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c @@ -0,0 +1,58 @@ +/** @file + Execute 32-bit code in Protected Mode. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <Uefi.h> +#include <FspApi.h> + +/** + FSP API functions. + + @param[in] Param1 The first parameter to pass to 32bit code. + @param[in] Param2 The second parameter to pass to 32bit code. + + @return EFI_STATUS. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_FUNCTION) ( + IN VOID *Param1, + IN VOID *Param2 + ); + +/** + Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to + long mode. + + @param[in] Function The 32bit code entry to be executed. + @param[in] Param1 The first parameter to pass to 32bit code. + @param[in] Param2 The second parameter to pass to 32bit code. + + @return EFI_STATUS. +**/ +EFI_STATUS +Execute32BitCode ( + IN UINT64 Function, + IN UINT64 Param1, + IN UINT64 Param2 + ) +{ + FSP_FUNCTION EntryFunc; + EFI_STATUS Status; + + EntryFunc = (FSP_FUNCTION) (UINTN) (Function); + Status = EntryFunc ((VOID *)(UINTN)Param1, (VOID *)(UINTN)Param2); + + return Status; +} + diff --git a/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c new file mode 100644 index 0000000..6fb0ac0 --- /dev/null +++ b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c @@ -0,0 +1,108 @@ +/** @file + Execute 32-bit code in Long Mode. + Provide a thunk function to transition from long mode to compatibility mode to execute 32-bit code and then transit + back to long mode. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <Uefi.h> +#include <Library/BaseLib.h> +#include <FspApi.h> + +#pragma pack(1) +typedef union { + struct { + UINT32 LimitLow : 16; + UINT32 BaseLow : 16; + UINT32 BaseMid : 8; + UINT32 Type : 4; + UINT32 System : 1; + UINT32 Dpl : 2; + UINT32 Present : 1; + UINT32 LimitHigh : 4; + UINT32 Software : 1; + UINT32 Reserved : 1; + UINT32 DefaultSize : 1; + UINT32 Granularity : 1; + UINT32 BaseHigh : 8; + } Bits; + UINT64 Uint64; +} IA32_GDT; +#pragma pack() + +GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = { + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x0: reserve */ + {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x8: compatibility mode */ + {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}}, /* 0x10: for long mode */ + {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x18: data */ + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x20: reserve */ +}; + +// +// IA32 Gdt register +// +GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = { + sizeof (mGdtEntries) - 1, + (UINTN) mGdtEntries + }; + +/** + Assembly function to transition from long mode to compatibility mode to execute 32-bit code and then transit back to + long mode. + + @param[in] Function The 32bit code entry to be executed. + @param[in] Param1 The first parameter to pass to 32bit code + @param[in] Param2 The second parameter to pass to 32bit code + @param[in] InternalGdtr The GDT and GDT descriptor used by this library + + @return status. +**/ +UINT32 +AsmExecute32BitCode ( + IN UINT64 Function, + IN UINT64 Param1, + IN UINT64 Param2, + IN IA32_DESCRIPTOR *InternalGdtr + ); + +/** + Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to + long mode. + + @param[in] Function The 32bit code entry to be executed. + @param[in] Param1 The first parameter to pass to 32bit code. + @param[in] Param2 The second parameter to pass to 32bit code. + + @return EFI_STATUS. +**/ +EFI_STATUS +Execute32BitCode ( + IN UINT64 Function, + IN UINT64 Param1, + IN UINT64 Param2 + ) +{ + EFI_STATUS Status; + IA32_DESCRIPTOR Idtr; + + // + // Idtr might be changed inside of FSP. 32bit FSP only knows the <4G address. + // If IDTR.Base is >4G, FSP can not handle. So we need save/restore IDTR here for X64 only. + // Interrupt is already disabled here, so it is safety to update IDTR. + // + AsmReadIdtr (&Idtr); + Status = AsmExecute32BitCode (Function, Param1, Param2, &mGdt); + AsmWriteIdtr (&Idtr); + + return Status; +} + diff --git a/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.S b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.S new file mode 100644 index 0000000..b6b5c1a --- /dev/null +++ b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.S @@ -0,0 +1,230 @@ +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# Module Name: +# +# Thunk64To32.asm +# +# Abstract: +# +# This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then +# transit back to long mode. +# +#------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Procedure: AsmExecute32BitCode +# +# Input: None +# +# Output: None +# +# Prototype: UINT32 +# AsmExecute32BitCode ( +# IN UINT64 Function, +# IN UINT64 Param1, +# IN UINT64 Param2, +# IN IA32_DESCRIPTOR *InternalGdtr +# ); +# +# +# Description: A thunk function to execute 32-bit code in long mode. +# +#---------------------------------------------------------------------------- + +ASM_GLOBAL ASM_PFX(AsmExecute32BitCode) +ASM_PFX(AsmExecute32BitCode): + # + # save IFLAG and disable it + # + pushfq + cli + + # + # save orignal GDTR and CS + # + movl %ds, %eax + push %rax + movl %cs, %eax + push %rax + subq $0x10, %rsp + sgdt (%rsp) + # + # load internal GDT + # + lgdt (%r9) + # + # Save general purpose register and rflag register + # + pushfq + push %rdi + push %rsi + push %rbp + push %rbx + + # + # save CR3 + # + movq %cr3, %rax + movq %rax, %rbp + + # + # Prepare the CS and return address for the transition from 32-bit to 64-bit mode + # + movq $0x10, %rax # load long mode selector + shl $32, %rax + lea ReloadCS(%rip), %r9 #Assume the ReloadCS is under 4G + orq %r9, %rax + push %rax + # + # Save parameters for 32-bit function call + # + movq %r8, %rax + shl $32, %rax + orq %rdx, %rax + push %rax + # + # save the 32-bit function entry and the return address into stack which will be + # retrieve in compatibility mode. + # + lea ReturnBack(%rip), %rax #Assume the ReloadCS is under 4G + shl $32, %rax + orq %rcx, %rax + push %rax + + # + # let rax save DS + # + movq $0x18, %rax + + # + # Change to Compatible Segment + # + movq $8, %rcx # load compatible mode selector + shl $32, %rcx + lea Compatible(%rip), %rdx # assume address < 4G + orq %rdx, %rcx + push %rcx + .byte 0xcb # retf + +Compatible: + # reload DS/ES/SS to make sure they are correct referred to current GDT + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + + # + # Disable paging + # + movq %cr0, %rcx + btc $31, %ecx + movq %rcx, %cr0 + # + # Clear EFER.LME + # + movl $0xC0000080, %ecx + rdmsr + btc $8, %eax + wrmsr + +# Now we are in protected mode + # + # Call 32-bit function. Assume the function entry address and parameter value is less than 4G + # + pop %rax # Here is the function entry + # + # Now the parameter is at the bottom of the stack, then call in to IA32 function. + # + jmp *%rax +ReturnBack: + movl %eax, %ebx # save return status + pop %rcx # drop param1 + pop %rcx # drop param2 + + # + # restore CR4 + # + movq %cr4, %rax + bts $5, %eax + movq %rax, %cr4 + + # + # restore CR3 + # + movl %ebp, %eax + movq %rax, %cr3 + + # + # Set EFER.LME to re-enable ia32-e + # + movl $0xC0000080, %ecx + rdmsr + bts $8, %eax + wrmsr + # + # Enable paging + # + movq %cr0, %rax + bts $31, %eax + mov %rax, %cr0 +# Now we are in compatible mode + + # + # Reload cs register + # + .byte 0xcb # retf +ReloadCS: + # + # Now we're in Long Mode + # + # + # Restore C register and eax hold the return status from 32-bit function. + # Note: Do not touch rax from now which hold the return value from IA32 function + # + movl %ebx, %eax # put return status to EAX + pop %rbx + pop %rbp + pop %rsi + pop %rdi + popfq + # + # Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor. + # + lgdt (%rsp) + # + # drop GDT descriptor in stack + # + addq $0x10, %rsp + # + # switch to orignal CS and GDTR + # + pop %r9 # get CS + shl $32, %r9 # rcx[32..47] <- Cs + lea ReturnToLongMode(%rip), %rcx + orq %r9, %rcx + push %rcx + .byte 0xcb # retf +ReturnToLongMode: + # + # Reload original DS/ES/SS + # + pop %rcx + movl %ecx, %ds + movl %ecx, %es + movl %ecx, %ss + + # + # Restore IFLAG + # + popfq + + ret + diff --git a/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.asm b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.asm new file mode 100644 index 0000000..70e7b5f --- /dev/null +++ b/IntelFspWrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.asm @@ -0,0 +1,230 @@ +; +; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; +; Module Name: +; +; Thunk64To32.asm +; +; Abstract: +; +; This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then +; transit back to long mode. +; +;------------------------------------------------------------------------------- + .code +;---------------------------------------------------------------------------- +; Procedure: AsmExecute32BitCode +; +; Input: None +; +; Output: None +; +; Prototype: UINT32 +; AsmExecute32BitCode ( +; IN UINT64 Function, +; IN UINT64 Param1, +; IN UINT64 Param2, +; IN IA32_DESCRIPTOR *InternalGdtr +; ); +; +; +; Description: A thunk function to execute 32-bit code in long mode. +; +;---------------------------------------------------------------------------- +AsmExecute32BitCode PROC + ; + ; save IFLAG and disable it + ; + pushfq + cli + + ; + ; save orignal GDTR and CS + ; + mov rax, ds + push rax + mov rax, cs + push rax + sub rsp, 10h + sgdt fword ptr [rsp] + ; + ; load internal GDT + ; + lgdt fword ptr [r9] + ; + ; Save general purpose register and rflag register + ; + pushfq + push rdi + push rsi + push rbp + push rbx + + ; + ; save CR3 + ; + mov rax, cr3 + mov rbp, rax + + ; + ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode + ; + mov rax, 10h ; load long mode selector + shl rax, 32 + mov r9, OFFSET ReloadCS ;Assume the ReloadCS is under 4G + or rax, r9 + push rax + ; + ; Save parameters for 32-bit function call + ; + mov rax, r8 + shl rax, 32 + or rax, rdx + push rax + ; + ; save the 32-bit function entry and the return address into stack which will be + ; retrieve in compatibility mode. + ; + mov rax, OFFSET ReturnBack ;Assume the ReloadCS is under 4G + shl rax, 32 + or rax, rcx + push rax + + ; + ; let rax save DS + ; + mov rax, 018h + + ; + ; Change to Compatible Segment + ; + mov rcx, 08h ; load compatible mode selector + shl rcx, 32 + mov rdx, OFFSET Compatible ; assume address < 4G + or rcx, rdx + push rcx + retf + +Compatible: + ; reload DS/ES/SS to make sure they are correct referred to current GDT + mov ds, ax + mov es, ax + mov ss, ax + + ; + ; Disable paging + ; + mov rcx, cr0 + btc ecx, 31 + mov cr0, rcx + ; + ; Clear EFER.LME + ; + mov ecx, 0C0000080h + rdmsr + btc eax, 8 + wrmsr + +; Now we are in protected mode + ; + ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G + ; + pop rax ; Here is the function entry + ; + ; Now the parameter is at the bottom of the stack, then call in to IA32 function. + ; + jmp rax +ReturnBack: + mov ebx, eax ; save return status + pop rcx ; drop param1 + pop rcx ; drop param2 + + ; + ; restore CR4 + ; + mov rax, cr4 + bts eax, 5 + mov cr4, rax + + ; + ; restore CR3 + ; + mov eax, ebp + mov cr3, rax + + ; + ; Set EFER.LME to re-enable ia32-e + ; + mov ecx, 0C0000080h + rdmsr + bts eax, 8 + wrmsr + ; + ; Enable paging + ; + mov rax, cr0 + bts eax, 31 + mov cr0, rax +; Now we are in compatible mode + + ; + ; Reload cs register + ; + retf +ReloadCS: + ; + ; Now we're in Long Mode + ; + ; + ; Restore C register and eax hold the return status from 32-bit function. + ; Note: Do not touch rax from now which hold the return value from IA32 function + ; + mov eax, ebx ; put return status to EAX + pop rbx + pop rbp + pop rsi + pop rdi + popfq + ; + ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor. + ; + lgdt fword ptr[rsp] + ; + ; drop GDT descriptor in stack + ; + add rsp, 10h + ; + ; switch to orignal CS and GDTR + ; + pop r9 ; get CS + shl r9, 32 ; rcx[32..47] <- Cs + mov rcx, OFFSET @F + or rcx, r9 + push rcx + retf +@@: + ; + ; Reload original DS/ES/SS + ; + pop rcx + mov ds, rcx + mov es, rcx + mov ss, rcx + + ; + ; Restore IFLAG + ; + popfq + + ret +AsmExecute32BitCode ENDP + + END -- 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

