summaryrefslogtreecommitdiffstats
path: root/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib
diff options
context:
space:
mode:
authorJiewen Yao <jiewen.yao@intel.com>2016-05-13 13:00:53 +0800
committerJiewen Yao <jiewen.yao@intel.com>2016-05-13 13:00:53 +0800
commitcf1d454983fb4fd3b580a92bd242310467a5eaef (patch)
treec289db5c4533b6f6d824f2aad6f9fc1e00648bf6 /IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib
parentc9802c45647d84e71b4620fdfff0c4bd88cf5acb (diff)
downloadedk2-cf1d454983fb4fd3b580a92bd242310467a5eaef.tar.gz
edk2-cf1d454983fb4fd3b580a92bd242310467a5eaef.tar.bz2
edk2-cf1d454983fb4fd3b580a92bd242310467a5eaef.zip
Add IntelFsp2Pkg and IntelFsp2WrapperPkg.
Add FSP2.0 support. This series of patch is to support FSP2.0 specification at https://firmware.intel.com/sites/default/files/FSP_EAS_v2.0_Draft%20External.pdf Some major updates include: 1) One FSP binary is separated to multiple components: FSP-T, FSP-M, FSP-S, and optional FSP-O. Each component has its own configuration data region. 2) All FSP-APIs use same UPD format - FSP_UPD_HEADER. 3) Add EnumInitPhaseEndOfFirmware notifyphase. 4) FSP1.1/FSP1.0 compatibility is NOT maintained. 5) We also add rename Fsp* to FspWrapper* in IntelFsp2WrapperPkg, to indicate that it is for FspWrapper only. IntelFspPkg and IntelFspWrapperPkg will be deprecated. The new Intel platform will follow FSP2.0 and use IntelFsp2Pkg and IntelFsp2WrapperPkg. The old platform can still use IntelFspPkg and IntelFspWrapperPkg for compatibility consideration. Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com> Cc: Maurice Ma <maurice.ma@intel.com> Cc: Ravi P Rangarajan <ravi.p.rangarajan@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed-by: Giri P Mudusuru <giri.p.mudusuru@intel.com> Reviewed-by: Maurice Ma <maurice.ma@intel.com> Reviewed-by: Ravi P Rangarajan <ravi.p.rangarajan@intel.com>
Diffstat (limited to 'IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib')
-rw-r--r--IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf71
-rw-r--r--IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c203
-rw-r--r--IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c58
-rw-r--r--IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c108
-rw-r--r--IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.S230
-rw-r--r--IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.asm230
6 files changed, 900 insertions, 0 deletions
diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
new file mode 100644
index 0000000000..b1a9f38f4e
--- /dev/null
+++ b/IntelFsp2WrapperPkg/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 = F42C789F-4D66-49AF-8C73-1AADC00437AC
+ 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
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+ IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+
+[LibraryClasses]
+ BaseLib
+
+[Guids]
+ gFspHeaderFileGuid ## CONSUMES ## GUID
+
+[Pcd]
+ gFspWrapperTokenSpaceGuid.PcdFspmBaseAddress ## CONSUMES
+ gFspWrapperTokenSpaceGuid.PcdFspsBaseAddress ## CONSUMES
diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c
new file mode 100644
index 0000000000..8cf136fe1a
--- /dev/null
+++ b/IntelFsp2WrapperPkg/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 <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.
+ @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
+ );
+
+/**
+ 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] FspmUpdDataPtr Address pointer to the FSP_MEMORY_INIT_PARAMS structure.
+ @param[out] HobListPtr Address of the HobList pointer.
+
+ @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] 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] FspsUpdDataPtr 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/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c
new file mode 100644
index 0000000000..72b1762f4c
--- /dev/null
+++ b/IntelFsp2WrapperPkg/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 <FspEas.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/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c
new file mode 100644
index 0000000000..061d381c1b
--- /dev/null
+++ b/IntelFsp2WrapperPkg/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 <FspEas.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/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.S b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.S
new file mode 100644
index 0000000000..b6b5c1aca8
--- /dev/null
+++ b/IntelFsp2WrapperPkg/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/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.asm b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.asm
new file mode 100644
index 0000000000..70e7b5f408
--- /dev/null
+++ b/IntelFsp2WrapperPkg/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