3 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
16 EFI PEIM to provide the platform support functionality on the Thurley.
20 #include "CommonHeader.h"
22 #include "PlatformBaseAddresses.h"
23 #include "PchAccess.h"
24 #include "PlatformBootMode.h"
25 #include <Guid/SetupVariable.h>
28 // Priority of our boot modes, highest priority first
30 EFI_BOOT_MODE mBootModePriority
[] = {
31 BOOT_IN_RECOVERY_MODE
,
32 BOOT_WITH_DEFAULT_SETTINGS
,
37 BOOT_WITH_MINIMAL_CONFIGURATION
,
38 BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
,
39 BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS
,
40 BOOT_WITH_FULL_CONFIGURATION
,
44 EFI_PEI_NOTIFY_DESCRIPTOR mCapsuleNotifyList
[1] = {
46 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
48 CapsulePpiNotifyCallback
53 GetSleepTypeAfterWakeup (
54 IN CONST EFI_PEI_SERVICES
**PeiServices
,
60 CapsulePpiNotifyCallback (
61 IN EFI_PEI_SERVICES
**PeiServices
,
62 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
67 EFI_BOOT_MODE BootMode
;
68 PEI_CAPSULE_PPI
*Capsule
;
70 Status
= (*PeiServices
)->GetBootMode((const EFI_PEI_SERVICES
**)PeiServices
, &BootMode
);
71 ASSERT_EFI_ERROR (Status
);
73 if (BootMode
== BOOT_ON_S3_RESUME
) {
75 // Determine if we're in capsule update mode
77 Status
= (*PeiServices
)->LocatePpi ((const EFI_PEI_SERVICES
**)PeiServices
,
84 if (Status
== EFI_SUCCESS
) {
85 if (Capsule
->CheckCapsuleUpdate ((EFI_PEI_SERVICES
**)PeiServices
) == EFI_SUCCESS
) {
86 BootMode
= BOOT_ON_FLASH_UPDATE
;
87 Status
= (*PeiServices
)->SetBootMode((const EFI_PEI_SERVICES
**)PeiServices
, BootMode
);
88 ASSERT_EFI_ERROR (Status
);
96 #ifdef NOCS_S3_SUPPORT
99 IN CONST EFI_PEI_SERVICES
**PeiServices
103 EFI_BOOT_MODE BootMode
;
107 Status
= (*PeiServices
)->GetBootMode(PeiServices
, &BootMode
);
108 ASSERT_EFI_ERROR (Status
);
109 if (BootMode
== BOOT_IN_RECOVERY_MODE
){
114 // Let's assume things are OK if not told otherwise
116 BootMode
= BOOT_WITH_FULL_CONFIGURATION
;
118 if (GetSleepTypeAfterWakeup (PeiServices
, &SleepType
)) {
120 case V_PCH_ACPI_PM1_CNT_S3
:
121 BootMode
= BOOT_ON_S3_RESUME
;
122 Status
= (*PeiServices
)->NotifyPpi (PeiServices
, &mCapsuleNotifyList
[0]);
123 ASSERT_EFI_ERROR (Status
);
126 case V_PCH_ACPI_PM1_CNT_S4
:
127 BootMode
= BOOT_ON_S4_RESUME
;
130 case V_PCH_ACPI_PM1_CNT_S5
:
131 BootMode
= BOOT_ON_S5_RESUME
;
133 } // switch (SleepType)
136 if (IsFastBootEnabled (PeiServices
)) {
137 DEBUG ((EFI_D_INFO
, "Prioritizing Boot mode to BOOT_WITH_MINIMAL_CONFIGURATION\n"));
138 PrioritizeBootMode (&BootMode
, BOOT_WITH_MINIMAL_CONFIGURATION
);
142 case BOOT_WITH_FULL_CONFIGURATION
:
143 strBootMode
= L
"BOOT_WITH_FULL_CONFIGURATION";
145 case BOOT_WITH_MINIMAL_CONFIGURATION
:
146 strBootMode
= L
"BOOT_WITH_MINIMAL_CONFIGURATION";
148 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
:
149 strBootMode
= L
"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";
151 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS
:
152 strBootMode
= L
"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";
154 case BOOT_WITH_DEFAULT_SETTINGS
:
155 strBootMode
= L
"BOOT_WITH_DEFAULT_SETTINGS";
157 case BOOT_ON_S4_RESUME
:
158 strBootMode
= L
"BOOT_ON_S4_RESUME";
160 case BOOT_ON_S5_RESUME
:
161 strBootMode
= L
"BOOT_ON_S5_RESUME";
163 case BOOT_ON_S2_RESUME
:
164 strBootMode
= L
"BOOT_ON_S2_RESUME";
166 case BOOT_ON_S3_RESUME
:
167 strBootMode
= L
"BOOT_ON_S3_RESUME";
170 case BOOT_ON_FLASH_UPDATE
:
171 strBootMode
= L
"BOOT_ON_FLASH_UPDATE";
173 case BOOT_IN_RECOVERY_MODE
:
174 strBootMode
= L
"BOOT_IN_RECOVERY_MODE";
177 strBootMode
= L
"Unknown boot mode";
178 } // switch (BootMode)
180 DEBUG ((EFI_D_ERROR
, "Setting BootMode to %s\n", strBootMode
));
181 Status
= (*PeiServices
)->SetBootMode(PeiServices
, BootMode
);
182 ASSERT_EFI_ERROR (Status
);
189 Get sleep type after wakeup
191 @param PeiServices Pointer to the PEI Service Table.
192 @param SleepType Sleep type to be returned.
194 @retval TRUE A wake event occured without power failure.
195 @retval FALSE Power failure occured or not a wakeup.
199 GetSleepTypeAfterWakeup (
200 IN CONST EFI_PEI_SERVICES
**PeiServices
,
201 OUT UINT16
*SleepType
208 // VLV BIOS Specification 0.6.2 - Section 18.4, "Power Failure Consideration"
210 // When the SUS_PWR_FLR bit is set, it indicates the SUS well power is lost.
211 // This bit is in the SUS Well and defaults to 1\92b1 based on RSMRST# assertion (not cleared by any type of reset).
212 // System BIOS should follow cold boot path if SUS_PWR_FLR (PBASE + 0x20[14]),
213 // GEN_RST_STS (PBASE + 0x20[9]) or PWRBTNOR_STS (ABASE + 0x00[11]) is set to 1\92b1
214 // regardless of the value in the SLP_TYP (ABASE + 0x04[12:10]) field.
216 GenPmCon1
= MmioRead16 (PMC_BASE_ADDRESS
+ R_PCH_PMC_GEN_PMCON_1
);
219 // Read the ACPI registers
221 Pm1Sts
= IoRead16 (ACPI_BASE_ADDRESS
+ R_PCH_ACPI_PM1_STS
);
222 Pm1Cnt
= IoRead16 (ACPI_BASE_ADDRESS
+ R_PCH_ACPI_PM1_CNT
);
224 if ((GenPmCon1
& (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR
| B_PCH_PMC_GEN_PMCON_GEN_RST_STS
)) ||
225 (Pm1Sts
& B_PCH_ACPI_PM1_STS_PRBTNOR
)) {
227 // If power failure indicator, then don't attempt s3 resume.
228 // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has
229 // lost already. This is to make sure no one will use PM1_CNT to check for S3 after
232 if ((Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
) == V_PCH_ACPI_PM1_CNT_S3
) {
233 Pm1Cnt
= ((Pm1Cnt
& ~B_PCH_ACPI_PM1_CNT_SLP_TYP
) | V_PCH_ACPI_PM1_CNT_S5
);
234 IoWrite16 (ACPI_BASE_ADDRESS
+ R_PCH_ACPI_PM1_CNT
, Pm1Cnt
);
237 // Clear Wake Status (WAK_STS)
241 // Get sleep type if a wake event occurred and there is no power failure
243 if ((Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
) == V_PCH_ACPI_PM1_CNT_S3
) {
244 *SleepType
= Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
;
246 } else if ((Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
) == V_PCH_ACPI_PM1_CNT_S4
) {
247 *SleepType
= Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
;
256 IN CONST EFI_PEI_SERVICES
**PeiServices
260 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*PeiReadOnlyVarPpi
;
262 SYSTEM_CONFIGURATION SystemConfiguration
;
263 BOOLEAN FastBootEnabledStatus
;
265 FastBootEnabledStatus
= FALSE
;
266 Status
= (**PeiServices
).LocatePpi (
268 &gEfiPeiReadOnlyVariable2PpiGuid
,
271 (void **)&PeiReadOnlyVarPpi
273 if (Status
== EFI_SUCCESS
) {
274 VarSize
= sizeof (SYSTEM_CONFIGURATION
);
275 Status
= PeiReadOnlyVarPpi
->GetVariable (
277 PLATFORM_SETUP_VARIABLE_NAME
,
278 &gEfiSetupVariableGuid
,
283 if (Status
== EFI_SUCCESS
) {
284 if (SystemConfiguration
.FastBoot
!= 0) {
285 FastBootEnabledStatus
= TRUE
;
290 return FastBootEnabledStatus
;
294 Given the current boot mode, and a proposed new boot mode, determine
295 which has priority. If the new boot mode has higher priority, then
296 make it the current boot mode.
298 @param CurrentBootMode pointer to current planned boot mode
299 @param NewBootMode proposed boot mode
301 @retval EFI_NOT_FOUND if either boot mode is not recognized
302 @retval EFI_SUCCESS if both boot mode values were recognized and
307 IN OUT EFI_BOOT_MODE
*CurrentBootMode
,
308 IN EFI_BOOT_MODE NewBootMode
315 // Find the position of the current boot mode in our priority array
317 for ( CurrentIndex
= 0;
318 CurrentIndex
< ARRAY_SIZE (mBootModePriority
);
320 if (mBootModePriority
[CurrentIndex
] == *CurrentBootMode
) {
324 if (CurrentIndex
>= ARRAY_SIZE (mBootModePriority
)) {
325 return EFI_NOT_FOUND
;
329 // Find the position of the new boot mode in our priority array
332 NewIndex
< ARRAY_SIZE (mBootModePriority
);
334 if (mBootModePriority
[NewIndex
] == NewBootMode
) {
336 // If this new boot mode occurs before the current boot mode in the
337 // priority array, then take it.
339 if (NewIndex
< CurrentIndex
) {
340 *CurrentBootMode
= NewBootMode
;
345 return EFI_NOT_FOUND
;