1 /** @file 2 3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> 4 5 6 This program and the accompanying materials are licensed and made available under 7 8 the terms and conditions of the BSD License that accompanies this distribution. 9 10 The full text of the license may be found at 11 12 http://opensource.org/licenses/bsd-license.php. 13 14 15 16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 17 18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 19 20 21 22 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 GetConfigJumper(IN CONST EFI_PEI_SERVICES ** PeiServices,IN OUT EFI_PLATFORM_INFO_HOB * PlatformInfoHob)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 CheckIfSafeMode(IN CONST EFI_PEI_SERVICES ** PeiServices,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 CheckIfManufacturingMode(IN CONST EFI_PEI_SERVICES ** PeiServices)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, UpdateBootMode(IN CONST EFI_PEI_SERVICES ** PeiServices,IN OUT EFI_PLATFORM_INFO_HOB * PlatformInfoHob)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 GetSleepTypeAfterWakeup(IN CONST EFI_PEI_SERVICES ** PeiServices,OUT UINT16 * SleepType)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