mirror of https://github.com/acidanthera/audk.git
MdeModulePkg BootScriptExecutorDxe: Fix S3 failure When PcdUse1GPageTable defined as dynamic.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14896 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
fae736240c
commit
59cc677cf3
|
@ -4,7 +4,7 @@
|
||||||
# This is a standalone Boot Script Executor. Standalone means it does not
|
# This is a standalone Boot Script Executor. Standalone means it does not
|
||||||
# depends on any PEI or DXE service.
|
# depends on any PEI or DXE service.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||||
#
|
#
|
||||||
# This program and the accompanying materials are
|
# This program and the accompanying materials are
|
||||||
# licensed and made available under the terms and conditions of the BSD License
|
# licensed and made available under the terms and conditions of the BSD License
|
||||||
|
@ -75,6 +75,9 @@
|
||||||
gPerformanceProtocolGuid
|
gPerformanceProtocolGuid
|
||||||
gEfiEventExitBootServicesGuid
|
gEfiEventExitBootServicesGuid
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiDxeSmmReadyToLockProtocolGuid
|
||||||
|
|
||||||
[FeaturePcd]
|
[FeaturePcd]
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
|
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/** @file
|
/** @file
|
||||||
This is the code for Boot Script Executer module.
|
This is the code for Boot Script Executer module.
|
||||||
|
|
||||||
This driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory
|
This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
|
||||||
in the entry point. The functionality is to interpret and restore the S3 boot script
|
in the entry point. The functionality is to interpret and restore the S3 boot script
|
||||||
|
|
||||||
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
@ -22,6 +22,8 @@ EFI_GUID mBootScriptExecutorImageGuid = {
|
||||||
0x9a8d3433, 0x9fe8, 0x42b6, { 0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b }
|
0x9a8d3433, 0x9fe8, 0x42b6, { 0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BOOLEAN mPage1GSupport = FALSE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Entry function of Boot script exector. This function will be executed in
|
Entry function of Boot script exector. This function will be executed in
|
||||||
S3 boot path.
|
S3 boot path.
|
||||||
|
@ -205,6 +207,121 @@ S3BootScriptExecutorEntryFunction (
|
||||||
CpuDeadLoop();
|
CpuDeadLoop();
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This is the Event notification function to reload BootScriptExecutor image
|
||||||
|
to RESERVED mem and save it to LockBox.
|
||||||
|
|
||||||
|
@param Event Pointer to this event
|
||||||
|
@param Context Event hanlder private data
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ReadyToLockEventNotify (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
VOID *Interface;
|
||||||
|
UINT8 *Buffer;
|
||||||
|
UINTN BufferSize;
|
||||||
|
EFI_HANDLE NewImageHandle;
|
||||||
|
UINTN Pages;
|
||||||
|
EFI_PHYSICAL_ADDRESS FfsBuffer;
|
||||||
|
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
|
||||||
|
|
||||||
|
Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// A workaround: Here we install a dummy handle
|
||||||
|
//
|
||||||
|
NewImageHandle = NULL;
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&NewImageHandle,
|
||||||
|
&gEfiCallerIdGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reload BootScriptExecutor image itself to RESERVED mem
|
||||||
|
//
|
||||||
|
Status = GetSectionFromAnyFv (
|
||||||
|
&gEfiCallerIdGuid,
|
||||||
|
EFI_SECTION_PE32,
|
||||||
|
0,
|
||||||
|
(VOID **) &Buffer,
|
||||||
|
&BufferSize
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
ImageContext.Handle = Buffer;
|
||||||
|
ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
|
||||||
|
//
|
||||||
|
// Get information about the image being loaded
|
||||||
|
//
|
||||||
|
Status = PeCoffLoaderGetImageInfo (&ImageContext);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
Pages = EFI_SIZE_TO_PAGES(BufferSize + ImageContext.SectionAlignment);
|
||||||
|
FfsBuffer = 0xFFFFFFFF;
|
||||||
|
Status = gBS->AllocatePages (
|
||||||
|
AllocateMaxAddress,
|
||||||
|
EfiReservedMemoryType,
|
||||||
|
Pages,
|
||||||
|
&FfsBuffer
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
|
||||||
|
//
|
||||||
|
// Align buffer on section boundry
|
||||||
|
//
|
||||||
|
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
|
||||||
|
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
|
||||||
|
//
|
||||||
|
// Load the image to our new buffer
|
||||||
|
//
|
||||||
|
Status = PeCoffLoaderLoadImage (&ImageContext);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Relocate the image in our new buffer
|
||||||
|
//
|
||||||
|
Status = PeCoffLoaderRelocateImage (&ImageContext);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
|
||||||
|
//
|
||||||
|
gBS->FreePool (Buffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Flush the instruction cache so the image data is written before we execute it
|
||||||
|
//
|
||||||
|
InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
|
||||||
|
Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, gST);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Additional step for BootScript integrity
|
||||||
|
// Save BootScriptExecutor image
|
||||||
|
//
|
||||||
|
Status = SaveLockBox (
|
||||||
|
&mBootScriptExecutorImageGuid,
|
||||||
|
(VOID *)(UINTN)ImageContext.ImageAddress,
|
||||||
|
(UINTN)ImageContext.ImageSize
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
gBS->CloseEvent (Event);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Entrypoint of Boot script exector driver, this function will be executed in
|
Entrypoint of Boot script exector driver, this function will be executed in
|
||||||
normal boot phase and invoked by DXE dispatch.
|
normal boot phase and invoked by DXE dispatch.
|
||||||
|
@ -222,16 +339,16 @@ BootScriptExecutorEntryPoint (
|
||||||
IN EFI_SYSTEM_TABLE *SystemTable
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT8 *Buffer;
|
|
||||||
UINTN BufferSize;
|
UINTN BufferSize;
|
||||||
UINTN Pages;
|
UINTN Pages;
|
||||||
EFI_PHYSICAL_ADDRESS FfsBuffer;
|
|
||||||
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
|
|
||||||
BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
|
BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
|
||||||
EFI_PHYSICAL_ADDRESS BootScriptExecutorBuffer;
|
EFI_PHYSICAL_ADDRESS BootScriptExecutorBuffer;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
VOID *DevicePath;
|
VOID *DevicePath;
|
||||||
EFI_HANDLE NewImageHandle;
|
EFI_EVENT ReadyToLockEvent;
|
||||||
|
VOID *Registration;
|
||||||
|
UINT32 RegEax;
|
||||||
|
UINT32 RegEdx;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
|
// Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
|
||||||
|
@ -240,94 +357,32 @@ BootScriptExecutorEntryPoint (
|
||||||
//
|
//
|
||||||
Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
|
Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is the first-time loaded by DXE core. reload itself to RESERVED mem
|
// Create ReadyToLock event to reload BootScriptExecutor image
|
||||||
|
// to RESERVED mem and save it to LockBox.
|
||||||
//
|
//
|
||||||
//
|
ReadyToLockEvent = EfiCreateProtocolNotifyEvent (
|
||||||
// A workaround: Here we install a dummy handle
|
&gEfiDxeSmmReadyToLockProtocolGuid,
|
||||||
//
|
TPL_NOTIFY,
|
||||||
NewImageHandle = NULL;
|
ReadyToLockEventNotify,
|
||||||
Status = gBS->InstallProtocolInterface (
|
NULL,
|
||||||
&NewImageHandle,
|
&Registration
|
||||||
&gEfiCallerIdGuid,
|
);
|
||||||
EFI_NATIVE_INTERFACE,
|
ASSERT (ReadyToLockEvent != NULL);
|
||||||
NULL
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
Status = GetSectionFromAnyFv (
|
|
||||||
&gEfiCallerIdGuid,
|
|
||||||
EFI_SECTION_PE32,
|
|
||||||
0,
|
|
||||||
(VOID **) &Buffer,
|
|
||||||
&BufferSize
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
ImageContext.Handle = Buffer;
|
|
||||||
ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
|
|
||||||
//
|
|
||||||
// Get information about the image being loaded
|
|
||||||
//
|
|
||||||
Status = PeCoffLoaderGetImageInfo (&ImageContext);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
Pages = EFI_SIZE_TO_PAGES(BufferSize + ImageContext.SectionAlignment);
|
|
||||||
FfsBuffer = 0xFFFFFFFF;
|
|
||||||
Status = gBS->AllocatePages (
|
|
||||||
AllocateMaxAddress,
|
|
||||||
EfiReservedMemoryType,
|
|
||||||
Pages,
|
|
||||||
&FfsBuffer
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
|
|
||||||
//
|
|
||||||
// Align buffer on section boundry
|
|
||||||
//
|
|
||||||
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
|
|
||||||
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
|
|
||||||
//
|
|
||||||
// Load the image to our new buffer
|
|
||||||
//
|
|
||||||
Status = PeCoffLoaderLoadImage (&ImageContext);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Relocate the image in our new buffer
|
|
||||||
//
|
|
||||||
Status = PeCoffLoaderRelocateImage (&ImageContext);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
|
|
||||||
//
|
|
||||||
gBS->FreePool (Buffer);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Flush the instruction cache so the image data is written before we execute it
|
|
||||||
//
|
|
||||||
InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
|
|
||||||
Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Additional step for BootScript integrity
|
|
||||||
// Save BootScriptExecutor image
|
|
||||||
//
|
|
||||||
Status = SaveLockBox (
|
|
||||||
&mBootScriptExecutorImageGuid,
|
|
||||||
(VOID *)(UINTN)ImageContext.ImageAddress,
|
|
||||||
(UINTN)ImageContext.ImageSize
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// the entry point is invoked after reloading. following code only run in RESERVED mem
|
// the entry point is invoked after reloading. following code only run in RESERVED mem
|
||||||
//
|
//
|
||||||
|
if (PcdGetBool(PcdUse1GPageTable)) {
|
||||||
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000001) {
|
||||||
|
AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
|
||||||
|
if ((RegEdx & BIT26) != 0) {
|
||||||
|
mPage1GSupport = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
|
BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
|
||||||
|
|
||||||
BootScriptExecutorBuffer = 0xFFFFFFFF;
|
BootScriptExecutorBuffer = 0xFFFFFFFF;
|
||||||
|
@ -363,11 +418,8 @@ BootScriptExecutorEntryPoint (
|
||||||
|
|
||||||
Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
|
Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/** @file
|
/** @file
|
||||||
The header file for Boot Script Executer module.
|
The header file for Boot Script Executer module.
|
||||||
|
|
||||||
This driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory
|
This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
|
||||||
in the entry point. The functionality is to interpret and restore the S3 boot script
|
in the entry point. The functionality is to interpret and restore the S3 boot script
|
||||||
|
|
||||||
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
@ -39,7 +39,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
#include <Guid/AcpiS3Context.h>
|
#include <Guid/AcpiS3Context.h>
|
||||||
#include <Guid/BootScriptExecutorVariable.h>
|
#include <Guid/BootScriptExecutorVariable.h>
|
||||||
#include <Guid/EventGroup.h>
|
#include <Protocol/DxeSmmReadyToLock.h>
|
||||||
#include <IndustryStandard/Acpi.h>
|
#include <IndustryStandard/Acpi.h>
|
||||||
/**
|
/**
|
||||||
a ASM function to transfer control to OS.
|
a ASM function to transfer control to OS.
|
||||||
|
@ -83,5 +83,6 @@ SetIdtEntry (
|
||||||
|
|
||||||
extern UINT32 AsmFixAddress16;
|
extern UINT32 AsmFixAddress16;
|
||||||
extern UINT32 AsmJmpAddr32;
|
extern UINT32 AsmJmpAddr32;
|
||||||
|
extern BOOLEAN mPage1GSupport;
|
||||||
|
|
||||||
#endif //_BOOT_SCRIPT_EXECUTOR_H_
|
#endif //_BOOT_SCRIPT_EXECUTOR_H_
|
||||||
|
|
|
@ -21,7 +21,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#define IA32_PG_PS BIT7
|
#define IA32_PG_PS BIT7
|
||||||
|
|
||||||
UINT64 mPhyMask;
|
UINT64 mPhyMask;
|
||||||
BOOLEAN mPage1GSupport;
|
|
||||||
VOID *mOriginalHandler;
|
VOID *mOriginalHandler;
|
||||||
UINTN mS3NvsPageTableAddress;
|
UINTN mS3NvsPageTableAddress;
|
||||||
|
|
||||||
|
@ -47,23 +46,18 @@ HookPageFaultHandler (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT32 RegEax;
|
UINT32 RegEax;
|
||||||
UINT32 RegEdx;
|
UINT8 PhysicalAddressBits;
|
||||||
UINTN PageFaultHandlerHookAddress;
|
UINTN PageFaultHandlerHookAddress;
|
||||||
|
|
||||||
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
mPhyMask = LShiftU64 (1, (UINT8)RegEax) - 1;
|
if (RegEax >= 0x80000008) {
|
||||||
mPhyMask &= (1ull << 48) - SIZE_4KB;
|
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
||||||
|
PhysicalAddressBits = (UINT8) RegEax;
|
||||||
mPage1GSupport = FALSE;
|
} else {
|
||||||
if (PcdGetBool(PcdUse1GPageTable)) {
|
PhysicalAddressBits = 36;
|
||||||
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
|
||||||
if (RegEax >= 0x80000001) {
|
|
||||||
AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
|
|
||||||
if ((RegEdx & BIT26) != 0) {
|
|
||||||
mPage1GSupport = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
mPhyMask = LShiftU64 (1, PhysicalAddressBits) - 1;
|
||||||
|
mPhyMask &= (1ull << 48) - SIZE_4KB;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set Page Fault entry to catch >4G access
|
// Set Page Fault entry to catch >4G access
|
||||||
|
|
Loading…
Reference in New Issue