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;