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