3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 EFI PEIM to provide the platform support functionality on the Thurley.
25 #include "CommonHeader.h"
27 #include "PlatformBaseAddresses.h"
28 #include "PchAccess.h"
29 #include "PlatformBootMode.h"
30 #include <Guid/SetupVariable.h>
32 #include <Guid/BootState.h>
35 // Priority of our boot modes, highest priority first
37 EFI_BOOT_MODE mBootModePriority
[] = {
38 BOOT_IN_RECOVERY_MODE
,
39 BOOT_WITH_DEFAULT_SETTINGS
,
44 BOOT_WITH_MINIMAL_CONFIGURATION
,
45 BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
,
46 BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS
,
47 BOOT_WITH_FULL_CONFIGURATION
,
51 EFI_PEI_NOTIFY_DESCRIPTOR mCapsuleNotifyList
[1] = {
53 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
55 CapsulePpiNotifyCallback
60 GetSleepTypeAfterWakeup (
61 IN CONST EFI_PEI_SERVICES
**PeiServices
,
67 CapsulePpiNotifyCallback (
68 IN EFI_PEI_SERVICES
**PeiServices
,
69 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
74 EFI_BOOT_MODE BootMode
;
75 PEI_CAPSULE_PPI
*Capsule
;
77 Status
= (*PeiServices
)->GetBootMode((const EFI_PEI_SERVICES
**)PeiServices
, &BootMode
);
78 ASSERT_EFI_ERROR (Status
);
80 if (BootMode
== BOOT_ON_S3_RESUME
) {
82 // Determine if we're in capsule update mode
84 Status
= (*PeiServices
)->LocatePpi ((const EFI_PEI_SERVICES
**)PeiServices
,
91 if (Status
== EFI_SUCCESS
) {
92 if (Capsule
->CheckCapsuleUpdate ((EFI_PEI_SERVICES
**)PeiServices
) == EFI_SUCCESS
) {
93 BootMode
= BOOT_ON_FLASH_UPDATE
;
94 Status
= (*PeiServices
)->SetBootMode((const EFI_PEI_SERVICES
**)PeiServices
, BootMode
);
95 ASSERT_EFI_ERROR (Status
);
104 Check CMOS register bit to determine if previous boot was successful
106 @param PeiServices pointer to the PEI Service Table
108 @retval TRUE - Previous Boot was success
109 @retval FALSE - Previous Boot wasn't success
113 IsPreviousBootSuccessful(
114 IN CONST EFI_PEI_SERVICES
**PeiServices
121 CHAR16 VarName
[] = BOOT_STATE_VARIABLE_NAME
;
122 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*PeiVar
;
124 Status
= (**PeiServices
).LocatePpi (
126 &gEfiPeiReadOnlyVariable2PpiGuid
,
131 ASSERT_EFI_ERROR (Status
);
134 // Get last Boot State Variable to confirm that it is not a first boot .
137 DataSize
= sizeof (BOOLEAN
);
138 Status
= PeiVar
->GetVariable (
146 if (EFI_ERROR (Status
) || (BootState
== TRUE
)) {
150 DEBUG ((EFI_D_INFO
, "Previous boot cycle successfully completed handover to OS\n"));
153 #ifdef NOCS_S3_SUPPORT
156 IN CONST EFI_PEI_SERVICES
**PeiServices
160 EFI_BOOT_MODE BootMode
;
164 Status
= (*PeiServices
)->GetBootMode(PeiServices
, &BootMode
);
165 ASSERT_EFI_ERROR (Status
);
166 if (BootMode
== BOOT_IN_RECOVERY_MODE
){
171 // Let's assume things are OK if not told otherwise
173 BootMode
= BOOT_WITH_FULL_CONFIGURATION
;
175 if (GetSleepTypeAfterWakeup (PeiServices
, &SleepType
)) {
177 case V_PCH_ACPI_PM1_CNT_S3
:
178 BootMode
= BOOT_ON_S3_RESUME
;
179 Status
= (*PeiServices
)->NotifyPpi (PeiServices
, &mCapsuleNotifyList
[0]);
180 ASSERT_EFI_ERROR (Status
);
183 case V_PCH_ACPI_PM1_CNT_S4
:
184 BootMode
= BOOT_ON_S4_RESUME
;
187 case V_PCH_ACPI_PM1_CNT_S5
:
188 BootMode
= BOOT_ON_S5_RESUME
;
190 } // switch (SleepType)
193 if (IsFastBootEnabled (PeiServices
) && IsPreviousBootSuccessful (PeiServices
)) {
194 DEBUG ((EFI_D_INFO
, "Prioritizing Boot mode to BOOT_WITH_MINIMAL_CONFIGURATION\n"));
195 PrioritizeBootMode (&BootMode
, BOOT_WITH_MINIMAL_CONFIGURATION
);
199 case BOOT_WITH_FULL_CONFIGURATION
:
200 strBootMode
= L
"BOOT_WITH_FULL_CONFIGURATION";
202 case BOOT_WITH_MINIMAL_CONFIGURATION
:
203 strBootMode
= L
"BOOT_WITH_MINIMAL_CONFIGURATION";
205 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
:
206 strBootMode
= L
"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";
208 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS
:
209 strBootMode
= L
"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";
211 case BOOT_WITH_DEFAULT_SETTINGS
:
212 strBootMode
= L
"BOOT_WITH_DEFAULT_SETTINGS";
214 case BOOT_ON_S4_RESUME
:
215 strBootMode
= L
"BOOT_ON_S4_RESUME";
217 case BOOT_ON_S5_RESUME
:
218 strBootMode
= L
"BOOT_ON_S5_RESUME";
220 case BOOT_ON_S2_RESUME
:
221 strBootMode
= L
"BOOT_ON_S2_RESUME";
223 case BOOT_ON_S3_RESUME
:
224 strBootMode
= L
"BOOT_ON_S3_RESUME";
227 case BOOT_ON_FLASH_UPDATE
:
228 strBootMode
= L
"BOOT_ON_FLASH_UPDATE";
230 case BOOT_IN_RECOVERY_MODE
:
231 strBootMode
= L
"BOOT_IN_RECOVERY_MODE";
234 strBootMode
= L
"Unknown boot mode";
235 } // switch (BootMode)
237 DEBUG ((EFI_D_ERROR
, "Setting BootMode to %s\n", strBootMode
));
238 Status
= (*PeiServices
)->SetBootMode(PeiServices
, BootMode
);
239 ASSERT_EFI_ERROR (Status
);
246 Get sleep type after wakeup
248 @param PeiServices Pointer to the PEI Service Table.
249 @param SleepType Sleep type to be returned.
251 @retval TRUE A wake event occured without power failure.
252 @retval FALSE Power failure occured or not a wakeup.
256 GetSleepTypeAfterWakeup (
257 IN CONST EFI_PEI_SERVICES
**PeiServices
,
258 OUT UINT16
*SleepType
265 // VLV BIOS Specification 0.6.2 - Section 18.4, "Power Failure Consideration"
267 // When the SUS_PWR_FLR bit is set, it indicates the SUS well power is lost.
268 // This bit is in the SUS Well and defaults to 1\92b1 based on RSMRST# assertion (not cleared by any type of reset).
269 // System BIOS should follow cold boot path if SUS_PWR_FLR (PBASE + 0x20[14]),
270 // GEN_RST_STS (PBASE + 0x20[9]) or PWRBTNOR_STS (ABASE + 0x00[11]) is set to 1\92b1
271 // regardless of the value in the SLP_TYP (ABASE + 0x04[12:10]) field.
273 GenPmCon1
= MmioRead16 (PMC_BASE_ADDRESS
+ R_PCH_PMC_GEN_PMCON_1
);
276 // Read the ACPI registers
278 Pm1Sts
= IoRead16 (ACPI_BASE_ADDRESS
+ R_PCH_ACPI_PM1_STS
);
279 Pm1Cnt
= IoRead16 (ACPI_BASE_ADDRESS
+ R_PCH_ACPI_PM1_CNT
);
281 if ((GenPmCon1
& (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR
| B_PCH_PMC_GEN_PMCON_GEN_RST_STS
)) ||
282 (Pm1Sts
& B_PCH_ACPI_PM1_STS_PRBTNOR
)) {
284 // If power failure indicator, then don't attempt s3 resume.
285 // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has
286 // lost already. This is to make sure no one will use PM1_CNT to check for S3 after
289 if ((Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
) == V_PCH_ACPI_PM1_CNT_S3
) {
290 Pm1Cnt
= ((Pm1Cnt
& ~B_PCH_ACPI_PM1_CNT_SLP_TYP
) | V_PCH_ACPI_PM1_CNT_S5
);
291 IoWrite16 (ACPI_BASE_ADDRESS
+ R_PCH_ACPI_PM1_CNT
, Pm1Cnt
);
294 // Clear Wake Status (WAK_STS)
298 // Get sleep type if a wake event occurred and there is no power failure
300 if ((Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
) == V_PCH_ACPI_PM1_CNT_S3
) {
301 *SleepType
= Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
;
303 } else if ((Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
) == V_PCH_ACPI_PM1_CNT_S4
) {
304 *SleepType
= Pm1Cnt
& B_PCH_ACPI_PM1_CNT_SLP_TYP
;
313 IN CONST EFI_PEI_SERVICES
**PeiServices
317 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*PeiReadOnlyVarPpi
;
319 SYSTEM_CONFIGURATION SystemConfiguration
;
320 BOOLEAN FastBootEnabledStatus
;
322 FastBootEnabledStatus
= FALSE
;
323 Status
= (**PeiServices
).LocatePpi (
325 &gEfiPeiReadOnlyVariable2PpiGuid
,
328 (void **)&PeiReadOnlyVarPpi
330 if (Status
== EFI_SUCCESS
) {
331 VarSize
= sizeof (SYSTEM_CONFIGURATION
);
332 Status
= PeiReadOnlyVarPpi
->GetVariable (
334 PLATFORM_SETUP_VARIABLE_NAME
,
335 &gEfiSetupVariableGuid
,
340 if (Status
== EFI_SUCCESS
) {
341 if (SystemConfiguration
.FastBoot
!= 0) {
342 FastBootEnabledStatus
= TRUE
;
347 return FastBootEnabledStatus
;
351 Given the current boot mode, and a proposed new boot mode, determine
352 which has priority. If the new boot mode has higher priority, then
353 make it the current boot mode.
355 @param CurrentBootMode pointer to current planned boot mode
356 @param NewBootMode proposed boot mode
358 @retval EFI_NOT_FOUND if either boot mode is not recognized
359 @retval EFI_SUCCESS if both boot mode values were recognized and
364 IN OUT EFI_BOOT_MODE
*CurrentBootMode
,
365 IN EFI_BOOT_MODE NewBootMode
372 // Find the position of the current boot mode in our priority array
374 for ( CurrentIndex
= 0;
375 CurrentIndex
< ARRAY_SIZE (mBootModePriority
);
377 if (mBootModePriority
[CurrentIndex
] == *CurrentBootMode
) {
381 if (CurrentIndex
>= ARRAY_SIZE (mBootModePriority
)) {
382 return EFI_NOT_FOUND
;
386 // Find the position of the new boot mode in our priority array
389 NewIndex
< ARRAY_SIZE (mBootModePriority
);
391 if (mBootModePriority
[NewIndex
] == NewBootMode
) {
393 // If this new boot mode occurs before the current boot mode in the
394 // priority array, then take it.
396 if (NewIndex
< CurrentIndex
) {
397 *CurrentBootMode
= NewBootMode
;
402 return EFI_NOT_FOUND
;