]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/PlatformPei/BootMode.c
MdeModulePkg/CapsuleApp: Center bitmap at bottom of screen
[mirror_edk2.git] / Vlv2TbltDevicePkg / PlatformPei / BootMode.c
1 /** @file
2
3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
4
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.
9
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.
12
13
14 Module Name:
15
16
17 BootMode.c
18
19 Abstract:
20
21 EFI PEIM to provide the platform support functionality on the Thurley.
22
23
24 --*/
25 #include "CommonHeader.h"
26 #include "Platform.h"
27 #include "PlatformBaseAddresses.h"
28 #include "PchAccess.h"
29 #include "PlatformBootMode.h"
30 #include <Guid/SetupVariable.h>
31
32 #include <Guid/BootState.h>
33
34 //
35 // Priority of our boot modes, highest priority first
36 //
37 EFI_BOOT_MODE mBootModePriority[] = {
38 BOOT_IN_RECOVERY_MODE,
39 BOOT_WITH_DEFAULT_SETTINGS,
40 BOOT_ON_FLASH_UPDATE,
41 BOOT_ON_S2_RESUME,
42 BOOT_ON_S3_RESUME,
43 BOOT_ON_S4_RESUME,
44 BOOT_WITH_MINIMAL_CONFIGURATION,
45 BOOT_ASSUMING_NO_CONFIGURATION_CHANGES,
46 BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS,
47 BOOT_WITH_FULL_CONFIGURATION,
48 BOOT_ON_S5_RESUME
49 };
50
51 EFI_PEI_NOTIFY_DESCRIPTOR mCapsuleNotifyList[1] = {
52 {
53 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
54 &gPeiCapsulePpiGuid,
55 CapsulePpiNotifyCallback
56 }
57 };
58
59 BOOLEAN
60 GetSleepTypeAfterWakeup (
61 IN CONST EFI_PEI_SERVICES **PeiServices,
62 OUT UINT16 *SleepType
63 );
64
65 EFI_STATUS
66 EFIAPI
67 CapsulePpiNotifyCallback (
68 IN EFI_PEI_SERVICES **PeiServices,
69 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
70 IN VOID *Ppi
71 )
72 {
73 EFI_STATUS Status;
74 EFI_BOOT_MODE BootMode;
75 PEI_CAPSULE_PPI *Capsule;
76
77 Status = (*PeiServices)->GetBootMode((const EFI_PEI_SERVICES **)PeiServices, &BootMode);
78 ASSERT_EFI_ERROR (Status);
79
80 if (BootMode == BOOT_ON_S3_RESUME) {
81 //
82 // Determine if we're in capsule update mode
83 //
84 Status = (*PeiServices)->LocatePpi ((const EFI_PEI_SERVICES **)PeiServices,
85 &gPeiCapsulePpiGuid,
86 0,
87 NULL,
88 (VOID **)&Capsule
89 );
90
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);
96 }
97 }
98 }
99
100 return Status;
101 }
102
103 /**
104 Check CMOS register bit to determine if previous boot was successful
105
106 @param PeiServices pointer to the PEI Service Table
107
108 @retval TRUE - Previous Boot was success
109 @retval FALSE - Previous Boot wasn't success
110
111 **/
112 BOOLEAN
113 IsPreviousBootSuccessful(
114 IN CONST EFI_PEI_SERVICES **PeiServices
115
116 )
117 {
118 EFI_STATUS Status;
119 BOOLEAN BootState;
120 UINTN DataSize;
121 CHAR16 VarName[] = BOOT_STATE_VARIABLE_NAME;
122 EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiVar;
123
124 Status = (**PeiServices).LocatePpi (
125 PeiServices,
126 &gEfiPeiReadOnlyVariable2PpiGuid,
127 0,
128 NULL,
129 (void **)&PeiVar
130 );
131 ASSERT_EFI_ERROR (Status);
132
133 //
134 // Get last Boot State Variable to confirm that it is not a first boot .
135 //
136
137 DataSize = sizeof (BOOLEAN);
138 Status = PeiVar->GetVariable (
139 PeiVar,
140 VarName,
141 &gEfiBootStateGuid,
142 NULL,
143 &DataSize,
144 &BootState
145 );
146 if (EFI_ERROR (Status) || (BootState == TRUE)) {
147 return FALSE;
148 }
149
150 DEBUG ((EFI_D_INFO, "Previous boot cycle successfully completed handover to OS\n"));
151 return TRUE;
152 }
153 #ifdef NOCS_S3_SUPPORT
154 EFI_STATUS
155 UpdateBootMode (
156 IN CONST EFI_PEI_SERVICES **PeiServices
157 )
158 {
159 EFI_STATUS Status;
160 EFI_BOOT_MODE BootMode;
161 UINT16 SleepType;
162 CHAR16 *strBootMode;
163
164 Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode);
165 ASSERT_EFI_ERROR (Status);
166 if (BootMode == BOOT_IN_RECOVERY_MODE){
167 return Status;
168 }
169
170 //
171 // Let's assume things are OK if not told otherwise
172 //
173 BootMode = BOOT_WITH_FULL_CONFIGURATION;
174
175 if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) {
176 switch (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);
181 break;
182
183 case V_PCH_ACPI_PM1_CNT_S4:
184 BootMode = BOOT_ON_S4_RESUME;
185 break;
186
187 case V_PCH_ACPI_PM1_CNT_S5:
188 BootMode = BOOT_ON_S5_RESUME;
189 break;
190 } // switch (SleepType)
191 }
192
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);
196 }
197
198 switch (BootMode) {
199 case BOOT_WITH_FULL_CONFIGURATION:
200 strBootMode = L"BOOT_WITH_FULL_CONFIGURATION";
201 break;
202 case BOOT_WITH_MINIMAL_CONFIGURATION:
203 strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION";
204 break;
205 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
206 strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";
207 break;
208 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
209 strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";
210 break;
211 case BOOT_WITH_DEFAULT_SETTINGS:
212 strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS";
213 break;
214 case BOOT_ON_S4_RESUME:
215 strBootMode = L"BOOT_ON_S4_RESUME";
216 break;
217 case BOOT_ON_S5_RESUME:
218 strBootMode = L"BOOT_ON_S5_RESUME";
219 break;
220 case BOOT_ON_S2_RESUME:
221 strBootMode = L"BOOT_ON_S2_RESUME";
222 break;
223 case BOOT_ON_S3_RESUME:
224 strBootMode = L"BOOT_ON_S3_RESUME";
225
226 break;
227 case BOOT_ON_FLASH_UPDATE:
228 strBootMode = L"BOOT_ON_FLASH_UPDATE";
229 break;
230 case BOOT_IN_RECOVERY_MODE:
231 strBootMode = L"BOOT_IN_RECOVERY_MODE";
232 break;
233 default:
234 strBootMode = L"Unknown boot mode";
235 } // switch (BootMode)
236
237 DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode));
238 Status = (*PeiServices)->SetBootMode(PeiServices, BootMode);
239 ASSERT_EFI_ERROR (Status);
240
241 return Status;
242 }
243 #endif
244
245 /**
246 Get sleep type after wakeup
247
248 @param PeiServices Pointer to the PEI Service Table.
249 @param SleepType Sleep type to be returned.
250
251 @retval TRUE A wake event occured without power failure.
252 @retval FALSE Power failure occured or not a wakeup.
253
254 **/
255 BOOLEAN
256 GetSleepTypeAfterWakeup (
257 IN CONST EFI_PEI_SERVICES **PeiServices,
258 OUT UINT16 *SleepType
259 )
260 {
261 UINT16 Pm1Sts;
262 UINT16 Pm1Cnt;
263 UINT16 GenPmCon1;
264 //
265 // VLV BIOS Specification 0.6.2 - Section 18.4, "Power Failure Consideration"
266 //
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.
272 //
273 GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);
274
275 //
276 // Read the ACPI registers
277 //
278 Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);
279 Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT);
280
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)) {
283 //
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
287 // power failure.
288 //
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);
292 }
293 //
294 // Clear Wake Status (WAK_STS)
295 //
296 }
297 //
298 // Get sleep type if a wake event occurred and there is no power failure
299 //
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;
302 return TRUE;
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;
305 return TRUE;
306 }
307 return FALSE;
308 }
309
310 BOOLEAN
311 EFIAPI
312 IsFastBootEnabled (
313 IN CONST EFI_PEI_SERVICES **PeiServices
314 )
315 {
316 EFI_STATUS Status;
317 EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi;
318 UINTN VarSize;
319 SYSTEM_CONFIGURATION SystemConfiguration;
320 BOOLEAN FastBootEnabledStatus;
321
322 FastBootEnabledStatus = FALSE;
323 Status = (**PeiServices).LocatePpi (
324 PeiServices,
325 &gEfiPeiReadOnlyVariable2PpiGuid,
326 0,
327 NULL,
328 (void **)&PeiReadOnlyVarPpi
329 );
330 if (Status == EFI_SUCCESS) {
331 VarSize = sizeof (SYSTEM_CONFIGURATION);
332 Status = PeiReadOnlyVarPpi->GetVariable (
333 PeiReadOnlyVarPpi,
334 PLATFORM_SETUP_VARIABLE_NAME,
335 &gEfiSetupVariableGuid,
336 NULL,
337 &VarSize,
338 &SystemConfiguration
339 );
340 if (Status == EFI_SUCCESS) {
341 if (SystemConfiguration.FastBoot != 0) {
342 FastBootEnabledStatus = TRUE;
343 }
344 }
345 }
346
347 return FastBootEnabledStatus;
348 }
349
350 /**
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.
354
355 @param CurrentBootMode pointer to current planned boot mode
356 @param NewBootMode proposed boot mode
357
358 @retval EFI_NOT_FOUND if either boot mode is not recognized
359 @retval EFI_SUCCESS if both boot mode values were recognized and
360 were processed.
361 **/
362 EFI_STATUS
363 PrioritizeBootMode (
364 IN OUT EFI_BOOT_MODE *CurrentBootMode,
365 IN EFI_BOOT_MODE NewBootMode
366 )
367 {
368 UINT32 CurrentIndex;
369 UINT32 NewIndex;
370
371 //
372 // Find the position of the current boot mode in our priority array
373 //
374 for ( CurrentIndex = 0;
375 CurrentIndex < ARRAY_SIZE (mBootModePriority);
376 CurrentIndex++) {
377 if (mBootModePriority[CurrentIndex] == *CurrentBootMode) {
378 break;
379 }
380 }
381 if (CurrentIndex >= ARRAY_SIZE (mBootModePriority)) {
382 return EFI_NOT_FOUND;
383 }
384
385 //
386 // Find the position of the new boot mode in our priority array
387 //
388 for ( NewIndex = 0;
389 NewIndex < ARRAY_SIZE (mBootModePriority);
390 NewIndex++) {
391 if (mBootModePriority[NewIndex] == NewBootMode) {
392 //
393 // If this new boot mode occurs before the current boot mode in the
394 // priority array, then take it.
395 //
396 if (NewIndex < CurrentIndex) {
397 *CurrentBootMode = NewBootMode;
398 }
399 return EFI_SUCCESS;
400 }
401 }
402 return EFI_NOT_FOUND;
403 }