113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** @file 213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten This is an implementation of the ACPI S3 Save protocol. This is defined in 313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten S3 boot path specification 0.9. 413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 5353f5ba92f9420266bbf5dd86c3faae35db6a478Star ZengCopyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenThis program and the accompanying materials 813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenare licensed and made available under the terms and conditions 913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenof the BSD License which accompanies this distribution. The 1013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenfull text of the license may be found at 1113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenhttp://opensource.org/licenses/bsd-license.php 1213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 1313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 1413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 1513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 1613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 1713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 1813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <PiDxe.h> 1913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Library/BaseLib.h> 2013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Library/BaseMemoryLib.h> 2113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Library/UefiBootServicesTableLib.h> 2213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Library/UefiRuntimeServicesTableLib.h> 23c56b65665de7a665e29107ee9c377c1e2e84d343jyao#include <Library/HobLib.h> 2413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Library/LockBoxLib.h> 2513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Library/PcdLib.h> 2613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Library/DebugLib.h> 2713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Guid/AcpiVariableCompatibility.h> 2813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Guid/AcpiS3Context.h> 2913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Guid/Acpi.h> 3013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <Protocol/AcpiS3Save.h> 3113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include <IndustryStandard/Acpi.h> 3213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 3313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten#include "AcpiS3Save.h" 3413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 35353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng// 36353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng// 8 extra pages for PF handler. 37353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng// 38353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng#define EXTRA_PAGE_TABLE_PAGES 8 39353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 4013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 4113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save. 4213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 4313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenVOID 4413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenInstallAcpiS3SaveThunk ( 4513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten VOID 4613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ); 4713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 4813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 4913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Hook point for AcpiVariableThunkPlatform for S3Ready. 5013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 5113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param AcpiS3Context ACPI s3 context 5213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 5313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenVOID 5413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenS3ReadyThunkPlatform ( 5513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IN ACPI_S3_CONTEXT *AcpiS3Context 5613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ); 5713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 5813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenUINTN mLegacyRegionSize; 5913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 6013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFI_ACPI_S3_SAVE_PROTOCOL mS3Save = { 6113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten LegacyGetS3MemorySize, 6213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten S3Ready, 6313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten}; 6413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 6513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFI_GUID mAcpiS3IdtrProfileGuid = { 66ce68d3bc68eda5ce919b90aea8db094ed4b64c34lzeng 0xdea652b0, 0xd587, 0x4c54, { 0xb5, 0xb4, 0xc6, 0x82, 0xe7, 0xa0, 0xaa, 0x3d } 6713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten}; 6813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 6913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 70091249f49723fa773d17c910d2dbbc2de211466elzeng Allocate memory below 4G memory address. 7113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 72091249f49723fa773d17c910d2dbbc2de211466elzeng This function allocates memory below 4G memory address. 7313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 74091249f49723fa773d17c910d2dbbc2de211466elzeng @param MemoryType Memory type of memory to allocate. 7513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param Size Size of memory to allocate. 7613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 7713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @return Allocated address for output. 7813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 7913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 8013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenVOID* 81091249f49723fa773d17c910d2dbbc2de211466elzengAllocateMemoryBelow4G ( 8273f0127f98adec4beb5f235face3a515e380cfb7lzeng IN EFI_MEMORY_TYPE MemoryType, 8373f0127f98adec4beb5f235face3a515e380cfb7lzeng IN UINTN Size 8413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ) 8513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten{ 8613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten UINTN Pages; 8713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_PHYSICAL_ADDRESS Address; 8813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_STATUS Status; 8913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten VOID* Buffer; 9013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 9113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Pages = EFI_SIZE_TO_PAGES (Size); 9213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Address = 0xffffffff; 9313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 9413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Status = gBS->AllocatePages ( 9513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten AllocateMaxAddress, 96091249f49723fa773d17c910d2dbbc2de211466elzeng MemoryType, 9713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Pages, 9813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten &Address 9913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ); 10013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT_EFI_ERROR (Status); 10113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 10213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Buffer = (VOID *) (UINTN) Address; 10313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ZeroMem (Buffer, Size); 10413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 10513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return Buffer; 10613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten} 10713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 10813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 109c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 110c93776c2d47b23b5e64691753efc7ab47ba257c0jyao This function scan ACPI table in RSDT. 111c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 112c93776c2d47b23b5e64691753efc7ab47ba257c0jyao @param Rsdt ACPI RSDT 113c93776c2d47b23b5e64691753efc7ab47ba257c0jyao @param Signature ACPI table signature 114c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 115c93776c2d47b23b5e64691753efc7ab47ba257c0jyao @return ACPI table 116c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 117c93776c2d47b23b5e64691753efc7ab47ba257c0jyao**/ 118c93776c2d47b23b5e64691753efc7ab47ba257c0jyaoVOID * 119c93776c2d47b23b5e64691753efc7ab47ba257c0jyaoScanTableInRSDT ( 120c93776c2d47b23b5e64691753efc7ab47ba257c0jyao IN EFI_ACPI_DESCRIPTION_HEADER *Rsdt, 121c93776c2d47b23b5e64691753efc7ab47ba257c0jyao IN UINT32 Signature 122c93776c2d47b23b5e64691753efc7ab47ba257c0jyao ) 123c93776c2d47b23b5e64691753efc7ab47ba257c0jyao{ 124c93776c2d47b23b5e64691753efc7ab47ba257c0jyao UINTN Index; 125c93776c2d47b23b5e64691753efc7ab47ba257c0jyao UINT32 EntryCount; 126c93776c2d47b23b5e64691753efc7ab47ba257c0jyao UINT32 *EntryPtr; 127c93776c2d47b23b5e64691753efc7ab47ba257c0jyao EFI_ACPI_DESCRIPTION_HEADER *Table; 128c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 129c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Rsdt == NULL) { 130c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return NULL; 131c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 132c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 133c93776c2d47b23b5e64691753efc7ab47ba257c0jyao EntryCount = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32); 134c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 135c93776c2d47b23b5e64691753efc7ab47ba257c0jyao EntryPtr = (UINT32 *)(Rsdt + 1); 136c93776c2d47b23b5e64691753efc7ab47ba257c0jyao for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) { 137c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(*EntryPtr)); 138c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Table->Signature == Signature) { 139c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return Table; 140c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 141c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 142c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 143c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return NULL; 144c93776c2d47b23b5e64691753efc7ab47ba257c0jyao} 145c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 146c93776c2d47b23b5e64691753efc7ab47ba257c0jyao/** 147c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 148c93776c2d47b23b5e64691753efc7ab47ba257c0jyao This function scan ACPI table in XSDT. 149c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 150c93776c2d47b23b5e64691753efc7ab47ba257c0jyao @param Xsdt ACPI XSDT 151c93776c2d47b23b5e64691753efc7ab47ba257c0jyao @param Signature ACPI table signature 152c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 153c93776c2d47b23b5e64691753efc7ab47ba257c0jyao @return ACPI table 154c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 155c93776c2d47b23b5e64691753efc7ab47ba257c0jyao**/ 156c93776c2d47b23b5e64691753efc7ab47ba257c0jyaoVOID * 157c93776c2d47b23b5e64691753efc7ab47ba257c0jyaoScanTableInXSDT ( 158c93776c2d47b23b5e64691753efc7ab47ba257c0jyao IN EFI_ACPI_DESCRIPTION_HEADER *Xsdt, 159c93776c2d47b23b5e64691753efc7ab47ba257c0jyao IN UINT32 Signature 160c93776c2d47b23b5e64691753efc7ab47ba257c0jyao ) 161c93776c2d47b23b5e64691753efc7ab47ba257c0jyao{ 162c93776c2d47b23b5e64691753efc7ab47ba257c0jyao UINTN Index; 163c93776c2d47b23b5e64691753efc7ab47ba257c0jyao UINT32 EntryCount; 164c93776c2d47b23b5e64691753efc7ab47ba257c0jyao UINT64 EntryPtr; 165c93776c2d47b23b5e64691753efc7ab47ba257c0jyao UINTN BasePtr; 166c93776c2d47b23b5e64691753efc7ab47ba257c0jyao EFI_ACPI_DESCRIPTION_HEADER *Table; 167c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 168c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Xsdt == NULL) { 169c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return NULL; 170c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 171c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 172c93776c2d47b23b5e64691753efc7ab47ba257c0jyao EntryCount = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64); 173c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 174c93776c2d47b23b5e64691753efc7ab47ba257c0jyao BasePtr = (UINTN)(Xsdt + 1); 175c93776c2d47b23b5e64691753efc7ab47ba257c0jyao for (Index = 0; Index < EntryCount; Index ++) { 176c93776c2d47b23b5e64691753efc7ab47ba257c0jyao CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64)); 177c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(EntryPtr)); 178c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Table->Signature == Signature) { 179c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return Table; 180c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 181c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 182c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 183c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return NULL; 184c93776c2d47b23b5e64691753efc7ab47ba257c0jyao} 185c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 186c93776c2d47b23b5e64691753efc7ab47ba257c0jyao/** 187c93776c2d47b23b5e64691753efc7ab47ba257c0jyao To find Facs in FADT. 188c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 189c93776c2d47b23b5e64691753efc7ab47ba257c0jyao @param Fadt FADT table pointer 190c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 191c93776c2d47b23b5e64691753efc7ab47ba257c0jyao @return Facs table pointer. 192c93776c2d47b23b5e64691753efc7ab47ba257c0jyao**/ 193c93776c2d47b23b5e64691753efc7ab47ba257c0jyaoEFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * 194c93776c2d47b23b5e64691753efc7ab47ba257c0jyaoFindAcpiFacsFromFadt ( 195c93776c2d47b23b5e64691753efc7ab47ba257c0jyao IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt 196c93776c2d47b23b5e64691753efc7ab47ba257c0jyao ) 197c93776c2d47b23b5e64691753efc7ab47ba257c0jyao{ 198c93776c2d47b23b5e64691753efc7ab47ba257c0jyao EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; 199c93776c2d47b23b5e64691753efc7ab47ba257c0jyao UINT64 Data64; 200c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 201c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Fadt == NULL) { 202c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return NULL; 203c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 204c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 205c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { 206c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl; 207c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } else { 208c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Fadt->FirmwareCtrl != 0) { 209c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl; 210c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } else { 211c93776c2d47b23b5e64691753efc7ab47ba257c0jyao CopyMem (&Data64, &Fadt->XFirmwareCtrl, sizeof(UINT64)); 212c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Data64; 213c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 214c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 215c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return Facs; 216c93776c2d47b23b5e64691753efc7ab47ba257c0jyao} 217c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 218c93776c2d47b23b5e64691753efc7ab47ba257c0jyao/** 21913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten To find Facs in Acpi tables. 22013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 22113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored 22213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten in the table. 22313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 22413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param AcpiTableGuid The guid used to find ACPI table in UEFI ConfigurationTable. 22513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 22613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @return Facs table pointer. 22713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 22813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * 22913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenFindAcpiFacsTableByAcpiGuid ( 23013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IN EFI_GUID *AcpiTableGuid 23113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ) 23213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten{ 23313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; 23413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_ACPI_DESCRIPTION_HEADER *Rsdt; 235c93776c2d47b23b5e64691753efc7ab47ba257c0jyao EFI_ACPI_DESCRIPTION_HEADER *Xsdt; 23613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; 23713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; 23813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten UINTN Index; 239c93776c2d47b23b5e64691753efc7ab47ba257c0jyao 24013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Rsdp = NULL; 24113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 24213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // found ACPI table RSD_PTR from system table 24313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 24413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { 24513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), AcpiTableGuid)) { 24613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 24713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // A match was found. 24813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 24913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Rsdp = gST->ConfigurationTable[Index].VendorTable; 25013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten break; 25113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 25213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 25313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 25413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (Rsdp == NULL) { 25513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return NULL; 25613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 25713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 258c93776c2d47b23b5e64691753efc7ab47ba257c0jyao // 259c93776c2d47b23b5e64691753efc7ab47ba257c0jyao // Search XSDT 260c93776c2d47b23b5e64691753efc7ab47ba257c0jyao // 261c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) { 262c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->XsdtAddress; 263c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Fadt = ScanTableInXSDT (Xsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE); 264c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Fadt != NULL) { 265c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Facs = FindAcpiFacsFromFadt (Fadt); 266c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Facs != NULL) { 267c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return Facs; 268c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 26913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 27013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 27113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 272c93776c2d47b23b5e64691753efc7ab47ba257c0jyao // 273c93776c2d47b23b5e64691753efc7ab47ba257c0jyao // Search RSDT 274c93776c2d47b23b5e64691753efc7ab47ba257c0jyao // 275c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress; 276c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Fadt = ScanTableInRSDT (Rsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE); 277c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Fadt != NULL) { 278c93776c2d47b23b5e64691753efc7ab47ba257c0jyao Facs = FindAcpiFacsFromFadt (Fadt); 279c93776c2d47b23b5e64691753efc7ab47ba257c0jyao if (Facs != NULL) { 280c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return Facs; 281c93776c2d47b23b5e64691753efc7ab47ba257c0jyao } 28213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 28313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 284c93776c2d47b23b5e64691753efc7ab47ba257c0jyao return NULL; 28513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten} 28613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 28713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 28813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten To find Facs in Acpi tables. 28913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 29013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored 29113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten in the table. 29213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 29313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @return Facs table pointer. 29413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 29513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * 29613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenFindAcpiFacsTable ( 29713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten VOID 29813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ) 29913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten{ 30013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; 30113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 30213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Facs = FindAcpiFacsTableByAcpiGuid (&gEfiAcpi20TableGuid); 30313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (Facs != NULL) { 30413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return Facs; 30513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 30613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 30713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return FindAcpiFacsTableByAcpiGuid (&gEfiAcpi10TableGuid); 30813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten} 30913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 31013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 311353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng The function will check if long mode waking vector is supported. 312353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 313353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng @param[in] Facs Pointer to FACS table. 314353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 315353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng @retval TRUE Long mode waking vector is supported. 316353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng @retval FALSE Long mode waking vector is not supported. 317353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 318353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng**/ 319353f5ba92f9420266bbf5dd86c3faae35db6a478Star ZengBOOLEAN 320353f5ba92f9420266bbf5dd86c3faae35db6a478Star ZengIsLongModeWakingVectorSupport ( 321353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng IN EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs 322353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng ) 323353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng{ 324353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if ((Facs == NULL) || 325353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ) { 326353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 327353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // Something wrong with FACS. 328353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 329353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng return FALSE; 330353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 331353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (Facs->XFirmwareWakingVector != 0) { 332353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && 333353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0)) { 334353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 335353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // BIOS supports 64bit waking vector. 336353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 337353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { 338353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng return TRUE; 339353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 340353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 341353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 342353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng return FALSE; 343353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng} 344353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 345353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng/** 346353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng Allocates page table buffer. 347353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 348353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng @param[in] LongModeWakingVectorSupport Support long mode waking vector or not. 349353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 35013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten If BootScriptExector driver will run in 64-bit mode, this function will establish the 1:1 351353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng virtual to physical mapping page table when long mode waking vector is supported, otherwise 352353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng create 4G page table when long mode waking vector is not supported and let PF handler to 353353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng handle > 4G request. 35413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. 35513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 356353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng @return Page table base address. 35713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 35813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 35913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFI_PHYSICAL_ADDRESS 360353f5ba92f9420266bbf5dd86c3faae35db6a478Star ZengS3AllocatePageTablesBuffer ( 361353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng IN BOOLEAN LongModeWakingVectorSupport 36213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ) 36313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten{ 36413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { 365353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng UINTN ExtraPageTablePages; 36613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten UINT32 RegEax; 367c56b65665de7a665e29107ee9c377c1e2e84d343jyao UINT32 RegEdx; 36813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten UINT8 PhysicalAddressBits; 369c56b65665de7a665e29107ee9c377c1e2e84d343jyao UINT32 NumberOfPml4EntriesNeeded; 370c56b65665de7a665e29107ee9c377c1e2e84d343jyao UINT32 NumberOfPdpEntriesNeeded; 37113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress; 37213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten UINTN TotalPageTableSize; 373c56b65665de7a665e29107ee9c377c1e2e84d343jyao VOID *Hob; 374c56b65665de7a665e29107ee9c377c1e2e84d343jyao BOOLEAN Page1GSupport; 375c56b65665de7a665e29107ee9c377c1e2e84d343jyao 376353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng Page1GSupport = FALSE; 377353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (PcdGetBool(PcdUse1GPageTable)) { 378353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); 379353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (RegEax >= 0x80000001) { 380353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); 381353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if ((RegEdx & BIT26) != 0) { 382353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng Page1GSupport = TRUE; 383378175d2584ab0d52922308f6a18e710a36152efjyao } 384c56b65665de7a665e29107ee9c377c1e2e84d343jyao } 385353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 386353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 387353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 388353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // Get physical address bits supported. 389353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 390353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng Hob = GetFirstHob (EFI_HOB_TYPE_CPU); 391353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (Hob != NULL) { 392353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; 393353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } else { 394353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); 395353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (RegEax >= 0x80000008) { 396353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); 397353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng PhysicalAddressBits = (UINT8) RegEax; 398ac790db940b6cc5205073e1c8cc9c3f1c01615d4Elvin Li } else { 399353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng PhysicalAddressBits = 36; 400ac790db940b6cc5205073e1c8cc9c3f1c01615d4Elvin Li } 401353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 402353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 403353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 404353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. 405353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 406353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng ASSERT (PhysicalAddressBits <= 52); 407353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (PhysicalAddressBits > 48) { 408353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng PhysicalAddressBits = 48; 409353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 410353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 411353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng ExtraPageTablePages = 0; 412353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (!LongModeWakingVectorSupport) { 413ac790db940b6cc5205073e1c8cc9c3f1c01615d4Elvin Li // 414353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // Create 4G page table when BIOS does not support long mode waking vector, 415353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // and let PF handler to handle > 4G request. 416ac790db940b6cc5205073e1c8cc9c3f1c01615d4Elvin Li // 417353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng PhysicalAddressBits = 32; 418353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng ExtraPageTablePages = EXTRA_PAGE_TABLE_PAGES; 419353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 420353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 421353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 422353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // Calculate the table entries needed. 423353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 424353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (PhysicalAddressBits <= 39 ) { 425353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng NumberOfPml4EntriesNeeded = 1; 426353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); 427353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } else { 428353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); 429353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng NumberOfPdpEntriesNeeded = 512; 43013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 431353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 432353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 433353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs. 434353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 435353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng if (!Page1GSupport) { 436353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded); 437353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } else { 438353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded); 439353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng } 440353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 441353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng TotalPageTableSize += ExtraPageTablePages; 442353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng DEBUG ((EFI_D_ERROR, "AcpiS3Save TotalPageTableSize - 0x%x pages\n", TotalPageTableSize)); 443353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng 444353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 445353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. 446353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng // 447353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGES_TO_SIZE(TotalPageTableSize)); 448353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng ASSERT (S3NvsPageTableAddress != 0); 449353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng return S3NvsPageTableAddress; 45013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } else { 45113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 45213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // If DXE is running 32-bit mode, no need to establish page table. 45313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 45413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return (EFI_PHYSICAL_ADDRESS) 0; 45513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 45613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten} 45713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 45813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 45913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Gets the buffer of legacy memory below 1 MB 46013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten This function is to get the buffer in legacy memory below 1MB that is required during S3 resume. 46113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 46213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. 46313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param Size The returned size of legacy memory below 1 MB. 46413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 46513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_SUCCESS Size is successfully returned. 46613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_INVALID_PARAMETER The pointer Size is NULL. 46713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 46813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 46913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFI_STATUS 47013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFIAPI 47113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenLegacyGetS3MemorySize ( 47213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IN EFI_ACPI_S3_SAVE_PROTOCOL *This, 47313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten OUT UINTN *Size 47413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ) 47513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten{ 47613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (Size == NULL) { 47713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return EFI_INVALID_PARAMETER; 47813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 47913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 48013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten *Size = mLegacyRegionSize; 48113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return EFI_SUCCESS; 48213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten} 48313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 48413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 48513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Prepares all information that is needed in the S3 resume boot path. 48613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 48713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path 48813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 48913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. 49013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param LegacyMemoryAddress The base address of legacy memory. 49113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 49213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_NOT_FOUND Some necessary information cannot be found. 49313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_SUCCESS All information was saved successfully. 49413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information. 49513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB. 49613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 49713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 49813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFI_STATUS 49913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFIAPI 50013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenS3Ready ( 50113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IN EFI_ACPI_S3_SAVE_PROTOCOL *This, 50213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IN VOID *LegacyMemoryAddress 50313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ) 50413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten{ 50513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_STATUS Status; 50613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_PHYSICAL_ADDRESS AcpiS3ContextBuffer; 50713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ACPI_S3_CONTEXT *AcpiS3Context; 50813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten STATIC BOOLEAN AlreadyEntered; 50913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IA32_DESCRIPTOR *Idtr; 51013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IA32_IDT_GATE_DESCRIPTOR *IdtGate; 511353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; 51213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 51313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten DEBUG ((EFI_D_INFO, "S3Ready!\n")); 51413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 51513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 51613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // Platform may invoke AcpiS3Save->S3Save() before ExitPmAuth, because we need save S3 information there, while BDS ReadyToBoot may invoke it again. 51713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // So if 2nd S3Save() is triggered later, we need ignore it. 51813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 51913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (AlreadyEntered) { 52013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return EFI_SUCCESS; 52113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 52213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten AlreadyEntered = TRUE; 52313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 524091249f49723fa773d17c910d2dbbc2de211466elzeng AcpiS3Context = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(*AcpiS3Context)); 52513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT (AcpiS3Context != NULL); 52613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten AcpiS3ContextBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context; 52713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 52813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 52913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // Get ACPI Table because we will save its position to variable 53013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 531353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) FindAcpiFacsTable (); 532353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng AcpiS3Context->AcpiFacsTable = (EFI_PHYSICAL_ADDRESS) (UINTN) Facs; 53313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT (AcpiS3Context->AcpiFacsTable != 0); 53413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 535091249f49723fa773d17c910d2dbbc2de211466elzeng IdtGate = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR)); 53613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Idtr = (IA32_DESCRIPTOR *)(IdtGate + 0x100); 53713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Idtr->Base = (UINTN)IdtGate; 53813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Idtr->Limit = (UINT16)(sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 - 1); 53913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten AcpiS3Context->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)Idtr; 54013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 54113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Status = SaveLockBox ( 54213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten &mAcpiS3IdtrProfileGuid, 54313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten (VOID *)(UINTN)Idtr, 54413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten (UINTN)sizeof(IA32_DESCRIPTOR) 54513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ); 54613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT_EFI_ERROR (Status); 54713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 54813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Status = SetLockBoxAttributes (&mAcpiS3IdtrProfileGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); 54913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT_EFI_ERROR (Status); 55013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 55113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 55213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // Allocate page table 55313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 554353f5ba92f9420266bbf5dd86c3faae35db6a478Star Zeng AcpiS3Context->S3NvsPageTableAddress = S3AllocatePageTablesBuffer (IsLongModeWakingVectorSupport (Facs)); 55513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 55613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 55713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // Allocate stack 55813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 55913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten AcpiS3Context->BootScriptStackSize = PcdGet32 (PcdS3BootScriptStackSize); 560091249f49723fa773d17c910d2dbbc2de211466elzeng AcpiS3Context->BootScriptStackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3BootScriptStackSize)); 56113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT (AcpiS3Context->BootScriptStackBase != 0); 56213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 56313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 564f4a25e813f7ffa624b4868eb19fe13a34c4778cevanjeff // Allocate a code buffer < 4G for S3 debug to load external code, set invalid code instructions in it. 56513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 566091249f49723fa773d17c910d2dbbc2de211466elzeng AcpiS3Context->S3DebugBufferAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGE_SIZE); 567f4a25e813f7ffa624b4868eb19fe13a34c4778cevanjeff SetMem ((VOID *)(UINTN)AcpiS3Context->S3DebugBufferAddress, EFI_PAGE_SIZE, 0xff); 56813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 56913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten DEBUG((EFI_D_INFO, "AcpiS3Context: AcpiFacsTable is 0x%8x\n", AcpiS3Context->AcpiFacsTable)); 57013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten DEBUG((EFI_D_INFO, "AcpiS3Context: IdtrProfile is 0x%8x\n", AcpiS3Context->IdtrProfile)); 57113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten DEBUG((EFI_D_INFO, "AcpiS3Context: S3NvsPageTableAddress is 0x%8x\n", AcpiS3Context->S3NvsPageTableAddress)); 57213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten DEBUG((EFI_D_INFO, "AcpiS3Context: S3DebugBufferAddress is 0x%8x\n", AcpiS3Context->S3DebugBufferAddress)); 573b34039b2e17e682d78feb92afba20132cc7d1e0bGao, Liming DEBUG((EFI_D_INFO, "AcpiS3Context: BootScriptStackBase is 0x%8x\n", AcpiS3Context->BootScriptStackBase)); 574b34039b2e17e682d78feb92afba20132cc7d1e0bGao, Liming DEBUG((EFI_D_INFO, "AcpiS3Context: BootScriptStackSize is 0x%8x\n", AcpiS3Context->BootScriptStackSize)); 57513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 57613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Status = SaveLockBox ( 57713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten &gEfiAcpiVariableGuid, 57813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten &AcpiS3ContextBuffer, 57913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten sizeof(AcpiS3ContextBuffer) 58013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ); 58113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT_EFI_ERROR (Status); 58213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 58313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Status = SaveLockBox ( 58413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten &gEfiAcpiS3ContextGuid, 58513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten (VOID *)(UINTN)AcpiS3Context, 58613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten (UINTN)sizeof(*AcpiS3Context) 58713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ); 58813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT_EFI_ERROR (Status); 58913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 59013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Status = SetLockBoxAttributes (&gEfiAcpiS3ContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); 59113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT_EFI_ERROR (Status); 59213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 59313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) { 59413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten S3ReadyThunkPlatform (AcpiS3Context); 59513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 59613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 59713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return EFI_SUCCESS; 59813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten} 59913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 60013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten/** 60113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten The Driver Entry Point. 60213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 60313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten The function is the driver Entry point which will produce AcpiS3SaveProtocol. 60413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 60513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param ImageHandle A handle for the image that is initializing this driver 60613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @param SystemTable A pointer to the EFI system table 60713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 60813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_SUCCESS: Driver initialized successfully 60913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_LOAD_ERROR: Failed to Initialize or has been loaded 61013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources 61113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 61213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten**/ 61313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFI_STATUS 61413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenEFIAPI 61513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljustenInstallAcpiS3Save ( 61613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IN EFI_HANDLE ImageHandle, 61713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten IN EFI_SYSTEM_TABLE *SystemTable 61813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ) 61913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten{ 62013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_STATUS Status; 62113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 62213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (!FeaturePcdGet(PcdPlatformCsmSupport)) { 62313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 62413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // More memory for no CSM tip, because GDT need relocation 62513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten // 62613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten mLegacyRegionSize = 0x250; 62713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } else { 62813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten mLegacyRegionSize = 0x100; 62913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 63013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 63113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) { 63213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten InstallAcpiS3SaveThunk (); 63313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten } 63413d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten 63513d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten Status = gBS->InstallProtocolInterface ( 63613d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten &ImageHandle, 63713d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten &gEfiAcpiS3SaveProtocolGuid, 63813d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten EFI_NATIVE_INTERFACE, 63913d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten &mS3Save 64013d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ); 64113d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten ASSERT_EFI_ERROR (Status); 64213d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten return Status; 64313d4af68f83c39993b90c0f4d251c4312a0ddc9ajljusten} 644