IntelFrameworkModulePkg: Add AcpiS3SaveDxe driver

Signed-off-by: jljusten
Reviewed-by: rsun3

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12246 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jljusten 2011-08-31 18:57:46 +00:00
parent c0d494b5a7
commit 13d4af68f8
5 changed files with 875 additions and 0 deletions

View File

@ -81,6 +81,9 @@
PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
[LibraryClasses.common.DXE_DRIVER]
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
@ -160,6 +163,9 @@
IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf
IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf
[Components.IA32,Components.X64]
IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf
[Components.IA32,Components.X64,Components.IPF]
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf

View File

@ -0,0 +1,485 @@
/** @file
This is an implementation of the ACPI S3 Save protocol. This is defined in
S3 boot path specification 0.9.
Copyright (c) 2006 - 2011, 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 <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/LockBoxLib.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <Guid/AcpiVariableCompatibility.h>
#include <Guid/AcpiS3Context.h>
#include <Guid/Acpi.h>
#include <Protocol/AcpiS3Save.h>
#include <IndustryStandard/Acpi.h>
#include "AcpiS3Save.h"
/**
Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.
**/
VOID
InstallAcpiS3SaveThunk (
VOID
);
/**
Hook point for AcpiVariableThunkPlatform for S3Ready.
@param AcpiS3Context ACPI s3 context
**/
VOID
S3ReadyThunkPlatform (
IN ACPI_S3_CONTEXT *AcpiS3Context
);
UINTN mLegacyRegionSize;
EFI_ACPI_S3_SAVE_PROTOCOL mS3Save = {
LegacyGetS3MemorySize,
S3Ready,
};
EFI_GUID mAcpiS3IdtrProfileGuid = {
0xdea652b0, 0xd587, 0x4c54, 0xb5, 0xb4, 0xc6, 0x82, 0xe7, 0xa0, 0xaa, 0x3d
};
/**
Allocate EfiACPIMemoryNVS below 4G memory address.
This function allocates EfiACPIMemoryNVS below 4G memory address.
@param Size Size of memory to allocate.
@return Allocated address for output.
**/
VOID*
AllocateAcpiNvsMemoryBelow4G (
IN UINTN Size
)
{
UINTN Pages;
EFI_PHYSICAL_ADDRESS Address;
EFI_STATUS Status;
VOID* Buffer;
Pages = EFI_SIZE_TO_PAGES (Size);
Address = 0xffffffff;
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiACPIMemoryNVS,
Pages,
&Address
);
ASSERT_EFI_ERROR (Status);
Buffer = (VOID *) (UINTN) Address;
ZeroMem (Buffer, Size);
return Buffer;
}
/**
To find Facs in Acpi tables.
To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored
in the table.
@param AcpiTableGuid The guid used to find ACPI table in UEFI ConfigurationTable.
@return Facs table pointer.
**/
EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *
FindAcpiFacsTableByAcpiGuid (
IN EFI_GUID *AcpiTableGuid
)
{
EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
UINTN Index;
UINT32 Data32;
Rsdp = NULL;
Rsdt = NULL;
Fadt = NULL;
//
// found ACPI table RSD_PTR from system table
//
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), AcpiTableGuid)) {
//
// A match was found.
//
Rsdp = gST->ConfigurationTable[Index].VendorTable;
break;
}
}
if (Rsdp == NULL) {
return NULL;
}
Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress;
if (Rsdt == NULL || Rsdt->Signature != EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
return NULL;
}
for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Rsdt->Length; Index = Index + sizeof (UINT32)) {
Data32 = *(UINT32 *) ((UINT8 *) Rsdt + Index);
Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) (UINT32 *) (UINTN) Data32;
if (Fadt->Header.Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
break;
}
}
if (Fadt == NULL || Fadt->Header.Signature != EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
return NULL;
}
Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl;
return Facs;
}
/**
To find Facs in Acpi tables.
To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored
in the table.
@return Facs table pointer.
**/
EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *
FindAcpiFacsTable (
VOID
)
{
EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
Facs = FindAcpiFacsTableByAcpiGuid (&gEfiAcpi20TableGuid);
if (Facs != NULL) {
return Facs;
}
return FindAcpiFacsTableByAcpiGuid (&gEfiAcpi10TableGuid);
}
/**
Allocates and fills in the Page Directory and Page Table Entries to
establish a 1:1 Virtual to Physical mapping.
If BootScriptExector driver will run in 64-bit mode, this function will establish the 1:1
virtual to physical mapping page table.
If BootScriptExector driver will not run in 64-bit mode, this function will do nothing.
@return the 1:1 Virtual to Physical identity mapping page table base address.
**/
EFI_PHYSICAL_ADDRESS
S3CreateIdentityMappingPageTables (
VOID
)
{
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
UINT32 RegEax;
UINT8 PhysicalAddressBits;
EFI_PHYSICAL_ADDRESS PageAddress;
UINTN IndexOfPml4Entries;
UINTN IndexOfPdpEntries;
UINTN IndexOfPageDirectoryEntries;
UINTN NumberOfPml4EntriesNeeded;
UINTN NumberOfPdpEntriesNeeded;
PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
PAGE_TABLE_ENTRY *PageDirectoryEntry;
EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress;
UINTN TotalPageTableSize;
//
// Get physical address bits supported.
//
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
if (RegEax >= 0x80000008) {
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
PhysicalAddressBits = (UINT8) RegEax;
} else {
PhysicalAddressBits = 36;
}
//
// Calculate the table entries needed.
//
if (PhysicalAddressBits <= 39 ) {
NumberOfPml4EntriesNeeded = 1;
NumberOfPdpEntriesNeeded = (UINTN)LShiftU64 (1, (PhysicalAddressBits - 30));
} else {
NumberOfPml4EntriesNeeded = (UINTN)LShiftU64 (1, (PhysicalAddressBits - 39));
NumberOfPdpEntriesNeeded = 512;
}
//
// We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs.
//
TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded);
DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize));
//
// By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.
//
S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateAcpiNvsMemoryBelow4G (EFI_PAGES_TO_SIZE(TotalPageTableSize));
ASSERT (S3NvsPageTableAddress != 0);
PageMap = (PAGE_MAP_AND_DIRECTORY_POINTER *)(UINTN)S3NvsPageTableAddress;
S3NvsPageTableAddress += SIZE_4KB;
PageMapLevel4Entry = PageMap;
PageAddress = 0;
for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {
//
// Each PML4 entry points to a page of Page Directory Pointer entires.
// So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
//
PageDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER *)(UINTN)S3NvsPageTableAddress;
S3NvsPageTableAddress += SIZE_4KB;
//
// Make a PML4 Entry
//
PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
PageMapLevel4Entry->Bits.ReadWrite = 1;
PageMapLevel4Entry->Bits.Present = 1;
for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
//
// Each Directory Pointer entries points to a page of Page Directory entires.
// So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
//
PageDirectoryEntry = (PAGE_TABLE_ENTRY *)(UINTN)S3NvsPageTableAddress;
S3NvsPageTableAddress += SIZE_4KB;
//
// Fill in a Page Directory Pointer Entries
//
PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;
PageDirectoryPointerEntry->Bits.ReadWrite = 1;
PageDirectoryPointerEntry->Bits.Present = 1;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 0x200000) {
//
// Fill in the Page Directory entries
//
PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
PageDirectoryEntry->Bits.ReadWrite = 1;
PageDirectoryEntry->Bits.Present = 1;
PageDirectoryEntry->Bits.MustBe1 = 1;
}
}
}
return (EFI_PHYSICAL_ADDRESS) (UINTN) PageMap;
} else {
//
// If DXE is running 32-bit mode, no need to establish page table.
//
return (EFI_PHYSICAL_ADDRESS) 0;
}
}
/**
Gets the buffer of legacy memory below 1 MB
This function is to get the buffer in legacy memory below 1MB that is required during S3 resume.
@param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.
@param Size The returned size of legacy memory below 1 MB.
@retval EFI_SUCCESS Size is successfully returned.
@retval EFI_INVALID_PARAMETER The pointer Size is NULL.
**/
EFI_STATUS
EFIAPI
LegacyGetS3MemorySize (
IN EFI_ACPI_S3_SAVE_PROTOCOL *This,
OUT UINTN *Size
)
{
if (Size == NULL) {
return EFI_INVALID_PARAMETER;
}
*Size = mLegacyRegionSize;
return EFI_SUCCESS;
}
/**
Prepares all information that is needed in the S3 resume boot path.
Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path
@param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.
@param LegacyMemoryAddress The base address of legacy memory.
@retval EFI_NOT_FOUND Some necessary information cannot be found.
@retval EFI_SUCCESS All information was saved successfully.
@retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information.
@retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB.
**/
EFI_STATUS
EFIAPI
S3Ready (
IN EFI_ACPI_S3_SAVE_PROTOCOL *This,
IN VOID *LegacyMemoryAddress
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS AcpiS3ContextBuffer;
ACPI_S3_CONTEXT *AcpiS3Context;
STATIC BOOLEAN AlreadyEntered;
IA32_DESCRIPTOR *Idtr;
IA32_IDT_GATE_DESCRIPTOR *IdtGate;
DEBUG ((EFI_D_INFO, "S3Ready!\n"));
//
// Platform may invoke AcpiS3Save->S3Save() before ExitPmAuth, because we need save S3 information there, while BDS ReadyToBoot may invoke it again.
// So if 2nd S3Save() is triggered later, we need ignore it.
//
if (AlreadyEntered) {
return EFI_SUCCESS;
}
AlreadyEntered = TRUE;
AcpiS3Context = AllocateAcpiNvsMemoryBelow4G (sizeof(*AcpiS3Context));
ASSERT (AcpiS3Context != NULL);
AcpiS3ContextBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;
//
// Get ACPI Table because we will save its position to variable
//
AcpiS3Context->AcpiFacsTable = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiFacsTable ();
ASSERT (AcpiS3Context->AcpiFacsTable != 0);
IdtGate = AllocateAcpiNvsMemoryBelow4G (sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR));
Idtr = (IA32_DESCRIPTOR *)(IdtGate + 0x100);
Idtr->Base = (UINTN)IdtGate;
Idtr->Limit = (UINT16)(sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 - 1);
AcpiS3Context->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)Idtr;
Status = SaveLockBox (
&mAcpiS3IdtrProfileGuid,
(VOID *)(UINTN)Idtr,
(UINTN)sizeof(IA32_DESCRIPTOR)
);
ASSERT_EFI_ERROR (Status);
Status = SetLockBoxAttributes (&mAcpiS3IdtrProfileGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
ASSERT_EFI_ERROR (Status);
//
// Allocate page table
//
AcpiS3Context->S3NvsPageTableAddress = S3CreateIdentityMappingPageTables ();
//
// Allocate stack
//
AcpiS3Context->BootScriptStackSize = PcdGet32 (PcdS3BootScriptStackSize);
AcpiS3Context->BootScriptStackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3BootScriptStackSize));
ASSERT (AcpiS3Context->BootScriptStackBase != 0);
//
// Allocate a code buffer < 4G for S3 debug to load external code
//
AcpiS3Context->S3DebugBufferAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateAcpiNvsMemoryBelow4G (EFI_PAGE_SIZE);
DEBUG((EFI_D_INFO, "AcpiS3Context: AcpiFacsTable is 0x%8x\n", AcpiS3Context->AcpiFacsTable));
DEBUG((EFI_D_INFO, "AcpiS3Context: IdtrProfile is 0x%8x\n", AcpiS3Context->IdtrProfile));
DEBUG((EFI_D_INFO, "AcpiS3Context: S3NvsPageTableAddress is 0x%8x\n", AcpiS3Context->S3NvsPageTableAddress));
DEBUG((EFI_D_INFO, "AcpiS3Context: S3DebugBufferAddress is 0x%8x\n", AcpiS3Context->S3DebugBufferAddress));
Status = SaveLockBox (
&gEfiAcpiVariableGuid,
&AcpiS3ContextBuffer,
sizeof(AcpiS3ContextBuffer)
);
ASSERT_EFI_ERROR (Status);
Status = SaveLockBox (
&gEfiAcpiS3ContextGuid,
(VOID *)(UINTN)AcpiS3Context,
(UINTN)sizeof(*AcpiS3Context)
);
ASSERT_EFI_ERROR (Status);
Status = SetLockBoxAttributes (&gEfiAcpiS3ContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
ASSERT_EFI_ERROR (Status);
if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
S3ReadyThunkPlatform (AcpiS3Context);
}
return EFI_SUCCESS;
}
/**
The Driver Entry Point.
The function is the driver Entry point which will produce AcpiS3SaveProtocol.
@param ImageHandle A handle for the image that is initializing this driver
@param SystemTable A pointer to the EFI system table
@retval EFI_SUCCESS: Driver initialized successfully
@retval EFI_LOAD_ERROR: Failed to Initialize or has been loaded
@retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
**/
EFI_STATUS
EFIAPI
InstallAcpiS3Save (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
if (!FeaturePcdGet(PcdPlatformCsmSupport)) {
//
// More memory for no CSM tip, because GDT need relocation
//
mLegacyRegionSize = 0x250;
} else {
mLegacyRegionSize = 0x100;
}
if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
InstallAcpiS3SaveThunk ();
}
Status = gBS->InstallProtocolInterface (
&ImageHandle,
&gEfiAcpiS3SaveProtocolGuid,
EFI_NATIVE_INTERFACE,
&mS3Save
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -0,0 +1,135 @@
/** @file
This is an implementation of the ACPI S3 Save protocol. This is defined in
S3 boot path specification 0.9.
Copyright (c) 2006 - 2010, 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 _ACPI_S3_SAVE_H_
#define _ACPI_S3_SAVE_H_
#pragma pack(push, 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;
typedef struct {
IA32_IDT_GATE_DESCRIPTOR Ia32IdtEntry;
UINT32 Offset32To63;
UINT32 Reserved;
} X64_IDT_GATE_DESCRIPTOR;
//
// Page-Map Level-4 Offset (PML4) and
// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
//
typedef union {
struct {
UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
UINT64 Reserved:1; // Reserved
UINT64 MustBeZero:2; // Must Be Zero
UINT64 Available:3; // Available for use by system software
UINT64 PageTableBaseAddress:40; // Page Table Base Address
UINT64 AvabilableHigh:11; // Available for use by system software
UINT64 Nx:1; // No Execute bit
} Bits;
UINT64 Uint64;
} PAGE_MAP_AND_DIRECTORY_POINTER;
//
// Page Table Entry 2MB
//
typedef union {
struct {
UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
UINT64 MustBe1:1; // Must be 1
UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
UINT64 Available:3; // Available for use by system software
UINT64 PAT:1; //
UINT64 MustBeZero:8; // Must be zero;
UINT64 PageTableBaseAddress:31; // Page Table Base Address
UINT64 AvabilableHigh:11; // Available for use by system software
UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
} Bits;
UINT64 Uint64;
} PAGE_TABLE_ENTRY;
#pragma pack()
/**
Gets the buffer of legacy memory below 1 MB
This function is to get the buffer in legacy memory below 1MB that is required during S3 resume.
@param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.
@param Size The returned size of legacy memory below 1 MB.
@retval EFI_SUCCESS Size is successfully returned.
@retval EFI_INVALID_PARAMETER The pointer Size is NULL.
**/
EFI_STATUS
EFIAPI
LegacyGetS3MemorySize (
IN EFI_ACPI_S3_SAVE_PROTOCOL * This,
OUT UINTN * Size
);
/**
Prepares all information that is needed in the S3 resume boot path.
Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path
@param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.
@param LegacyMemoryAddress The base address of legacy memory.
@retval EFI_NOT_FOUND Some necessary information cannot be found.
@retval EFI_SUCCESS All information was saved successfully.
@retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information.
@retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB.
**/
EFI_STATUS
EFIAPI
S3Ready (
IN EFI_ACPI_S3_SAVE_PROTOCOL *This,
IN VOID *LegacyMemoryAddress
);
#endif

View File

@ -0,0 +1,83 @@
## @file
# Component description file for AcpiS3Save module.
#
# This is an implementation of the ACPI S3 Save protocol.
# Copyright (c) 2006 - 2011, 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]
INF_VERSION = 0x00010005
BASE_NAME = AcpiS3SaveDxe
FILE_GUID = 2BDED685-F733-455f-A840-43A22B791FB3
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InstallAcpiS3Save
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
AcpiS3Save.h
AcpiS3Save.c
AcpiVariableThunkPlatform.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
[LibraryClasses]
PcdLib
UefiRuntimeServicesTableLib
UefiBootServicesTableLib
UefiDriverEntryPoint
BaseMemoryLib
HobLib
UefiLib
LockBoxLib
DebugLib
DxeServicesLib
[Guids]
gEfiAcpiVariableGuid # ALWAYS_CONSUMED
gEfiAcpiS3ContextGuid # ALWAYS_CONSUMED
gEfiAcpiVariableCompatiblityGuid # SOMETIME_CONSUMED L"AcpiGlobalVariable"
gEfiAcpi20TableGuid # ALWAYS_CONSUMED System Table
gEfiAcpi10TableGuid # ALWAYS_CONSUMED System Table
[Protocols]
gEfiAcpiS3SaveProtocolGuid # PROTOCOL ALWAYS_PRODUCED
gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLegacyRegion2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
gFrameworkEfiMpServiceProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
[FeaturePcd]
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformCsmSupport ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
[Pcd]
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize ## CONSUMES
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3BootScriptStackSize ## CONSUMES
[Depex]
#
# Note: the extra dependency of gEfiMpServiceProtocolGuid is to ensure that ACPI variable is set by MpDxe driver before
# AcpiS3SaveDxe module is executed.
#
gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid AND gEfiMpServiceProtocolGuid

View File

@ -0,0 +1,166 @@
/** @file
This is an implementation of the AcpiVariable platform field for ECP platform.
Copyright (c) 2006 - 2010, 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.
==
typedef struct {
EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase; <<===
UINT32 AcpiReservedMemorySize; <<===
EFI_PHYSICAL_ADDRESS S3ReservedLowMemoryBase;
EFI_PHYSICAL_ADDRESS AcpiBootScriptTable;
EFI_PHYSICAL_ADDRESS RuntimeScriptTableBase;
EFI_PHYSICAL_ADDRESS AcpiFacsTable;
UINT64 SystemMemoryLength; <<===
ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData;
EFI_PHYSICAL_ADDRESS VideoOpromAddress;
UINT32 VideoOpromSize;
EFI_PHYSICAL_ADDRESS S3DebugBufferAddress;
EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint;
} ACPI_VARIABLE_SET_COMPATIBILITY;
**/
#include <FrameworkDxe.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/HobLib.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <Protocol/FrameworkMpService.h>
#include <Guid/AcpiVariableCompatibility.h>
#include <Guid/AcpiS3Context.h>
GLOBAL_REMOVE_IF_UNREFERENCED
ACPI_VARIABLE_SET_COMPATIBILITY *mAcpiVariableSetCompatibility = NULL;
/**
Allocate EfiACPIMemoryNVS below 4G memory address.
This function allocates EfiACPIMemoryNVS below 4G memory address.
@param Size Size of memory to allocate.
@return Allocated address for output.
**/
VOID*
AllocateAcpiNvsMemoryBelow4G (
IN UINTN Size
);
/**
Hook point for AcpiVariableThunkPlatform for S3Ready.
@param AcpiS3Context ACPI s3 context
**/
VOID
S3ReadyThunkPlatform (
IN ACPI_S3_CONTEXT *AcpiS3Context
)
{
EFI_PHYSICAL_ADDRESS AcpiMemoryBase;
UINT32 AcpiMemorySize;
EFI_PEI_HOB_POINTERS Hob;
UINT64 MemoryLength;
DEBUG ((EFI_D_INFO, "S3ReadyThunkPlatform\n"));
//
// Allocate ACPI reserved memory under 4G
//
AcpiMemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));
ASSERT (AcpiMemoryBase != 0);
AcpiMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);
//
// Calculate the system memory length by memory hobs
//
MemoryLength = 0x100000;
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
ASSERT (Hob.Raw != NULL);
while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {
if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
//
// Skip the memory region below 1MB
//
if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {
MemoryLength += Hob.ResourceDescriptor->ResourceLength;
}
}
Hob.Raw = GET_NEXT_HOB (Hob);
Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
}
mAcpiVariableSetCompatibility->AcpiReservedMemoryBase = AcpiMemoryBase;
mAcpiVariableSetCompatibility->AcpiReservedMemorySize = AcpiMemorySize;
mAcpiVariableSetCompatibility->SystemMemoryLength = MemoryLength;
DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemoryBase is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemoryBase));
DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemorySize is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemorySize));
DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: SystemMemoryLength is 0x%8x\n", mAcpiVariableSetCompatibility->SystemMemoryLength));
return ;
}
/**
Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.
**/
VOID
InstallAcpiS3SaveThunk (
VOID
)
{
EFI_STATUS Status;
FRAMEWORK_EFI_MP_SERVICES_PROTOCOL *FrameworkMpService;
UINTN VarSize;
Status = gBS->LocateProtocol (
&gFrameworkEfiMpServiceProtocolGuid,
NULL,
(VOID**) &FrameworkMpService
);
if (!EFI_ERROR (Status)) {
//
// On ECP platform, if framework CPU drivers are in use, The compatible version of ACPI variable set
// should be produced by CPU driver.
//
VarSize = sizeof (mAcpiVariableSetCompatibility);
Status = gRT->GetVariable (
ACPI_GLOBAL_VARIABLE,
&gEfiAcpiVariableCompatiblityGuid,
NULL,
&VarSize,
&mAcpiVariableSetCompatibility
);
ASSERT_EFI_ERROR (Status);
} else {
//
// Allocate/initialize the compatible version of Acpi Variable Set since Framework chipset/platform
// driver need this variable
//
mAcpiVariableSetCompatibility = AllocateAcpiNvsMemoryBelow4G (sizeof(ACPI_VARIABLE_SET_COMPATIBILITY));
Status = gRT->SetVariable (
ACPI_GLOBAL_VARIABLE,
&gEfiAcpiVariableCompatiblityGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
sizeof(mAcpiVariableSetCompatibility),
&mAcpiVariableSetCompatibility
);
ASSERT_EFI_ERROR (Status);
}
DEBUG((EFI_D_INFO, "AcpiVariableSetCompatibility is 0x%8x\n", mAcpiVariableSetCompatibility));
}