#\r
# The following information is for reference only and not required by the build tools.\r
#\r
-# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+# VALID_ARCHITECTURES = IA32 X64\r
#\r
\r
[Sources]\r
ScriptSave.c\r
ScriptSave.h\r
\r
+[Sources.X64]\r
+ X64/AsmDispatchExecute.asm\r
+ X64/AsmDispatchExecute.S\r
+ X64/DispatchExecute.c\r
+\r
+[Sources.Ia32] \r
+ IA32/DispatchExecute.c\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
IntelFrameworkPkg/IntelFrameworkPkg.dec\r
MdeModulePkg/MdeModulePkg.dec\r
-\r
+ EdkCompatibilityPkg/EdkCompatibilityPkg.dec\r
\r
[LibraryClasses]\r
UefiBootServicesTableLib\r
+ UefiRuntimeServicesTableLib\r
UefiDriverEntryPoint\r
BaseMemoryLib\r
+ MemoryAllocationLib\r
DebugLib\r
BaseLib\r
+ PeCoffLib\r
+ PcdLib\r
+ DxeServicesLib\r
+ CacheMaintenanceLib\r
\r
[Protocols]\r
gEfiBootScriptSaveProtocolGuid ## PRODUCES\r
gEfiS3SaveStateProtocolGuid ## CONSUMES\r
\r
+[Pcd]\r
+ gEfiEdkCompatibilityPkgTokenSpaceGuid.BootScriptThunkDataPtr\r
\r
[Depex]\r
gEfiS3SaveStateProtocolGuid\r
--- /dev/null
+/** @file\r
+ Execute 32-bit code in Long Mode\r
+ Provide a thunk function to transition from long mode to compatibility mode to execute 32-bit code and then transit\r
+ back to long mode.\r
+ \r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "ScriptSave.h"\r
+/**\r
+ Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to\r
+ long mode.\r
+ \r
+ @param Function The 32bit code entry to be executed.\r
+ @param Param1 The first parameter to pass to 32bit code\r
+ @param Param2 The second parameter to pass to 32bit code\r
+ @retval EFI_SUCCESS Execute 32bit code successfully.\r
+ @retval other Something wrong when execute the 32bit code \r
+ \r
+**/ \r
+EFI_STATUS\r
+Execute32BitCode (\r
+ IN UINT64 Function,\r
+ IN UINT64 Param1,\r
+ IN UINT64 Param2\r
+ )\r
+{\r
+ DISPATCH_ENTRYPOINT_FUNC EntryFunc;\r
+ EFI_STATUS Status;\r
+\r
+ EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (Function);\r
+ Status = EntryFunc ((VOID *)(UINTN)Param1, (VOID *)(UINTN)Param2);\r
+\r
+ return Status;\r
+}\r
+\r
BootScriptCloseTable\r
};\r
EFI_S3_SAVE_STATE_PROTOCOL *mS3SaveState;\r
+\r
+/**\r
+ Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to\r
+ long mode.\r
+ \r
+ @param Function The 32bit code entry to be executed.\r
+ @param Param1 The first parameter to pass to 32bit code\r
+ @param Param2 The second parameter to pass to 32bit code\r
+ @retval EFI_SUCCESS Execute 32bit code successfully.\r
+ @retval other Something wrong when execute the 32bit code \r
+ \r
+**/ \r
+EFI_STATUS\r
+Execute32BitCode (\r
+ IN UINT64 Function,\r
+ IN UINT64 Param1,\r
+ IN UINT64 Param2\r
+ );\r
+\r
+/**\r
+ A stub to convert framework boot script dispatch to PI boot script dispatch.\r
+ \r
+ @param ImageHandle It should be is NULL.\r
+ @param Context The first parameter to pass to 32bit code\r
+\r
+ @return dispatch value.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+FrameworkBootScriptDispatchStub (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ DISPATCH_ENTRYPOINT_FUNC EntryFunc;\r
+ VOID *PeiServices;\r
+ IA32_DESCRIPTOR Idtr;\r
+\r
+ DEBUG ((EFI_D_ERROR, "FrameworkBootScriptDispatchStub - 0x%08x\n", (UINTN)Context));\r
+\r
+ EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (Context);\r
+ AsmReadIdtr (&Idtr);\r
+ PeiServices = (VOID *)(UINTN)(*(UINT32 *)(Idtr.Base - sizeof (UINT32)));\r
+\r
+ //\r
+ // ECP assumes first parameter is NULL, and second parameter is PeiServices.\r
+ //\r
+ Status = Execute32BitCode ((UINT64)(UINTN)EntryFunc, 0, (UINT64)(UINTN)PeiServices);\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Internal function to add IO write opcode to the table.\r
\r
);\r
}\r
\r
+/**\r
+ Internal function to add Save jmp address according to DISPATCH_OPCODE. \r
+ We ignore "Context" parameter.\r
+ We need create thunk stub to convert PEI entrypoint (used in Framework version)\r
+ to DXE entrypoint (defined in PI spec).\r
+\r
+ @param Marker The variable argument list to get the opcode\r
+ and associated attributes.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.\r
+ @retval EFI_SUCCESS Opcode is added.\r
+\r
+**/\r
+EFI_STATUS\r
+FrameworkBootScriptDispatch (\r
+ IN VA_LIST Marker\r
+ )\r
+{\r
+ VOID *EntryPoint;\r
+ VOID *Context;\r
+\r
+ EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);\r
+\r
+ //\r
+ // Register callback\r
+ //\r
+ Context = EntryPoint;\r
+ EntryPoint = (VOID *)(UINTN)FrameworkBootScriptDispatchStub;\r
+ return mS3SaveState->Write (\r
+ mS3SaveState,\r
+ EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE,\r
+ EntryPoint,\r
+ Context\r
+ );\r
+}\r
+\r
/**\r
Internal function to add memory pool operation to the table. \r
\r
VA_LIST Marker;\r
\r
if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) {\r
- //\r
- // Only S3 boot script is supported for now\r
- //\r
+ //\r
+ // Only S3 boot script is supported for now\r
+ //\r
return EFI_OUT_OF_RESOURCES;\r
}\r
//\r
\r
case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:\r
VA_START (Marker, OpCode);\r
- Status = BootScriptDispatch (Marker);\r
+ Status = FrameworkBootScriptDispatch (Marker);\r
VA_END (Marker);\r
break;\r
\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
+ UINT8 *Buffer;\r
+ UINTN BufferSize;\r
+ VOID *FfsBuffer;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+ BOOT_SCRIPT_THUNK_DATA *BootScriptThunkData;\r
+ EFI_STATUS Status;\r
+ VOID *DevicePath;\r
+\r
//\r
- // Locate and cache PI S3 Save State Protocol.\r
+ // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry\r
+ // point is loaded by DXE code which is the first time loaded. or else, it is already\r
+ // be reloaded be itself.This is a work-around\r
//\r
- Status = gBS->LocateProtocol (\r
- &gEfiS3SaveStateProtocolGuid, \r
- NULL, \r
- (VOID **) &mS3SaveState\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // This is the first-time loaded by DXE core. reload itself to NVS mem\r
+ //\r
+ //\r
+ // A workarouond: Here we install a dummy handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &ImageHandle,\r
+ &gEfiCallerIdGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ DevicePath\r
+ );\r
+\r
+ Status = GetSectionFromAnyFv (\r
+ &gEfiCallerIdGuid,\r
+ EFI_SECTION_PE32,\r
+ 0,\r
+ (VOID **) &Buffer,\r
+ &BufferSize\r
+ );\r
+ ImageContext.Handle = Buffer;\r
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
+ //\r
+ // Get information about the image being loaded\r
+ //\r
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = gBS->AllocatePool (\r
+ EfiACPIMemoryNVS,\r
+ BufferSize + ImageContext.SectionAlignment,\r
+ &FfsBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;\r
+ //\r
+ // Align buffer on section boundry\r
+ //\r
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
+ ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);\r
+ //\r
+ // Load the image to our new buffer\r
+ //\r
+ Status = PeCoffLoaderLoadImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (FfsBuffer);\r
+ return Status;\r
+ }\r
\r
- return gBS->InstallProtocolInterface (\r
+ //\r
+ // Relocate the image in our new buffer\r
+ //\r
+ Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ PeCoffLoaderUnloadImage (&ImageContext);\r
+ gBS->FreePool (FfsBuffer);\r
+ return Status;\r
+ }\r
+ //\r
+ // Flush the instruction cache so the image data is written before we execute it\r
+ //\r
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+ Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) ((EFI_HANDLE)(UINTN)(ImageContext.ImageAddress), SystemTable);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (FfsBuffer);\r
+ return Status;\r
+ }\r
+ //\r
+ // Additional step for BootScriptThunk integrity\r
+ //\r
+\r
+ //\r
+ // Allocate BootScriptThunkData\r
+ //\r
+ BootScriptThunkData = AllocatePool (sizeof (BOOT_SCRIPT_THUNK_DATA));\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ BootScriptThunkData->BootScriptThunkBase = ImageContext.ImageAddress;\r
+ BootScriptThunkData->BootScriptThunkLength = ImageContext.ImageSize;\r
+ //\r
+ // Set BootScriptThunkData\r
+ //\r
+ PcdSet64 (BootScriptThunkDataPtr, (UINT64)(UINTN)BootScriptThunkData); \r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // the entry point is invoked after reloading. following code only run in ACPI NVS\r
+ //\r
+\r
+ //\r
+ // Locate and cache PI S3 Save State Protocol.\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiS3SaveStateProtocolGuid, \r
+ NULL, \r
+ (VOID **) &mS3SaveState\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return gBS->InstallProtocolInterface (\r
&mHandle,\r
&gEfiBootScriptSaveProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
&mS3ScriptSave\r
);\r
-\r
+ }\r
}\r
\r
\r
#include <Library/BaseLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
#include <Library/SmbusLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+#include <Library/CacheMaintenanceLib.h>\r
+\r
+#include <Guid/BootScriptThunkData.h>\r
+\r
#include <IndustryStandard/SmBus.h>\r
\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *DISPATCH_ENTRYPOINT_FUNC) (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN VOID *Context\r
+ );\r
+\r
/**\r
Adds a record into a specified Framework boot script table.\r
\r
--- /dev/null
+#\r
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+# Module Name:\r
+# \r
+# AsmDispatchExecute.asm\r
+#\r
+# Abstract:\r
+# \r
+# This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then \r
+# transit back to long mode.\r
+#\r
+#------------------------------------------------------------------------------- \r
+\r
+#----------------------------------------------------------------------------\r
+# Procedure: AsmExecute32BitCode\r
+#\r
+# Input: None\r
+#\r
+# Output: None\r
+#\r
+# Prototype: EFI_STATUS\r
+# AsmExecute32BitCode (\r
+# IN UINT64 Function,\r
+# IN UINT64 Param1,\r
+# IN UINT64 Param2,\r
+# IN IA32_DESCRIPTOR *InternalGdtr\r
+# );\r
+#\r
+#\r
+# Description: A thunk function to execute 32-bit code in long mode. \r
+#\r
+#----------------------------------------------------------------------------\r
+\r
+ASM_GLOBAL ASM_PFX(AsmExecute32BitCode)\r
+ASM_PFX(AsmExecute32BitCode):\r
+ #\r
+ # save orignal GDTR and CS\r
+ #\r
+ movq %ds, %rax\r
+ push %rax\r
+ movq %cs, %rax\r
+ push %rax\r
+ subq $0x10, %rsp\r
+ sgdt (%rsp)\r
+ #\r
+ # load internal GDT\r
+ #\r
+ lgdt (%r9)\r
+ #\r
+ # Save general purpose register and rflag register\r
+ #\r
+ pushfq \r
+ push %rdi\r
+ push %rsi\r
+ push %rbp\r
+ push %rbx\r
+ \r
+ #\r
+ # save CR3\r
+ #\r
+ movq %cr3, %rax\r
+ movq %rax, %rbp\r
+\r
+ #\r
+ # Prepare the CS and return address for the transition from 32-bit to 64-bit mode \r
+ # \r
+ movq $0x10, %rax # load long mode selector \r
+ shl $32, %rax\r
+ lea ReloadCS(%rip), %r9 #Assume the ReloadCS is under 4G\r
+ orq %r9, %rax\r
+ push %rax\r
+ #\r
+ # Save parameters for 32-bit function call\r
+ # \r
+ movq %r8, %rax\r
+ shl $32, %rax\r
+ orq %rdx, %rax\r
+ push %rax\r
+ #\r
+ # save the 32-bit function entry and the return address into stack which will be \r
+ # retrieve in compatibility mode.\r
+ #\r
+ lea ReturnBack(%rip), %rax #Assume the ReloadCS is under 4G \r
+ shl $32, %rax\r
+ orq %rcx, %rax\r
+ push %rax\r
+ \r
+ #\r
+ # let rax save DS\r
+ #\r
+ movq $0x18, %rax\r
+\r
+ #\r
+ # Change to Compatible Segment\r
+ #\r
+ movq $8, %rcx # load compatible mode selector \r
+ shl $32, %rcx\r
+ lea Compatible(%rip), %rdx # assume address < 4G\r
+ orq %rdx, %rcx\r
+ push %rcx\r
+ retf\r
+\r
+Compatible:\r
+ # reload DS/ES/SS to make sure they are correct referred to current GDT\r
+ movs %ax, %ds\r
+ movs %ax, %es\r
+ movs %ax, %ss\r
+\r
+ #\r
+ # Disable paging\r
+ #\r
+ movq %cr0, %rcx\r
+ btc $31, %ecx\r
+ movq %rcx, %cr0\r
+ #\r
+ # Clear EFER.LME\r
+ #\r
+ movl $0xC0000080, %ecx\r
+ rdmsr\r
+ btc $8, %eax\r
+ wrmsr\r
+\r
+# Now we are in protected mode\r
+ #\r
+ # Call 32-bit function. Assume the function entry address and parameter value is less than 4G\r
+ # \r
+ pop %rax # Here is the function entry\r
+ # \r
+ # Now the parameter is at the bottom of the stack, then call in to IA32 function.\r
+ #\r
+ jmp *%rax\r
+ReturnBack: \r
+ pop %rcx # drop param1 \r
+ pop %rcx # drop param2 \r
+\r
+ #\r
+ # restore CR4\r
+ #\r
+ movq %cr4, %rax\r
+ bts $5, %eax\r
+ movq %rax, %cr4\r
+\r
+ #\r
+ # restore CR3\r
+ #\r
+ movl %ebp, %eax\r
+ movq %rax, %cr3\r
+\r
+ #\r
+ # Set EFER.LME to re-enable ia32-e\r
+ #\r
+ movl $0xC0000080, %ecx\r
+ rdmsr\r
+ bts $8, %eax\r
+ wrmsr\r
+ #\r
+ # Enable paging\r
+ #\r
+ movq %cr0, %rax\r
+ bts $31, %eax\r
+ mov %rax, %cr0\r
+# Now we are in compatible mode\r
+\r
+ #\r
+ # Reload cs register \r
+ # \r
+ retf\r
+ReloadCS: \r
+ #\r
+ # Now we're in Long Mode\r
+ #\r
+ #\r
+ # Restore C register and eax hold the return status from 32-bit function.\r
+ # Note: Do not touch rax from now which hold the return value from IA32 function\r
+ #\r
+ pop %rbx\r
+ pop %rbp\r
+ pop %rsi\r
+ pop %rdi\r
+ popfq\r
+ #\r
+ # Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.\r
+ #\r
+ lgdt (%rsp)\r
+ #\r
+ # drop GDT descriptor in stack\r
+ #\r
+ addq $0x10, %rsp\r
+ #\r
+ # switch to orignal CS and GDTR\r
+ #\r
+ pop %r9 # get CS\r
+ shl $32, %r9 # rcx[32..47] <- Cs \r
+ lea @F(%rip), %rcx\r
+ orq %r9, %rcx\r
+ push %rcx\r
+ retf\r
+@@: \r
+ #\r
+ # Reload original DS/ES/SS\r
+ #\r
+ pop %rcx\r
+ movq %rcx, %ds\r
+ movq %rcx, %es\r
+ movq %rcx, %ss\r
+ ret\r
+\r
--- /dev/null
+;\r
+; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution. The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+;\r
+; Module Name:\r
+; \r
+; AsmDispatchExecute.asm\r
+;\r
+; Abstract:\r
+; \r
+; This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then \r
+; transit back to long mode.\r
+;\r
+;------------------------------------------------------------------------------- \r
+ .code\r
+;----------------------------------------------------------------------------\r
+; Procedure: AsmExecute32BitCode\r
+;\r
+; Input: None\r
+;\r
+; Output: None\r
+;\r
+; Prototype: EFI_STATUS\r
+; AsmExecute32BitCode (\r
+; IN UINT64 Function,\r
+; IN UINT64 Param1,\r
+; IN UINT64 Param2,\r
+; IN IA32_DESCRIPTOR *InternalGdtr\r
+; );\r
+;\r
+;\r
+; Description: A thunk function to execute 32-bit code in long mode. \r
+;\r
+;----------------------------------------------------------------------------\r
+AsmExecute32BitCode PROC \r
+ ;\r
+ ; save orignal GDTR and CS\r
+ ;\r
+ mov rax, ds\r
+ push rax\r
+ mov rax, cs\r
+ push rax\r
+ sub rsp, 10h\r
+ sgdt fword ptr [rsp]\r
+ ;\r
+ ; load internal GDT\r
+ ;\r
+ lgdt fword ptr [r9]\r
+ ;\r
+ ; Save general purpose register and rflag register\r
+ ;\r
+ pushfq \r
+ push rdi\r
+ push rsi\r
+ push rbp\r
+ push rbx\r
+ \r
+ ;\r
+ ; save CR3\r
+ ;\r
+ mov rax, cr3\r
+ mov rbp, rax\r
+\r
+ ;\r
+ ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode \r
+ ; \r
+ mov rax, 10h ; load long mode selector \r
+ shl rax, 32\r
+ mov r9, OFFSET ReloadCS ;Assume the ReloadCS is under 4G\r
+ or rax, r9\r
+ push rax\r
+ ;\r
+ ; Save parameters for 32-bit function call\r
+ ; \r
+ mov rax, r8\r
+ shl rax, 32\r
+ or rax, rdx\r
+ push rax\r
+ ;\r
+ ; save the 32-bit function entry and the return address into stack which will be \r
+ ; retrieve in compatibility mode.\r
+ ;\r
+ mov rax, OFFSET ReturnBack ;Assume the ReloadCS is under 4G \r
+ shl rax, 32\r
+ or rax, rcx\r
+ push rax\r
+ \r
+ ;\r
+ ; let rax save DS\r
+ ;\r
+ mov rax, 018h\r
+\r
+ ;\r
+ ; Change to Compatible Segment\r
+ ;\r
+ mov rcx, 08h ; load compatible mode selector \r
+ shl rcx, 32\r
+ mov rdx, OFFSET Compatible ; assume address < 4G\r
+ or rcx, rdx\r
+ push rcx\r
+ retf\r
+\r
+Compatible:\r
+ ; reload DS/ES/SS to make sure they are correct referred to current GDT\r
+ mov ds, ax\r
+ mov es, ax\r
+ mov ss, ax\r
+\r
+ ;\r
+ ; Disable paging\r
+ ;\r
+ mov rcx, cr0\r
+ btc ecx, 31\r
+ mov cr0, rcx\r
+ ;\r
+ ; Clear EFER.LME\r
+ ;\r
+ mov ecx, 0C0000080h\r
+ rdmsr\r
+ btc eax, 8\r
+ wrmsr\r
+\r
+; Now we are in protected mode\r
+ ;\r
+ ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G\r
+ ; \r
+ pop rax ; Here is the function entry\r
+ ; \r
+ ; Now the parameter is at the bottom of the stack, then call in to IA32 function.\r
+ ;\r
+ jmp rax\r
+ReturnBack:\r
+ pop rcx ; drop param1 \r
+ pop rcx ; drop param2 \r
+\r
+ ;\r
+ ; restore CR4\r
+ ;\r
+ mov rax, cr4\r
+ bts eax, 5\r
+ mov cr4, rax\r
+\r
+ ;\r
+ ; restore CR3\r
+ ;\r
+ mov eax, ebp\r
+ mov cr3, rax\r
+\r
+ ;\r
+ ; Set EFER.LME to re-enable ia32-e\r
+ ;\r
+ mov ecx, 0C0000080h\r
+ rdmsr\r
+ bts eax, 8\r
+ wrmsr\r
+ ;\r
+ ; Enable paging\r
+ ;\r
+ mov rax, cr0\r
+ bts eax, 31\r
+ mov cr0, rax\r
+; Now we are in compatible mode\r
+\r
+ ;\r
+ ; Reload cs register \r
+ ; \r
+ retf\r
+ReloadCS: \r
+ ;\r
+ ; Now we're in Long Mode\r
+ ;\r
+ ;\r
+ ; Restore C register and eax hold the return status from 32-bit function.\r
+ ; Note: Do not touch rax from now which hold the return value from IA32 function\r
+ ;\r
+ pop rbx\r
+ pop rbp\r
+ pop rsi\r
+ pop rdi\r
+ popfq\r
+ ;\r
+ ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.\r
+ ;\r
+ lgdt fword ptr[rsp]\r
+ ;\r
+ ; drop GDT descriptor in stack\r
+ ;\r
+ add rsp, 10h \r
+ ;\r
+ ; switch to orignal CS and GDTR\r
+ ;\r
+ pop r9 ; get CS\r
+ shl r9, 32 ; rcx[32..47] <- Cs \r
+ mov rcx, OFFSET @F \r
+ or rcx, r9\r
+ push rcx\r
+ retf\r
+@@: \r
+ ;\r
+ ; Reload original DS/ES/SS\r
+ ;\r
+ pop rcx\r
+ mov ds, rcx\r
+ mov es, rcx\r
+ mov ss, rcx\r
+ ret\r
+AsmExecute32BitCode ENDP\r
+\r
+ END\r
--- /dev/null
+/** @file\r
+ Execute 32-bit code in Long Mode\r
+ Provide a thunk function to transition from long mode to compatibility mode to execute 32-bit code and then transit\r
+ back to long mode.\r
+ \r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "ScriptSave.h"\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+ struct {\r
+ UINT32 LimitLow : 16;\r
+ UINT32 BaseLow : 16;\r
+ UINT32 BaseMid : 8;\r
+ UINT32 Type : 4;\r
+ UINT32 System : 1;\r
+ UINT32 Dpl : 2;\r
+ UINT32 Present : 1;\r
+ UINT32 LimitHigh : 4;\r
+ UINT32 Software : 1;\r
+ UINT32 Reserved : 1;\r
+ UINT32 DefaultSize : 1;\r
+ UINT32 Granularity : 1;\r
+ UINT32 BaseHigh : 8;\r
+ } Bits;\r
+ UINT64 Uint64;\r
+} IA32_GDT;\r
+#pragma pack()\r
+\r
+//\r
+// Global Descriptor Table (GDT)\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {\r
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x0: reserve */\r
+ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x8: compatibility mode */\r
+ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}}, /* 0x10: for long mode */\r
+ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x18: data */\r
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x20: reserve */\r
+};\r
+\r
+//\r
+// IA32 Gdt register\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {\r
+ sizeof (mGdtEntries) - 1,\r
+ (UINTN) mGdtEntries\r
+ };\r
+/**\r
+ Assembly function to transition from long mode to compatibility mode to execute 32-bit code and then transit back to\r
+ long mode.\r
+ @param Function The 32bit code entry to be executed.\r
+ @param Param1 The first parameter to pass to 32bit code\r
+ @param Param2 The second parameter to pass to 32bit code\r
+ @param InternalGdtr The GDT and GDT descriptor used by this library\r
+ \r
+ @retval EFI_SUCCESS Execute 32bit code successfully.\r
+ @retval other Something wrong when execute the 32bit code \r
+**/\r
+EFI_STATUS\r
+AsmExecute32BitCode (\r
+ IN UINT64 Function,\r
+ IN UINT64 Param1,\r
+ IN UINT64 Param2,\r
+ IN IA32_DESCRIPTOR *InternalGdtr\r
+ );\r
+ \r
+/**\r
+ Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to\r
+ long mode.\r
+ \r
+ @param Function The 32bit code entry to be executed.\r
+ @param Param1 The first parameter to pass to 32bit code\r
+ @param Param2 The second parameter to pass to 32bit code\r
+ @retval EFI_SUCCESS Execute 32bit code successfully.\r
+ @retval other Something wrong when execute the 32bit code \r
+ \r
+**/ \r
+EFI_STATUS\r
+Execute32BitCode (\r
+ IN UINT64 Function,\r
+ IN UINT64 Param1,\r
+ IN UINT64 Param2\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ \r
+ ASSERT (Function != 0);\r
+ \r
+ Status = AsmExecute32BitCode (\r
+ Function,\r
+ Param1,\r
+ Param2,\r
+ &mGdt\r
+ );\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Define Name, GUID and data format for an EFI PCD that is used to save the image base and size\r
+ of a code segment which will be loaded and executed by a boot script thunk on S3 boot path.\r
+\r
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php.\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BOOT_SCRIPT_THUNK_VARIABLE_H_\r
+#define _BOOT_SCRIPT_THUNK_VARIABLE_H_\r
+\r
+//\r
+// The following structure boosts performance by combining structure all ACPI related variables into one.\r
+//\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+ EFI_PHYSICAL_ADDRESS BootScriptThunkBase;\r
+ EFI_PHYSICAL_ADDRESS BootScriptThunkLength;\r
+} BOOT_SCRIPT_THUNK_DATA;\r
+\r
+#pragma pack()\r
+\r
+#endif\r
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf\r
DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf\r
LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf\r
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
\r
[LibraryClasses.common.PEIM]\r
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf\r
EdkCompatibilityPkg/Compatibility/LegacyRegion2OnLegacyRegionThunk/LegacyRegion2OnLegacyRegionThunk.inf\r
EdkCompatibilityPkg/Compatibility/PiSmbiosRecordOnDataHubSmbiosRecordThunk/PiSmbiosRecordOnDataHubSmbiosRecordThunk.inf\r
EdkCompatibilityPkg/Compatibility/CpuIo2OnCpuIoThunk/CpuIo2OnCpuIoThunk.inf\r
- EdkCompatibilityPkg/Compatibility/BootScriptSaveOnS3SaveStateThunk/BootScriptSaveOnS3SaveStateThunk.inf\r
\r
#\r
# User needs to turn on the compatibility switches for VFRC and EDK II build tool for Framework HII modules \r
EdkCompatibilityPkg/Compatibility/SmmControl2OnSmmControlThunk/SmmControl2OnSmmControlThunk.inf\r
EdkCompatibilityPkg/Compatibility/PiSmmStatusCodeOnFrameworkSmmStatusCodeThunk/PiSmmStatusCodeOnFrameworkSmmStatusCodeThunk.inf\r
EdkCompatibilityPkg/Compatibility/FrameworkSmmStatusCodeOnPiSmmStatusCodeThunk/FrameworkSmmStatusCodeOnPiSmmStatusCodeThunk.inf\r
+ EdkCompatibilityPkg/Compatibility/BootScriptSaveOnS3SaveStateThunk/BootScriptSaveOnS3SaveStateThunk.inf\r
\r
[Components.IPF]\r
EdkCompatibilityPkg/Foundation/Cpu/Itanium/CpuIa64Lib/CpuIA64Lib.inf\r