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