2 Implementation of helper routines for DXE environment.
4 Copyright (c) 2013 - 2016 Intel Corporation.
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
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.
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>
26 #include <Guid/MemoryConfigData.h>
27 #include <Guid/QuarkVariableLock.h>
29 #include "CommonHeader.h"
31 #define FLASH_BLOCK_SIZE SIZE_4KB
36 EFI_SPI_PROTOCOL
*mPlatHelpSpiProtocolRef
= NULL
;
39 // Routines defined in other source modules of this component.
43 // Routines local to this component.
47 // Routines shared with other souce modules in this component.
52 IN EFI_SMM_SYSTEM_TABLE2
*Smst
55 if (mPlatHelpSpiProtocolRef
== NULL
) {
57 Smst
->SmmLocateProtocol (
58 &gEfiSmmSpiProtocolGuid
,
60 (VOID
**) &mPlatHelpSpiProtocolRef
66 (VOID
**) &mPlatHelpSpiProtocolRef
69 ASSERT (mPlatHelpSpiProtocolRef
!= NULL
);
71 return mPlatHelpSpiProtocolRef
;
75 // Routines exported by this source module.
79 Find pointer to RAW data in Firmware volume file.
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.
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).
94 PlatformFindFvFileRawDataSection (
95 IN CONST EFI_GUID
*FvNameGuid OPTIONAL
,
96 IN CONST EFI_GUID
*FileNameGuid
,
97 OUT VOID
**SectionData
,
98 OUT UINTN
*SectionDataSize
101 if (FileNameGuid
== NULL
|| SectionData
== NULL
|| SectionDataSize
== NULL
) {
102 return EFI_INVALID_PARAMETER
;
104 if (FvNameGuid
!= NULL
) {
105 return EFI_UNSUPPORTED
; // Searching in specific FV unsupported in DXE.
108 return GetSectionFromAnyFv (FileNameGuid
, EFI_SECTION_RAW
, 0, SectionData
, SectionDataSize
);
112 Find free spi protect register and write to it to protect a flash region.
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.
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.
125 PlatformWriteFirstFreeSpiProtect (
126 IN CONST UINT32 DirectValue
,
127 IN CONST UINT32 BaseAddress
,
128 IN CONST UINT32 Length
132 UINT32 PchRootComplexBar
;
135 PchRootComplexBar
= QNC_RCRB_BASE
;
137 Status
= WriteFirstFreeSpiProtect (
145 if (!EFI_ERROR (Status
)) {
146 S3BootScriptSaveMemWrite (
147 S3BootScriptWidthUint32
,
148 (UINTN
) (PchRootComplexBar
+ FreeOffset
),
150 (VOID
*) (UINTN
) (PchRootComplexBar
+ FreeOffset
)
158 Lock legacy SPI static configuration information.
160 Function will assert if unable to lock config.
165 PlatformFlashLockConfig (
170 EFI_SPI_PROTOCOL
*SpiProtocol
;
173 // Enable lock of legacy SPI static configuration information.
176 SpiProtocol
= LocateSpiProtocol (NULL
); // This routine will not be called in SMM.
177 ASSERT_EFI_ERROR (SpiProtocol
!= NULL
);
178 if (SpiProtocol
!= NULL
) {
179 Status
= SpiProtocol
->Lock (SpiProtocol
);
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"));
186 ASSERT_EFI_ERROR (Status
);
192 Platform Variable Lock.
194 @retval EFI_SUCCESS Platform Variable Lock successful.
195 @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and
201 PlatformVariableLock (
205 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLockProtocol
;
207 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**)&VariableLockProtocol
);
208 ASSERT_EFI_ERROR (Status
);
210 Status
= VariableLockProtocol
->RequestToLock (
211 VariableLockProtocol
,
212 QUARK_VARIABLE_LOCK_NAME
,
213 &gQuarkVariableLockGuid
215 ASSERT_EFI_ERROR (Status
);
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
223 ASSERT_EFI_ERROR (Status
);
227 Lock regions and config of SPI flash given the policy for this platform.
229 Function will assert if unable to lock regions or config.
231 @param PreBootPolicy If TRUE do Pre Boot Flash Lock Policy.
236 PlatformFlashLockPolicy (
237 IN CONST BOOLEAN PreBootPolicy
241 UINT64 CpuAddressNvStorage
;
242 UINT64 CpuAddressFlashDevice
;
244 EFI_BOOT_MODE BootMode
;
245 UINTN SpiFlashDeviceSize
;
247 BootMode
= GetBootModeHob ();
249 SpiFlashDeviceSize
= (UINTN
) PcdGet32 (PcdSpiFlashDeviceSize
);
250 CpuAddressFlashDevice
= SIZE_4GB
- SpiFlashDeviceSize
;
253 "Platform:FlashDeviceSize = 0x%08x Bytes\n",
258 // If not in update or recovery mode, lock stuff down
260 if ((BootMode
!= BOOT_IN_RECOVERY_MODE
) && (BootMode
!= BOOT_ON_FLASH_UPDATE
)) {
265 CpuAddressNvStorage
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
268 // Lock from start of flash device up to Smi writable flash storage areas.
271 if (!PlatformIsSpiRangeProtected ((UINT32
) SpiAddress
, (UINT32
) (CpuAddressNvStorage
- CpuAddressFlashDevice
))) {
274 "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
275 (UINTN
) SpiAddress
, (UINTN
)(CpuAddressNvStorage
- CpuAddressFlashDevice
))
277 Status
= PlatformWriteFirstFreeSpiProtect (
280 (UINT32
) (CpuAddressNvStorage
- CpuAddressFlashDevice
)
283 ASSERT_EFI_ERROR (Status
);
286 // Move Spi Address to after Smi writable flash storage areas.
288 SpiAddress
= CpuAddressNvStorage
- CpuAddressFlashDevice
;
289 SpiAddress
+= ((UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
));
292 // Lock from end of OEM area to end of flash part.
294 if (!PlatformIsSpiRangeProtected ((UINT32
) SpiAddress
, SpiFlashDeviceSize
- ((UINT32
) SpiAddress
))) {
297 "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
299 (UINTN
) (SpiFlashDeviceSize
- ((UINT32
) SpiAddress
)))
301 ASSERT (SpiAddress
< ((UINT64
) SpiFlashDeviceSize
));
302 Status
= PlatformWriteFirstFreeSpiProtect (
305 SpiFlashDeviceSize
- ((UINT32
) SpiAddress
)
308 ASSERT_EFI_ERROR (Status
);
313 // Always Lock flash config registers if about to boot a boot option
314 // else lock depending on boot mode.
316 if (PreBootPolicy
|| (BootMode
!= BOOT_ON_FLASH_UPDATE
)) {
317 PlatformFlashLockConfig ();
321 // Enable Quark Variable lock if PreBootPolicy.
324 PlatformVariableLock ();
329 Erase and Write to platform flash.
331 Routine accesses one flash block at a time, each access consists
332 of an erase followed by a write of FLASH_BLOCK_SIZE. One or both
333 of DoErase & DoWrite params must be TRUE.
336 CpuWriteAddress must be aligned to FLASH_BLOCK_SIZE.
337 DataSize must be a multiple of FLASH_BLOCK_SIZE.
339 @param Smst If != NULL then InSmm and use to locate
341 @param CpuWriteAddress Address in CPU memory map of flash region.
342 @param Data The buffer containing the data to be written.
343 @param DataSize Amount of data to write.
344 @param DoErase Earse each block.
345 @param DoWrite Write to each block.
347 @retval EFI_SUCCESS Operation successful.
348 @retval EFI_NOT_READY Required resources not setup.
349 @retval EFI_INVALID_PARAMETER Invalid parameter.
350 @retval Others Unexpected error happened.
355 PlatformFlashEraseWrite (
357 IN UINTN CpuWriteAddress
,
365 UINT64 CpuBaseAddress
;
366 SPI_INIT_INFO
*SpiInfo
;
369 UINTN SpiWriteAddress
;
370 EFI_SPI_PROTOCOL
*SpiProtocol
;
372 if (!DoErase
&& !DoWrite
) {
373 return EFI_INVALID_PARAMETER
;
375 if (DoWrite
&& Data
== NULL
) {
376 return EFI_INVALID_PARAMETER
;
378 if ((CpuWriteAddress
% FLASH_BLOCK_SIZE
) != 0) {
379 return EFI_INVALID_PARAMETER
;
381 if ((DataSize
% FLASH_BLOCK_SIZE
) != 0) {
382 return EFI_INVALID_PARAMETER
;
384 SpiProtocol
= LocateSpiProtocol ((EFI_SMM_SYSTEM_TABLE2
*)Smst
);
385 if (SpiProtocol
== NULL
) {
386 return EFI_NOT_READY
;
390 // Find info to allow usage of SpiProtocol->Execute.
392 Status
= SpiProtocol
->Info (
396 if (EFI_ERROR(Status
)) {
399 ASSERT (SpiInfo
->InitTable
!= NULL
);
400 ASSERT (SpiInfo
->EraseOpcodeIndex
< SPI_NUM_OPCODE
);
401 ASSERT (SpiInfo
->ProgramOpcodeIndex
< SPI_NUM_OPCODE
);
403 CpuBaseAddress
= PcdGet32 (PcdFlashAreaBaseAddress
) - (UINT32
)SpiInfo
->InitTable
->BiosStartOffset
;
404 ASSERT(CpuBaseAddress
>= (SIZE_4GB
- SIZE_8MB
));
405 if (CpuWriteAddress
< CpuBaseAddress
) {
406 return (EFI_INVALID_PARAMETER
);
409 SpiWriteAddress
= CpuWriteAddress
- ((UINTN
) CpuBaseAddress
);
412 (EFI_D_INFO
, "PlatformFlashWrite:SpiWriteAddress=%08x EraseIndex=%d WriteIndex=%d\n",
414 (UINTN
) SpiInfo
->EraseOpcodeIndex
,
415 (UINTN
) SpiInfo
->ProgramOpcodeIndex
417 for (Index
=0; Index
< DataSize
/ FLASH_BLOCK_SIZE
; Index
++) {
420 (EFI_D_INFO
, "PlatformFlashWrite:Erase[%04x] SpiWriteAddress=%08x\n",
424 Status
= SpiProtocol
->Execute (
426 SpiInfo
->EraseOpcodeIndex
,// OpcodeIndex
427 0, // PrefixOpcodeIndex
431 SpiWriteAddress
, // Address
434 EnumSpiRegionAll
// SPI_REGION_TYPE
436 if (EFI_ERROR(Status
)) {
443 (EFI_D_INFO
, "PlatformFlashWrite:Write[%04x] SpiWriteAddress=%08x\n",
447 Status
= SpiProtocol
->Execute (
449 SpiInfo
->ProgramOpcodeIndex
, // OpcodeIndex
450 0, // PrefixOpcodeIndex
454 SpiWriteAddress
, // Address
455 FLASH_BLOCK_SIZE
, // Data Number
459 if (EFI_ERROR(Status
)) {
462 WriteBuf
+=FLASH_BLOCK_SIZE
;
464 SpiWriteAddress
+=FLASH_BLOCK_SIZE
;
469 /** Check if System booted with recovery Boot Stage1 image.
471 @retval TRUE If system booted with recovery Boot Stage1 image.
472 @retval FALSE If system booted with normal stage1 image.
477 PlatformIsBootWithRecoveryStage1 (
481 ASSERT_EFI_ERROR (EFI_UNSUPPORTED
);