Home | History | Annotate | Download | only in PlatformHelperLib
      1 /** @file
      2 Implementation of helper routines for DXE environment.
      3 
      4 Copyright (c) 2013 - 2016 Intel Corporation.
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <PiDxe.h>
     17 
     18 #include <Library/UefiBootServicesTableLib.h>
     19 #include <Library/S3BootScriptLib.h>
     20 #include <Library/DxeServicesLib.h>
     21 #include <Library/UefiRuntimeServicesTableLib.h>
     22 #include <Protocol/SmmBase2.h>
     23 #include <Protocol/Spi.h>
     24 #include <Protocol/VariableLock.h>
     25 
     26 #include <Guid/MemoryConfigData.h>
     27 #include <Guid/QuarkVariableLock.h>
     28 
     29 #include "CommonHeader.h"
     30 
     31 #define FLASH_BLOCK_SIZE            SIZE_4KB
     32 
     33 //
     34 // Global variables.
     35 //
     36 EFI_SPI_PROTOCOL                    *mPlatHelpSpiProtocolRef = NULL;
     37 
     38 //
     39 // Routines defined in other source modules of this component.
     40 //
     41 
     42 //
     43 // Routines local to this component.
     44 //
     45 
     46 //
     47 // Routines shared with other souce modules in this component.
     48 //
     49 
     50 EFI_SPI_PROTOCOL *
     51 LocateSpiProtocol (
     52   IN  EFI_SMM_SYSTEM_TABLE2             *Smst
     53   )
     54 {
     55   if (mPlatHelpSpiProtocolRef == NULL) {
     56     if (Smst != NULL) {
     57       Smst->SmmLocateProtocol (
     58               &gEfiSmmSpiProtocolGuid,
     59               NULL,
     60               (VOID **) &mPlatHelpSpiProtocolRef
     61               );
     62     } else {
     63       gBS->LocateProtocol (
     64              &gEfiSpiProtocolGuid,
     65              NULL,
     66              (VOID **) &mPlatHelpSpiProtocolRef
     67              );
     68     }
     69     ASSERT (mPlatHelpSpiProtocolRef != NULL);
     70   }
     71   return mPlatHelpSpiProtocolRef;
     72 }
     73 
     74 //
     75 // Routines exported by this source module.
     76 //
     77 
     78 /**
     79   Find pointer to RAW data in Firmware volume file.
     80 
     81   @param   FvNameGuid       Firmware volume to search. If == NULL search all.
     82   @param   FileNameGuid     Firmware volume file to search for.
     83   @param   SectionData      Pointer to RAW data section of found file.
     84   @param   SectionDataSize  Pointer to UNITN to get size of RAW data.
     85 
     86   @retval  EFI_SUCCESS            Raw Data found.
     87   @retval  EFI_INVALID_PARAMETER  FileNameGuid == NULL.
     88   @retval  EFI_NOT_FOUND          Firmware volume file not found.
     89   @retval  EFI_UNSUPPORTED        Unsupported in current enviroment (PEI or DXE).
     90 
     91 **/
     92 EFI_STATUS
     93 EFIAPI
     94 PlatformFindFvFileRawDataSection (
     95   IN CONST EFI_GUID                 *FvNameGuid OPTIONAL,
     96   IN CONST EFI_GUID                 *FileNameGuid,
     97   OUT VOID                          **SectionData,
     98   OUT UINTN                         *SectionDataSize
     99   )
    100 {
    101   if (FileNameGuid == NULL || SectionData == NULL || SectionDataSize == NULL) {
    102     return EFI_INVALID_PARAMETER;
    103   }
    104   if (FvNameGuid != NULL) {
    105     return EFI_UNSUPPORTED;  // Searching in specific FV unsupported in DXE.
    106   }
    107 
    108   return GetSectionFromAnyFv (FileNameGuid, EFI_SECTION_RAW, 0, SectionData, SectionDataSize);
    109 }
    110 
    111 /**
    112   Find free spi protect register and write to it to protect a flash region.
    113 
    114   @param   DirectValue      Value to directly write to register.
    115                             if DirectValue == 0 the use Base & Length below.
    116   @param   BaseAddress      Base address of region in Flash Memory Map.
    117   @param   Length           Length of region to protect.
    118 
    119   @retval  EFI_SUCCESS      Free spi protect register found & written.
    120   @retval  EFI_NOT_FOUND    Free Spi protect register not found.
    121   @retval  EFI_DEVICE_ERROR Unable to write to spi protect register.
    122 **/
    123 EFI_STATUS
    124 EFIAPI
    125 PlatformWriteFirstFreeSpiProtect (
    126   IN CONST UINT32                         DirectValue,
    127   IN CONST UINT32                         BaseAddress,
    128   IN CONST UINT32                         Length
    129   )
    130 {
    131   UINT32                            FreeOffset;
    132   UINT32                            PchRootComplexBar;
    133   EFI_STATUS                        Status;
    134 
    135   PchRootComplexBar = QNC_RCRB_BASE;
    136 
    137   Status = WriteFirstFreeSpiProtect (
    138              PchRootComplexBar,
    139              DirectValue,
    140              BaseAddress,
    141              Length,
    142              &FreeOffset
    143              );
    144 
    145   if (!EFI_ERROR (Status)) {
    146     S3BootScriptSaveMemWrite (
    147       S3BootScriptWidthUint32,
    148         (UINTN) (PchRootComplexBar + FreeOffset),
    149         1,
    150         (VOID *) (UINTN) (PchRootComplexBar + FreeOffset)
    151         );
    152   }
    153 
    154   return Status;
    155 }
    156 
    157 /**
    158   Lock legacy SPI static configuration information.
    159 
    160   Function will assert if unable to lock config.
    161 
    162 **/
    163 VOID
    164 EFIAPI
    165 PlatformFlashLockConfig (
    166   VOID
    167   )
    168 {
    169   EFI_STATUS        Status;
    170   EFI_SPI_PROTOCOL  *SpiProtocol;
    171 
    172   //
    173   // Enable lock of legacy SPI static configuration information.
    174   //
    175 
    176   SpiProtocol = LocateSpiProtocol (NULL);  // This routine will not be called in SMM.
    177   ASSERT (SpiProtocol != NULL);
    178   if (SpiProtocol != NULL) {
    179     Status = SpiProtocol->Lock (SpiProtocol);
    180 
    181     if (!EFI_ERROR (Status)) {
    182       DEBUG ((EFI_D_INFO, "Platform: Spi Config Locked Down\n"));
    183     } else if (Status == EFI_ACCESS_DENIED) {
    184       DEBUG ((EFI_D_INFO, "Platform: Spi Config already locked down\n"));
    185     } else {
    186       ASSERT_EFI_ERROR (Status);
    187     }
    188   }
    189 }
    190 
    191 /**
    192   Platform Variable Lock.
    193 
    194   @retval EFI_SUCCESS           Platform Variable Lock successful.
    195   @retval EFI_NOT_FOUND         No protocol instances were found that match Protocol and
    196                                 Registration.
    197 
    198 **/
    199 VOID
    200 EFIAPI
    201 PlatformVariableLock (
    202   )
    203 {
    204   EFI_STATUS                        Status;
    205   EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;
    206 
    207   Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
    208   ASSERT_EFI_ERROR (Status);
    209 
    210   Status = VariableLockProtocol->RequestToLock (
    211                                    VariableLockProtocol,
    212                                    QUARK_VARIABLE_LOCK_NAME,
    213                                    &gQuarkVariableLockGuid
    214                                    );
    215   ASSERT_EFI_ERROR (Status);
    216 
    217   // Memory Config Data shouldn't be writable when Quark Variable Lock is enabled.
    218   Status = VariableLockProtocol->RequestToLock (
    219                                    VariableLockProtocol,
    220                                    EFI_MEMORY_CONFIG_DATA_NAME,
    221                                    &gEfiMemoryConfigDataGuid
    222                                    );
    223   ASSERT_EFI_ERROR (Status);
    224 }
    225 
    226 /**
    227   Lock regions and config of SPI flash given the policy for this platform.
    228 
    229   Function will assert if unable to lock regions or config.
    230 
    231   @param   PreBootPolicy    If TRUE do Pre Boot Flash Lock Policy.
    232 
    233 **/
    234 VOID
    235 EFIAPI
    236 PlatformFlashLockPolicy (
    237   IN CONST BOOLEAN                        PreBootPolicy
    238   )
    239 {
    240   EFI_STATUS                        Status;
    241   UINT64                            CpuAddressNvStorage;
    242   UINT64                            CpuAddressFlashDevice;
    243   UINT64                            SpiAddress;
    244   EFI_BOOT_MODE                     BootMode;
    245   UINTN                             SpiFlashDeviceSize;
    246 
    247   BootMode = GetBootModeHob ();
    248 
    249   SpiFlashDeviceSize = (UINTN) PcdGet32 (PcdSpiFlashDeviceSize);
    250   CpuAddressFlashDevice = SIZE_4GB - SpiFlashDeviceSize;
    251   DEBUG (
    252       (EFI_D_INFO,
    253       "Platform:FlashDeviceSize = 0x%08x Bytes\n",
    254       SpiFlashDeviceSize)
    255       );
    256 
    257   //
    258   // If not in update or recovery mode, lock stuff down
    259   //
    260   if ((BootMode != BOOT_IN_RECOVERY_MODE) && (BootMode != BOOT_ON_FLASH_UPDATE)) {
    261 
    262     //
    263     // Lock regions
    264     //
    265     CpuAddressNvStorage = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase);
    266 
    267     //
    268     // Lock from start of flash device up to Smi writable flash storage areas.
    269     //
    270     SpiAddress = 0;
    271     if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice))) {
    272       DEBUG (
    273         (EFI_D_INFO,
    274         "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
    275         (UINTN) SpiAddress, (UINTN)(CpuAddressNvStorage - CpuAddressFlashDevice))
    276         );
    277       Status = PlatformWriteFirstFreeSpiProtect (
    278                   0,
    279                   (UINT32) SpiAddress,
    280                   (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice)
    281                   );
    282 
    283       ASSERT_EFI_ERROR (Status);
    284     }
    285     //
    286     // Move Spi Address to after Smi writable flash storage areas.
    287     //
    288     SpiAddress = CpuAddressNvStorage - CpuAddressFlashDevice;
    289     SpiAddress += ((UINT64) PcdGet32 (PcdFlashNvStorageVariableSize));
    290 
    291     //
    292     // Lock from end of OEM area to end of flash part.
    293     //
    294     if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, SpiFlashDeviceSize - ((UINT32) SpiAddress))) {
    295       DEBUG (
    296         (EFI_D_INFO,
    297         "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
    298         (UINTN) SpiAddress,
    299         (UINTN) (SpiFlashDeviceSize - ((UINT32) SpiAddress)))
    300         );
    301       ASSERT (SpiAddress < ((UINT64) SpiFlashDeviceSize));
    302       Status = PlatformWriteFirstFreeSpiProtect (
    303                   0,
    304                   (UINT32) SpiAddress,
    305                   SpiFlashDeviceSize - ((UINT32) SpiAddress)
    306                   );
    307 
    308       ASSERT_EFI_ERROR (Status);
    309     }
    310   }
    311 
    312   //
    313   // Always Lock flash config registers if about to boot a boot option
    314   // else lock depending on boot mode.
    315   //
    316   if (PreBootPolicy || (BootMode != BOOT_ON_FLASH_UPDATE)) {
    317     PlatformFlashLockConfig ();
    318   }
    319 
    320   //
    321   // Enable Quark Variable lock if PreBootPolicy.
    322   //
    323   if (PreBootPolicy) {
    324     PlatformVariableLock ();
    325   }
    326 }
    327 
    328 /** Check if System booted with recovery Boot Stage1 image.
    329 
    330   @retval  TRUE    If system booted with recovery Boot Stage1 image.
    331   @retval  FALSE   If system booted with normal stage1 image.
    332 
    333 **/
    334 BOOLEAN
    335 EFIAPI
    336 PlatformIsBootWithRecoveryStage1 (
    337   VOID
    338   )
    339 {
    340   ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
    341   return FALSE;
    342 }
    343 
    344