]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/PlatformInitPei/BootMode.c
ArmVirtPkg/PrePi ARM CLANG35: drop incompatible command line option
[mirror_edk2.git] / Vlv2TbltDevicePkg / PlatformInitPei / 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
26 #include "PlatformEarlyInit.h"
27
28
29 #define NORMALMODE 0
30 #define RECOVERYMODE 1
31 #define SAFEMODE 2
32 #define MANUFACTURINGMODE 3
33
34 #define GPIO_SSUS_OFFSET 0x2000
35 #define PMU_PWRBTN_B_OFFSET 0x88
36
37 EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = {
38 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
39 &gEfiPeiBootInRecoveryModePpiGuid,
40 NULL
41 };
42
43 /**
44 Return the setting of the Bios configuration jumper
45
46 @param VOID
47
48 @retval RECOVERYMODE jumper set to recovery mode
49 @retval SAFEMODE jumper set to config mode
50 @retval NORMALMODE jumper in normal mode
51
52 **/
53 UINTN
54 GetConfigJumper(
55 IN CONST EFI_PEI_SERVICES **PeiServices,
56 IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
57 )
58 {
59 //
60 // Do the Forced recovery detection based on logic chart above
61 //
62 if (IsRecoveryJumper(PeiServices, PlatformInfoHob)) {
63 return RECOVERYMODE;
64 } else {
65 return NORMALMODE;
66 }
67 }
68
69 BOOLEAN
70 CheckIfRecoveryMode(
71 IN CONST EFI_PEI_SERVICES **PeiServices,
72 IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
73 )
74 {
75 if (GetConfigJumper(PeiServices, PlatformInfoHob) == RECOVERYMODE) {
76 return TRUE;
77 }
78 return FALSE;
79 }
80
81 BOOLEAN
82 CheckIfSafeMode(
83 IN CONST EFI_PEI_SERVICES **PeiServices,
84 IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
85 )
86 {
87 if (GetConfigJumper(PeiServices, PlatformInfoHob) == SAFEMODE) {
88 return TRUE;
89 }
90 return FALSE;
91 }
92
93 BOOLEAN
94 CheckIfManufacturingMode (
95 IN CONST EFI_PEI_SERVICES **PeiServices
96 )
97 {
98 EFI_STATUS Status;
99 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
100 UINT32 Attributes;
101 UINTN DataSize;
102 CHAR16 VarName[] = MFGMODE_VARIABLE_NAME;
103 UINT8 MfgMode;
104
105 Status = (*PeiServices)->LocatePpi (
106 PeiServices,
107 &gEfiPeiReadOnlyVariable2PpiGuid,
108 0,
109 NULL,
110 (void **)&Variable
111 );
112 ASSERT_EFI_ERROR (Status);
113
114 //
115 // Check if SW MMJ mode
116 //
117 Attributes = (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS);
118 DataSize = sizeof (MFG_MODE_VAR);
119
120 Status = Variable->GetVariable (
121 Variable,
122 VarName,
123 &gMfgModeVariableGuid,
124 &Attributes,
125 &DataSize,
126 &MfgMode
127 );
128 if (!(EFI_ERROR (Status))) {
129 return TRUE;
130 }
131 return FALSE;
132 }
133
134 EFI_STATUS
135 UpdateBootMode (
136 IN CONST EFI_PEI_SERVICES **PeiServices,
137 IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
138 )
139 {
140 EFI_STATUS Status;
141 EFI_BOOT_MODE BootMode;
142 UINT16 SleepType;
143 CHAR16 *strBootMode;
144 PEI_CAPSULE_PPI *Capsule;
145 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
146 SYSTEM_CONFIGURATION SystemConfiguration;
147 UINTN VarSize;
148 volatile UINT32 GpioValue;
149 BOOLEAN IsFirstBoot;
150 UINT32 Data32;
151
152 Status = (*PeiServices)->GetBootMode(
153 PeiServices,
154 &BootMode
155 );
156 ASSERT_EFI_ERROR (Status);
157 if (BootMode == BOOT_IN_RECOVERY_MODE){
158 return Status;
159 }
160 GetWakeupEventAndSaveToHob (PeiServices);
161
162 //
163 // Let's assume things are OK if not told otherwise
164 //
165 BootMode = BOOT_WITH_FULL_CONFIGURATION;
166
167 //
168 // When this boot is WDT reset, the system needs booting with CrashDump function eanbled.
169 //
170 Data32 = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_TCO_STS);
171
172 //
173 // Check Power Button, click the power button, the system will boot in fast boot mode,
174 // if it is pressed and hold for a second, it will boot in FullConfiguration/setup mode.
175 //
176 GpioValue = MmioRead32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + PMU_PWRBTN_B_OFFSET); // The value of GPIOS_16 (PMU_PWRBTN_B)
177 if (((GpioValue & BIT0) != 0)&&((Data32 & B_PCH_TCO_STS_SECOND_TO) != B_PCH_TCO_STS_SECOND_TO)){
178 IsFirstBoot = PcdGetBool(PcdBootState);
179 if (!IsFirstBoot){
180 VarSize = sizeof (SYSTEM_CONFIGURATION);
181 ZeroMem (&SystemConfiguration, sizeof (SYSTEM_CONFIGURATION));
182
183 Status = (*PeiServices)->LocatePpi (
184 PeiServices,
185 &gEfiPeiReadOnlyVariable2PpiGuid,
186 0,
187 NULL,
188 (void **)&Variable
189 );
190 ASSERT_EFI_ERROR (Status);
191
192 //
193 // Use normal setup default from NVRAM variable,
194 // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable.
195 //
196 VarSize = sizeof(SYSTEM_CONFIGURATION);
197 Status = Variable->GetVariable (
198 Variable,
199 L"Setup",
200 &gEfiSetupVariableGuid,
201 NULL,
202 &VarSize,
203 &SystemConfiguration
204 );
205 if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
206 //The setup variable is corrupted
207 VarSize = sizeof(SYSTEM_CONFIGURATION);
208 Status = Variable->GetVariable(
209 Variable,
210 L"SetupRecovery",
211 &gEfiSetupVariableGuid,
212 NULL,
213 &VarSize,
214 &SystemConfiguration
215 );
216 ASSERT_EFI_ERROR (Status);
217 }
218
219 if (SystemConfiguration.FastBoot == 1) {
220 BootMode = BOOT_WITH_MINIMAL_CONFIGURATION;
221 }
222 }
223 }
224
225 //
226 // Check if we need to boot in forced recovery mode
227 //
228 if (CheckIfRecoveryMode(PeiServices, PlatformInfoHob)) {
229 BootMode = BOOT_IN_RECOVERY_MODE;
230 }
231
232 if (BootMode == BOOT_IN_RECOVERY_MODE) {
233 Status = (*PeiServices)->InstallPpi (
234 PeiServices,
235 &mPpiListRecoveryBootMode
236 );
237 ASSERT_EFI_ERROR (Status);
238 } else {
239 if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) {
240 switch (SleepType) {
241 case V_PCH_ACPI_PM1_CNT_S3:
242 BootMode = BOOT_ON_S3_RESUME;
243
244 //
245 // Determine if we're in capsule update mode
246 //
247 Status = (*PeiServices)->LocatePpi (
248 PeiServices,
249 &gPeiCapsulePpiGuid,
250 0,
251 NULL,
252 (void **)&Capsule
253 );
254
255 if (Status == EFI_SUCCESS) {
256 if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES**)PeiServices) == EFI_SUCCESS) {
257 BootMode = BOOT_ON_FLASH_UPDATE;
258 }
259 }
260
261 break;
262
263 case V_PCH_ACPI_PM1_CNT_S4:
264 BootMode = BOOT_ON_S4_RESUME;
265 break;
266
267 case V_PCH_ACPI_PM1_CNT_S5:
268 BootMode = BOOT_ON_S5_RESUME;
269 break;
270 } // switch (SleepType)
271 }
272
273 //
274 // Check for Safe Mode
275 //
276 }
277
278 switch (BootMode) {
279 case BOOT_WITH_FULL_CONFIGURATION:
280 strBootMode = L"BOOT_WITH_FULL_CONFIGURATION";
281 break;
282 case BOOT_WITH_MINIMAL_CONFIGURATION:
283 strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION";
284 break;
285 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
286 strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";
287 break;
288 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
289 strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";
290 break;
291 case BOOT_WITH_DEFAULT_SETTINGS:
292 strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS";
293 break;
294 case BOOT_ON_S4_RESUME:
295 strBootMode = L"BOOT_ON_S4_RESUME";
296 break;
297 case BOOT_ON_S5_RESUME:
298 strBootMode = L"BOOT_ON_S5_RESUME";
299 break;
300 case BOOT_ON_S2_RESUME:
301 strBootMode = L"BOOT_ON_S2_RESUME";
302 break;
303 case BOOT_ON_S3_RESUME:
304 strBootMode = L"BOOT_ON_S3_RESUME";
305 break;
306 case BOOT_ON_FLASH_UPDATE:
307 strBootMode = L"BOOT_ON_FLASH_UPDATE";
308 break;
309 case BOOT_IN_RECOVERY_MODE:
310 strBootMode = L"BOOT_IN_RECOVERY_MODE";
311 break;
312 default:
313 strBootMode = L"Unknown boot mode";
314 } // switch (BootMode)
315
316 DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode));
317 Status = (*PeiServices)->SetBootMode(
318 PeiServices,
319 BootMode
320 );
321 ASSERT_EFI_ERROR (Status);
322
323 return Status;
324 }
325
326 /**
327 Get sleep type after wakeup
328
329 @param PeiServices Pointer to the PEI Service Table.
330 @param SleepType Sleep type to be returned.
331
332 @retval TRUE A wake event occured without power failure.
333 @retval FALSE Power failure occured or not a wakeup.
334
335 **/
336 BOOLEAN
337 GetSleepTypeAfterWakeup (
338 IN CONST EFI_PEI_SERVICES **PeiServices,
339 OUT UINT16 *SleepType
340 )
341 {
342 UINT16 Pm1Sts;
343 UINT16 Pm1Cnt;
344 UINT16 GenPmCon1;
345 GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);
346
347 //
348 // Read the ACPI registers
349 //
350 Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);
351 Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT);
352
353 if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) ||
354 (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) {
355 //
356 // If power failure indicator, then don't attempt s3 resume.
357 // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has
358 // lost already. This is to make sure no one will use PM1_CNT to check for S3 after
359 // power failure.
360 //
361 if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
362 Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5);
363 IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
364 }
365 //
366 // Clear Wake Status (WAK_STS)
367 //
368 IoWrite16 ((ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_WAK);
369 }
370 //
371 // Get sleep type if a wake event occurred and there is no power failure
372 //
373 if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
374 *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
375 return TRUE;
376 } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4){
377 *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
378 return TRUE;
379 }
380 return FALSE;
381 }
382
383 VOID
384 SetPlatformBootMode (
385 IN CONST EFI_PEI_SERVICES **PeiServices,
386 IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
387 )
388 {
389 EFI_PLATFORM_SETUP_ID PlatformSetupId;
390
391 ZeroMem(&PlatformSetupId, sizeof (EFI_PLATFORM_SETUP_ID));
392
393 CopyMem (&PlatformSetupId.SetupGuid,
394 &gEfiNormalSetupGuid,
395 sizeof (EFI_GUID));
396
397 if (CheckIfRecoveryMode(PeiServices, PlatformInfoHob)) {
398 //
399 // Recovery mode
400 //
401 CopyMem (&PlatformSetupId.SetupName,
402 &NORMAL_SETUP_NAME,
403 StrSize (NORMAL_SETUP_NAME));
404 PlatformSetupId.PlatformBootMode = PLATFORM_RECOVERY_MODE;
405 } else if (CheckIfSafeMode(PeiServices, PlatformInfoHob)) {
406 //
407 // Safe mode also called config mode or maintenace mode.
408 //
409 CopyMem (&PlatformSetupId.SetupName,
410 &NORMAL_SETUP_NAME,
411 StrSize (NORMAL_SETUP_NAME));
412 PlatformSetupId.PlatformBootMode = PLATFORM_SAFE_MODE;
413
414 } else if(0) { // else if (CheckIfManufacturingMode(PeiServices)) {
415 //
416 // Manufacturing mode
417 //
418 CopyMem (&PlatformSetupId.SetupName,
419 MANUFACTURE_SETUP_NAME,
420 StrSize (MANUFACTURE_SETUP_NAME));
421 PlatformSetupId.PlatformBootMode = PLATFORM_MANUFACTURING_MODE;
422
423 } else {
424 //
425 // Default to normal mode.
426 //
427 CopyMem (&PlatformSetupId.SetupName,
428 &NORMAL_SETUP_NAME,
429 StrSize (NORMAL_SETUP_NAME));
430 PlatformSetupId.PlatformBootMode = PLATFORM_NORMAL_MODE;
431 }
432
433 BuildGuidDataHob (
434 &gEfiPlatformBootModeGuid,
435 &PlatformSetupId,
436 sizeof (EFI_PLATFORM_SETUP_ID)
437 );
438 return;
439 }