+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
- \r\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
- \r\r
-\r
-Module Name:\r
-\r
-\r
- BootMode.c\r
-\r
-Abstract:\r
-\r
- EFI PEIM to provide the platform support functionality on the Thurley.\r
-\r
-\r
---*/\r
-#include "CommonHeader.h"\r
-#include "Platform.h"\r
-#include "PlatformBaseAddresses.h"\r
-#include "PchAccess.h"\r
-#include "PlatformBootMode.h"\r
-#include <Guid/SetupVariable.h>\r
-\r
-//\r
-// Priority of our boot modes, highest priority first\r
-//\r
-EFI_BOOT_MODE mBootModePriority[] = {\r
- BOOT_IN_RECOVERY_MODE,\r
- BOOT_WITH_DEFAULT_SETTINGS,\r
- BOOT_ON_FLASH_UPDATE,\r
- BOOT_ON_S2_RESUME,\r
- BOOT_ON_S3_RESUME,\r
- BOOT_ON_S4_RESUME,\r
- BOOT_WITH_MINIMAL_CONFIGURATION,\r
- BOOT_ASSUMING_NO_CONFIGURATION_CHANGES,\r
- BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS,\r
- BOOT_WITH_FULL_CONFIGURATION,\r
- BOOT_ON_S5_RESUME\r
-};\r
-\r
-EFI_PEI_NOTIFY_DESCRIPTOR mCapsuleNotifyList[1] = {\r
- {\r
- (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
- &gPeiCapsulePpiGuid,\r
- CapsulePpiNotifyCallback\r
- }\r
-};\r
-\r
-BOOLEAN\r
-GetSleepTypeAfterWakeup (\r
- IN CONST EFI_PEI_SERVICES **PeiServices,\r
- OUT UINT16 *SleepType\r
- );\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-CapsulePpiNotifyCallback (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
- IN VOID *Ppi\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_BOOT_MODE BootMode;\r
- PEI_CAPSULE_PPI *Capsule;\r
-\r
- Status = (*PeiServices)->GetBootMode((const EFI_PEI_SERVICES **)PeiServices, &BootMode);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- if (BootMode == BOOT_ON_S3_RESUME) {\r
- //\r
- // Determine if we're in capsule update mode\r
- //\r
- Status = (*PeiServices)->LocatePpi ((const EFI_PEI_SERVICES **)PeiServices,\r
- &gPeiCapsulePpiGuid,\r
- 0,\r
- NULL,\r
- (VOID **)&Capsule\r
- );\r
-\r
- if (Status == EFI_SUCCESS) {\r
- if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES**)PeiServices) == EFI_SUCCESS) {\r
- BootMode = BOOT_ON_FLASH_UPDATE;\r
- Status = (*PeiServices)->SetBootMode((const EFI_PEI_SERVICES **)PeiServices, BootMode);\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-#ifdef NOCS_S3_SUPPORT\r
-EFI_STATUS\r
-UpdateBootMode (\r
- IN CONST EFI_PEI_SERVICES **PeiServices\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_BOOT_MODE BootMode;\r
- UINT16 SleepType;\r
- CHAR16 *strBootMode;\r
-\r
- Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode);\r
- ASSERT_EFI_ERROR (Status);\r
- if (BootMode == BOOT_IN_RECOVERY_MODE){\r
- return Status;\r
- }\r
-\r
- //\r
- // Let's assume things are OK if not told otherwise\r
- //\r
- BootMode = BOOT_WITH_FULL_CONFIGURATION;\r
-\r
- if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) {\r
- switch (SleepType) {\r
- case V_PCH_ACPI_PM1_CNT_S3:\r
- BootMode = BOOT_ON_S3_RESUME;\r
- Status = (*PeiServices)->NotifyPpi (PeiServices, &mCapsuleNotifyList[0]);\r
- ASSERT_EFI_ERROR (Status);\r
- break;\r
-\r
- case V_PCH_ACPI_PM1_CNT_S4:\r
- BootMode = BOOT_ON_S4_RESUME;\r
- break;\r
-\r
- case V_PCH_ACPI_PM1_CNT_S5:\r
- BootMode = BOOT_ON_S5_RESUME;\r
- break;\r
- } // switch (SleepType)\r
- }\r
-\r
- if (IsFastBootEnabled (PeiServices)) {\r
- DEBUG ((EFI_D_INFO, "Prioritizing Boot mode to BOOT_WITH_MINIMAL_CONFIGURATION\n"));\r
- PrioritizeBootMode (&BootMode, BOOT_WITH_MINIMAL_CONFIGURATION);\r
- }\r
-\r
- switch (BootMode) {\r
- case BOOT_WITH_FULL_CONFIGURATION:\r
- strBootMode = L"BOOT_WITH_FULL_CONFIGURATION";\r
- break;\r
- case BOOT_WITH_MINIMAL_CONFIGURATION:\r
- strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION";\r
- break;\r
- case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:\r
- strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";\r
- break;\r
- case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:\r
- strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";\r
- break;\r
- case BOOT_WITH_DEFAULT_SETTINGS:\r
- strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS";\r
- break;\r
- case BOOT_ON_S4_RESUME:\r
- strBootMode = L"BOOT_ON_S4_RESUME";\r
- break;\r
- case BOOT_ON_S5_RESUME:\r
- strBootMode = L"BOOT_ON_S5_RESUME";\r
- break;\r
- case BOOT_ON_S2_RESUME:\r
- strBootMode = L"BOOT_ON_S2_RESUME";\r
- break;\r
- case BOOT_ON_S3_RESUME:\r
- strBootMode = L"BOOT_ON_S3_RESUME";\r
-\r
- break;\r
- case BOOT_ON_FLASH_UPDATE:\r
- strBootMode = L"BOOT_ON_FLASH_UPDATE";\r
- break;\r
- case BOOT_IN_RECOVERY_MODE:\r
- strBootMode = L"BOOT_IN_RECOVERY_MODE";\r
- break;\r
- default:\r
- strBootMode = L"Unknown boot mode";\r
- } // switch (BootMode)\r
-\r
- DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode));\r
- Status = (*PeiServices)->SetBootMode(PeiServices, BootMode);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
-#endif\r
-\r
-/**\r
- Get sleep type after wakeup\r
-\r
- @param PeiServices Pointer to the PEI Service Table.\r
- @param SleepType Sleep type to be returned.\r
-\r
- @retval TRUE A wake event occured without power failure.\r
- @retval FALSE Power failure occured or not a wakeup.\r
-\r
-**/\r
-BOOLEAN\r
-GetSleepTypeAfterWakeup (\r
- IN CONST EFI_PEI_SERVICES **PeiServices,\r
- OUT UINT16 *SleepType\r
- )\r
-{\r
- UINT16 Pm1Sts;\r
- UINT16 Pm1Cnt;\r
- UINT16 GenPmCon1;\r
- //\r
- // VLV BIOS Specification 0.6.2 - Section 18.4, "Power Failure Consideration"\r
- //\r
- // When the SUS_PWR_FLR bit is set, it indicates the SUS well power is lost.\r
- // This bit is in the SUS Well and defaults to 1\92b1 based on RSMRST# assertion (not cleared by any type of reset).\r
- // System BIOS should follow cold boot path if SUS_PWR_FLR (PBASE + 0x20[14]),\r
- // GEN_RST_STS (PBASE + 0x20[9]) or PWRBTNOR_STS (ABASE + 0x00[11]) is set to 1\92b1\r
- // regardless of the value in the SLP_TYP (ABASE + 0x04[12:10]) field.\r
- //\r
- GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);\r
-\r
- //\r
- // Read the ACPI registers\r
- //\r
- Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);\r
- Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT);\r
-\r
- if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) ||\r
- (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) {\r
- //\r
- // If power failure indicator, then don't attempt s3 resume.\r
- // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has\r
- // lost already. This is to make sure no one will use PM1_CNT to check for S3 after\r
- // power failure.\r
- //\r
- if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {\r
- Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5);\r
- IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt);\r
- }\r
- //\r
- // Clear Wake Status (WAK_STS)\r
- //\r
- }\r
- //\r
- // Get sleep type if a wake event occurred and there is no power failure\r
- //\r
- if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {\r
- *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;\r
- return TRUE;\r
- } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4) {\r
- *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-BOOLEAN\r
-EFIAPI\r
-IsFastBootEnabled (\r
- IN CONST EFI_PEI_SERVICES **PeiServices\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi;\r
- UINTN VarSize;\r
- SYSTEM_CONFIGURATION SystemConfiguration;\r
- BOOLEAN FastBootEnabledStatus;\r
-\r
- FastBootEnabledStatus = FALSE;\r
- Status = (**PeiServices).LocatePpi (\r
- PeiServices,\r
- &gEfiPeiReadOnlyVariable2PpiGuid,\r
- 0,\r
- NULL,\r
- (void **)&PeiReadOnlyVarPpi\r
- );\r
- if (Status == EFI_SUCCESS) {\r
- VarSize = sizeof (SYSTEM_CONFIGURATION);\r
- Status = PeiReadOnlyVarPpi->GetVariable (\r
- PeiReadOnlyVarPpi,\r
- PLATFORM_SETUP_VARIABLE_NAME,\r
- &gEfiSetupVariableGuid,\r
- NULL,\r
- &VarSize,\r
- &SystemConfiguration\r
- );\r
- if (Status == EFI_SUCCESS) {\r
- if (SystemConfiguration.FastBoot != 0) {\r
- FastBootEnabledStatus = TRUE;\r
- }\r
- }\r
- }\r
-\r
- return FastBootEnabledStatus;\r
-}\r
-\r
-/**\r
- Given the current boot mode, and a proposed new boot mode, determine\r
- which has priority. If the new boot mode has higher priority, then\r
- make it the current boot mode.\r
-\r
- @param CurrentBootMode pointer to current planned boot mode\r
- @param NewBootMode proposed boot mode\r
-\r
- @retval EFI_NOT_FOUND if either boot mode is not recognized\r
- @retval EFI_SUCCESS if both boot mode values were recognized and\r
- were processed.\r
-**/\r
-EFI_STATUS\r
-PrioritizeBootMode (\r
- IN OUT EFI_BOOT_MODE *CurrentBootMode,\r
- IN EFI_BOOT_MODE NewBootMode\r
- )\r
-{\r
- UINT32 CurrentIndex;\r
- UINT32 NewIndex;\r
-\r
- //\r
- // Find the position of the current boot mode in our priority array\r
- //\r
- for ( CurrentIndex = 0;\r
- CurrentIndex < ARRAY_SIZE (mBootModePriority);\r
- CurrentIndex++) {\r
- if (mBootModePriority[CurrentIndex] == *CurrentBootMode) {\r
- break;\r
- }\r
- }\r
- if (CurrentIndex >= ARRAY_SIZE (mBootModePriority)) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Find the position of the new boot mode in our priority array\r
- //\r
- for ( NewIndex = 0;\r
- NewIndex < ARRAY_SIZE (mBootModePriority);\r
- NewIndex++) {\r
- if (mBootModePriority[NewIndex] == NewBootMode) {\r
- //\r
- // If this new boot mode occurs before the current boot mode in the\r
- // priority array, then take it.\r
- //\r
- if (NewIndex < CurrentIndex) {\r
- *CurrentBootMode = NewBootMode;\r
- }\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- return EFI_NOT_FOUND;\r
-}\r