X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FUniversal%2FAcpi%2FS3Resume2Pei%2FS3Resume.c;h=de3aec85e185375cce9660e05c219160d461b741;hb=d0bf562330e5309a92e55e44063a8ea37ead4d1d;hp=3afd0ff0e395859679c22afae22fc51bd9fa368a;hpb=378175d2584ab0d52922308f6a18e710a36152ef;p=mirror_edk2.git
diff --git a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
index 3afd0ff0e3..de3aec85e1 100644
--- a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
+++ b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
@@ -4,7 +4,7 @@
This module will excute the boot script saved during last boot and after that,
control is passed to OS waking up handler.
- Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -284,7 +284,9 @@ WriteToOsS3PerformanceData (
NULL,
(VOID **) &VariableServices
);
- ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
Status = VariableServices->GetVariable (
@@ -365,6 +367,41 @@ WriteToOsS3PerformanceData (
PerfHeader->S3EntryNum = (UINT32) Index;
}
+/**
+ The function will check if current waking vector is long mode.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+
+ @retval TRUE Current context need long mode waking vector.
+ @retval FALSE Current context need not long mode waking vector.
+**/
+BOOLEAN
+IsLongModeWakingVector (
+ IN ACPI_S3_CONTEXT *AcpiS3Context
+ )
+{
+ EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+
+ Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable));
+ if ((Facs == NULL) ||
+ (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
+ ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) {
+ // Something wrong with FACS
+ return FALSE;
+ }
+ if (Facs->XFirmwareWakingVector != 0) {
+ if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
+ ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
+ ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) {
+ // Both BIOS and OS wants 64bit vector
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
/**
Jump to OS waking vector.
The function will install boot script done PPI, report S3 resume status code, and then jump to OS waking vector.
@@ -390,6 +427,8 @@ S3ResumeBootOs (
//
AsmWriteIdtr (&PeiS3ResumeState->Idtr);
+ PERF_END (NULL, "ScriptExec", NULL, 0);
+
//
// Install BootScriptDonePpi
//
@@ -408,17 +447,17 @@ S3ResumeBootOs (
return ;
}
- //
- // report status code on S3 resume
- //
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);
-
//
// Install EndOfPeiPpi
//
Status = PeiServicesInstallPpi (&mPpiListEndOfPeiTable);
ASSERT_EFI_ERROR (Status);
+ //
+ // report status code on S3 resume
+ //
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);
+
PERF_CODE (
WriteToOsS3PerformanceData ();
);
@@ -479,10 +518,12 @@ S3ResumeBootOs (
If BootScriptExector driver will not run in 64-bit mode, this function will do nothing.
@param S3NvsPageTableAddress PageTableAddress in ACPINvs
+ @param Build4GPageTableOnly If BIOS just build 4G page table only
**/
VOID
RestoreS3PageTables (
- IN UINTN S3NvsPageTableAddress
+ IN UINTN S3NvsPageTableAddress,
+ IN BOOLEAN Build4GPageTableOnly
)
{
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
@@ -509,7 +550,7 @@ RestoreS3PageTables (
//
// The assumption is : whole page table is allocated in CONTINOUS memory and CR3 points to TOP page.
//
- DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x\n", S3NvsPageTableAddress));
+ DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x (%x)\n", (UINTN)S3NvsPageTableAddress, (UINTN)Build4GPageTableOnly));
//
// By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.
@@ -552,6 +593,14 @@ RestoreS3PageTables (
PhysicalAddressBits = 48;
}
+ //
+ // NOTE: In order to save time to create full page table, we just create 4G page table by default.
+ // And let PF handler in BootScript driver to create more on request.
+ //
+ if (Build4GPageTableOnly) {
+ PhysicalAddressBits = 32;
+ ZeroMem (PageMap, EFI_PAGES_TO_SIZE(2));
+ }
//
// Calculate the table entries needed.
//
@@ -679,25 +728,22 @@ S3ResumeExecuteBootScript (
NULL,
(VOID **) &SmmAccess
);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Close all SMRAM regions before executing boot script\n"));
+
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
- DEBUG ((EFI_D_ERROR, "Close all SMRAM regions before executing boot script\n"));
-
- for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
- Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
- }
-
- DEBUG ((EFI_D_ERROR, "Lock all SMRAM regions before executing boot script\n"));
-
- for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
- Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ DEBUG ((EFI_D_ERROR, "Lock all SMRAM regions before executing boot script\n"));
+
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
}
}
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
- //
- // Need reconstruct page table here, since we do not trust ACPINvs.
- //
- RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress);
AsmWriteCr3 ((UINTN)AcpiS3Context->S3NvsPageTableAddress);
}
@@ -712,6 +758,12 @@ S3ResumeExecuteBootScript (
//
IdtBuffer = AllocatePages (EFI_SIZE_TO_PAGES((IdtDescriptor->Limit + 1) + 16));
ASSERT (IdtBuffer != NULL);
+ //
+ // Additional 16 bytes allocated to save IA32 IDT descriptor and Pei Service Table Pointer
+ // IA32 IDT descriptor will be used to setup IA32 IDT table for 32-bit Framework Boot Script code
+ //
+ ZeroMem (IdtBuffer, 16);
+ AsmReadIdtr ((IA32_DESCRIPTOR *)IdtBuffer);
CopyMem ((VOID*)((UINT8*)IdtBuffer + 16),(VOID*)(IdtDescriptor->Base), (IdtDescriptor->Limit + 1));
IdtDescriptor->Base = (UINTN)((UINT8*)IdtBuffer + 16);
*(UINTN*)(IdtDescriptor->Base - sizeof(UINTN)) = (UINTN)GetPeiServicesTablePointer ();
@@ -736,6 +788,8 @@ S3ResumeExecuteBootScript (
//
AsmReadIdtr (&PeiS3ResumeState->Idtr);
+ PERF_START (NULL, "ScriptExec", NULL, 0);
+
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
//
// X64 S3 Resume
@@ -811,7 +865,6 @@ S3RestoreConfig2 (
PEI_SMM_ACCESS_PPI *SmmAccess;
UINTN Index;
ACPI_S3_CONTEXT *AcpiS3Context;
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
EFI_PHYSICAL_ADDRESS TempEfiBootScriptExecutorVariable;
EFI_PHYSICAL_ADDRESS TempAcpiS3Context;
BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
@@ -819,29 +872,10 @@ S3RestoreConfig2 (
EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
SMM_S3_RESUME_STATE *SmmS3ResumeState;
VOID *GuidHob;
+ BOOLEAN Build4GPageTableOnly;
DEBUG ((EFI_D_ERROR, "Enter S3 PEIM\r\n"));
- Status = PeiServicesLocatePpi (
- &gPeiSmmAccessPpiGuid,
- 0,
- NULL,
- (VOID **) &SmmAccess
- );
- for (Index = 0; !EFI_ERROR (Status); Index++) {
- Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
- }
-
- Status = PeiServicesLocatePpi (
- &gEfiPeiReadOnlyVariable2PpiGuid,
- 0,
- NULL,
- (VOID **) &VariableServices
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
Status = RestoreLockBox (
&gEfiAcpiVariableGuid,
@@ -896,11 +930,33 @@ S3RestoreConfig2 (
CpuDeadLoop ();
}
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ //
+ // Need reconstruct page table here, since we do not trust ACPINvs.
+ //
+ if (IsLongModeWakingVector (AcpiS3Context)) {
+ Build4GPageTableOnly = FALSE;
+ } else {
+ Build4GPageTableOnly = TRUE;
+ }
+ RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress, Build4GPageTableOnly);
+ }
+
//
// Attempt to use content from SMRAM first
//
GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
if (GuidHob != NULL) {
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SmmAccess
+ );
+ for (Index = 0; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+
SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;