Home | History | Annotate | Download | only in PlatformInitPei
      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