+++ /dev/null
-/** @file\r
- Platform Flash Access library.\r
-\r
- Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-#include <Uefi.h>\r
-\r
-#include <PiDxe.h>\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/PlatformFlashAccessLib.h>\r
-//#include <Library/FlashDeviceLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Protocol/Spi.h>\r
-#include <Library/CacheMaintenanceLib.h>\r
-#include "PchAccess.h"\r
-#include <Library/IoLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/PrintLib.h>\r
-\r
-//#define SECTOR_SIZE_64KB 0x10000 // Common 64kBytes sector size\r
-//#define ALINGED_SIZE SECTOR_SIZE_64KB\r
-\r
-#define BLOCK_SIZE 0x1000\r
-#define ALINGED_SIZE BLOCK_SIZE\r
-\r
-#define R_PCH_LPC_BIOS_CNTL 0xDC\r
-#define B_PCH_LPC_BIOS_CNTL_SMM_BWP 0x20 ///< SMM BIOS write protect disable\r
-\r
-//\r
-// Prefix Opcode Index on the host SPI controller\r
-//\r
-typedef enum {\r
- SPI_WREN, // Prefix Opcode 0: Write Enable\r
- SPI_EWSR, // Prefix Opcode 1: Enable Write Status Register\r
-} PREFIX_OPCODE_INDEX;\r
-//\r
-// Opcode Menu Index on the host SPI controller\r
-//\r
-typedef enum {\r
- SPI_READ_ID, // Opcode 0: READ ID, Read cycle with address\r
- SPI_READ, // Opcode 1: READ, Read cycle with address\r
- SPI_RDSR, // Opcode 2: Read Status Register, No address\r
- SPI_WRDI_SFDP, // Opcode 3: Write Disable or Discovery Parameters, No address\r
- SPI_SERASE, // Opcode 4: Sector Erase (4KB), Write cycle with address\r
- SPI_BERASE, // Opcode 5: Block Erase (32KB), Write cycle with address\r
- SPI_PROG, // Opcode 6: Byte Program, Write cycle with address\r
- SPI_WRSR, // Opcode 7: Write Status Register, No address\r
-} SPI_OPCODE_INDEX;\r
-\r
-STATIC EFI_PHYSICAL_ADDRESS mInternalFdAddress;\r
-\r
-EFI_SPI_PROTOCOL *mSpiProtocol;\r
-\r
-/**\r
- Read NumBytes bytes of data from the address specified by\r
- PAddress into Buffer.\r
-\r
- @param[in] Address The starting physical address of the read.\r
- @param[in,out] NumBytes On input, the number of bytes to read. On output, the number\r
- of bytes actually read.\r
- @param[out] Buffer The destination data buffer for the read.\r
-\r
- @retval EFI_SUCCESS Opertion is successful.\r
- @retval EFI_DEVICE_ERROR If there is any device errors.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SpiFlashRead (\r
- IN UINTN Address,\r
- IN OUT UINT32 *NumBytes,\r
- OUT UINT8 *Buffer\r
- )\r
-{\r
- EFI_STATUS Status = EFI_SUCCESS;\r
- UINTN Offset = 0;\r
-\r
- ASSERT ((NumBytes != NULL) && (Buffer != NULL));\r
-\r
-\r
- //if (Address >= (UINTN)PcdGet32 (PcdGbeRomBase) && Address < (UINTN)PcdGet32 (PcdPDRRomBase)) {\r
- Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);\r
-\r
- Status = mSpiProtocol->Execute (\r
- mSpiProtocol,\r
- 1, //SPI_READ,\r
- 0, //SPI_WREN,\r
- TRUE,\r
- TRUE,\r
- FALSE,\r
- Offset,\r
- BLOCK_SIZE,\r
- Buffer,\r
- EnumSpiRegionAll\r
- );\r
- return Status;\r
-}\r
-\r
-/**\r
- Write NumBytes bytes of data from Buffer to the address specified by\r
- PAddresss.\r
-\r
- @param[in] Address The starting physical address of the write.\r
- @param[in,out] NumBytes On input, the number of bytes to write. On output,\r
- the actual number of bytes written.\r
- @param[in] Buffer The source data buffer for the write.\r
-\r
- @retval EFI_SUCCESS Opertion is successful.\r
- @retval EFI_DEVICE_ERROR If there is any device errors.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SpiFlashWrite (\r
- IN UINTN Address,\r
- IN OUT UINT32 *NumBytes,\r
- IN UINT8 *Buffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Offset;\r
- UINT32 Length;\r
- UINT32 RemainingBytes;\r
-\r
- ASSERT ((NumBytes != NULL) && (Buffer != NULL));\r
- ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashChipBase));\r
-\r
- Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);\r
-\r
- ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashChipSize));\r
-\r
- Status = EFI_SUCCESS;\r
- RemainingBytes = *NumBytes;\r
-\r
- while (RemainingBytes > 0) {\r
- if (RemainingBytes > SIZE_4KB) {\r
- Length = SIZE_4KB;\r
- } else {\r
- Length = RemainingBytes;\r
- }\r
- Status = mSpiProtocol->Execute (\r
- mSpiProtocol,\r
- SPI_PROG,\r
- SPI_WREN,\r
- TRUE,\r
- TRUE,\r
- TRUE,\r
- (UINT32) Offset,\r
- Length,\r
- Buffer,\r
- EnumSpiRegionAll\r
- );\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- RemainingBytes -= Length;\r
- Offset += Length;\r
- Buffer += Length;\r
- }\r
-\r
- //\r
- // Actual number of bytes written\r
- //\r
- *NumBytes -= RemainingBytes;\r
-\r
- return Status;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-InternalReadBlock (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- OUT VOID *ReadBuffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 BlockSize;\r
-\r
- BlockSize = BLOCK_SIZE;\r
-\r
- Status = SpiFlashRead ((UINTN) BaseAddress, &BlockSize, ReadBuffer);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Erase the block starting at Address.\r
-\r
- @param[in] Address The starting physical address of the block to be erased.\r
- This library assume that caller garantee that the PAddress\r
- is at the starting address of this block.\r
- @param[in] NumBytes On input, the number of bytes of the logical block to be erased.\r
- On output, the actual number of bytes erased.\r
-\r
- @retval EFI_SUCCESS. Opertion is successful.\r
- @retval EFI_DEVICE_ERROR If there is any device errors.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SpiFlashBlockErase (\r
- IN UINTN Address,\r
- IN UINTN *NumBytes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Offset;\r
- UINTN RemainingBytes;\r
-\r
- ASSERT (NumBytes != NULL);\r
- ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashChipBase));\r
-\r
- Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);\r
-\r
- ASSERT ((*NumBytes % SIZE_4KB) == 0);\r
- ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashChipSize));\r
-\r
- Status = EFI_SUCCESS;\r
- RemainingBytes = *NumBytes;\r
-\r
- //\r
- // To adjust the Offset with Bios/Gbe\r
- //\r
-// if (Address >= (UINTN)PcdGet32 (PcdFlashChipBase)) {\r
-// Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);\r
-\r
- while (RemainingBytes > 0) {\r
- Status = mSpiProtocol->Execute (\r
- mSpiProtocol,\r
- SPI_SERASE,\r
- SPI_WREN,\r
- FALSE,\r
- TRUE,\r
- FALSE,\r
- (UINT32) Offset,\r
- 0,\r
- NULL,\r
- EnumSpiRegionAll\r
- );\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- RemainingBytes -= SIZE_4KB;\r
- Offset += SIZE_4KB;\r
- }\r
-// }\r
-\r
- //\r
- // Actual number of bytes erased\r
- //\r
- *NumBytes -= RemainingBytes;\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
-Routine Description:\r
-\r
- Erase the whole block.\r
-\r
-Arguments:\r
-\r
- BaseAddress - Base address of the block to be erased.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The command completed successfully.\r
- Other - Device error or wirte-locked, operation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-InternalEraseBlock (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN NumBytes;\r
-\r
- NumBytes = BLOCK_SIZE;\r
-\r
- Status = SpiFlashBlockErase ((UINTN) BaseAddress, &NumBytes);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-InternalCompareBlock (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT8 *Buffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- VOID *CompareBuffer;\r
- UINT32 NumBytes;\r
- INTN CompareResult;\r
-\r
- NumBytes = BLOCK_SIZE;\r
- CompareBuffer = AllocatePool (NumBytes);\r
- if (CompareBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- Status = SpiFlashRead ((UINTN) BaseAddress, &NumBytes, CompareBuffer);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- CompareResult = CompareMem (CompareBuffer, Buffer, BLOCK_SIZE);\r
- if (CompareResult != 0) {\r
- Status = EFI_VOLUME_CORRUPTED;\r
- }\r
-\r
-Done:\r
- if (CompareBuffer != NULL) {\r
- FreePool (CompareBuffer);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
-Routine Description:\r
-\r
- Write a block of data.\r
-\r
-Arguments:\r
-\r
- BaseAddress - Base address of the block.\r
- Buffer - Data buffer.\r
- BufferSize - Size of the buffer.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The command completed successfully.\r
- EFI_INVALID_PARAMETER - Invalid parameter, can not proceed.\r
- Other - Device error or wirte-locked, operation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-InternalWriteBlock (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT8 *Buffer,\r
- IN UINT32 BufferSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = SpiFlashWrite ((UINTN) BaseAddress, &BufferSize, Buffer);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG((DEBUG_ERROR, "\nFlash write error."));\r
- return Status;\r
- }\r
-\r
- WriteBackInvalidateDataCacheRange ((VOID *) (UINTN) BaseAddress, BLOCK_SIZE);\r
-\r
- Status = InternalCompareBlock (BaseAddress, Buffer);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG((DEBUG_ERROR, "\nError when writing to BaseAddress %x with different at offset %x.", BaseAddress, Status));\r
- } else {\r
- DEBUG((DEBUG_INFO, "\nVerified data written to Block at %x is correct.", BaseAddress));\r
- }\r
-\r
- return Status;\r
-\r
-}\r
-\r
-/**\r
- Perform flash write operation with progress indicator. The start and end\r
- completion percentage values are passed into this function. If the requested\r
- flash write operation is broken up, then completion percentage between the\r
- start and end values may be passed to the provided Progress function. The\r
- caller of this function is required to call the Progress function for the\r
- start and end completion percentage values. This allows the Progress,\r
- StartPercentage, and EndPercentage parameters to be ignored if the requested\r
- flash write operation can not be broken up\r
-\r
- @param[in] FirmwareType The type of firmware.\r
- @param[in] FlashAddress The address of flash device to be accessed.\r
- @param[in] FlashAddressType The type of flash device address.\r
- @param[in] Buffer The pointer to the data buffer.\r
- @param[in] Length The length of data buffer in bytes.\r
- @param[in] Progress A function used report the progress of the\r
- firmware update. This is an optional parameter\r
- that may be NULL.\r
- @param[in] StartPercentage The start completion percentage value that may\r
- be used to report progress during the flash\r
- write operation.\r
- @param[in] EndPercentage The end completion percentage value that may\r
- be used to report progress during the flash\r
- write operation.\r
-\r
- @retval EFI_SUCCESS The operation returns successfully.\r
- @retval EFI_WRITE_PROTECTED The flash device is read only.\r
- @retval EFI_UNSUPPORTED The flash device access is unsupported.\r
- @retval EFI_INVALID_PARAMETER The input parameter is not valid.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-PerformFlashWriteWithProgress (\r
- IN PLATFORM_FIRMWARE_TYPE FirmwareType,\r
- IN EFI_PHYSICAL_ADDRESS FlashAddress,\r
- IN FLASH_ADDRESS_TYPE FlashAddressType,\r
- IN VOID *Buffer,\r
- IN UINTN Length,\r
- IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL\r
- IN UINTN StartPercentage,\r
- IN UINTN EndPercentage\r
- )\r
-{\r
- EFI_STATUS Status = EFI_SUCCESS;\r
- UINTN Index;\r
- EFI_PHYSICAL_ADDRESS Address;\r
- UINTN CountOfBlocks;\r
- EFI_TPL OldTpl;\r
- BOOLEAN FlashError;\r
- UINT8 *Buf;\r
- UINTN LpcBaseAddress;\r
- UINT8 Data8Or;\r
- UINT8 Data8And;\r
- UINT8 BiosCntl;\r
-\r
- Index = 0;\r
- Address = 0;\r
- CountOfBlocks = 0;\r
- FlashError = FALSE;\r
- Buf = Buffer;\r
-\r
- DEBUG((DEBUG_INFO | DEBUG_ERROR, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));\r
- if (FlashAddressType == FlashAddressTypeRelativeAddress) {\r
- FlashAddress = FlashAddress + mInternalFdAddress;\r
- }\r
-\r
- CountOfBlocks = (UINTN) (Length / BLOCK_SIZE);\r
- Address = FlashAddress;\r
-\r
- LpcBaseAddress = MmPciAddress (0,\r
- DEFAULT_PCI_BUS_NUMBER_PCH,\r
- PCI_DEVICE_NUMBER_PCH_LPC,\r
- PCI_FUNCTION_NUMBER_PCH_LPC,\r
- 0\r
- );\r
- BiosCntl = MmioRead8 (LpcBaseAddress + R_PCH_LPC_BIOS_CNTL);\r
- if ((BiosCntl & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) {\r
- ///\r
- /// Clear SMM_BWP bit (D31:F0:RegDCh[5])\r
- ///\r
- Data8And = (UINT8) ~B_PCH_LPC_BIOS_CNTL_SMM_BWP;\r
- Data8Or = 0x00;\r
-\r
- MmioAndThenOr8 (\r
- LpcBaseAddress + R_PCH_LPC_BIOS_CNTL,\r
- Data8And,\r
- Data8Or\r
- );\r
- DEBUG((DEBUG_INFO, "PerformFlashWrite Clear SMM_BWP bit\n"));\r
- }\r
-\r
- //\r
- // Raise TPL to TPL_NOTIFY to block any event handler,\r
- // while still allowing RaiseTPL(TPL_NOTIFY) within\r
- // output driver during Print()\r
- //\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
- for (Index = 0; Index < CountOfBlocks; Index++) {\r
- if (Progress != NULL) {\r
- Progress (StartPercentage + ((Index * (EndPercentage - StartPercentage)) / CountOfBlocks));\r
- }\r
- //\r
- // Handle block based on address and contents.\r
- //\r
- if (!EFI_ERROR (InternalCompareBlock (Address, Buf))) {\r
- DEBUG((DEBUG_INFO, "Skipping block at 0x%lx (already programmed)\n", Address));\r
- } else {\r
- //\r
- // Make updating process uninterruptable,\r
- // so that the flash memory area is not accessed by other entities\r
- // which may interfere with the updating process\r
- //\r
- Status = InternalEraseBlock (Address);\r
- if (EFI_ERROR(Status)) {\r
- gBS->RestoreTPL (OldTpl);\r
- FlashError = TRUE;\r
- goto Done;\r
- }\r
- Status = InternalWriteBlock (\r
- Address,\r
- Buf,\r
- (UINT32)(Length > BLOCK_SIZE ? BLOCK_SIZE : Length)\r
- );\r
- if (EFI_ERROR(Status)) {\r
- gBS->RestoreTPL (OldTpl);\r
- FlashError = TRUE;\r
- goto Done;\r
- }\r
- }\r
-\r
- //\r
- // Move to next block to update.\r
- //\r
- Address += BLOCK_SIZE;\r
- Buf += BLOCK_SIZE;\r
- if (Length > BLOCK_SIZE) {\r
- Length -= BLOCK_SIZE;\r
- } else {\r
- Length = 0;\r
- }\r
- }\r
- gBS->RestoreTPL (OldTpl);\r
-\r
-Done:\r
- if ((BiosCntl & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) {\r
- //\r
- // Restore original control setting\r
- //\r
- MmioWrite8 (LpcBaseAddress + R_PCH_LPC_BIOS_CNTL, BiosCntl);\r
- }\r
-\r
- if (Progress != NULL) {\r
- Progress (EndPercentage);\r
- }\r
-\r
- if (FlashError) {\r
- return EFI_WRITE_PROTECTED;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Perform flash write operation.\r
-\r
- @param[in] FirmwareType The type of firmware.\r
- @param[in] FlashAddress The address of flash device to be accessed.\r
- @param[in] FlashAddressType The type of flash device address.\r
- @param[in] Buffer The pointer to the data buffer.\r
- @param[in] Length The length of data buffer in bytes.\r
-\r
- @retval EFI_SUCCESS The operation returns successfully.\r
- @retval EFI_WRITE_PROTECTED The flash device is read only.\r
- @retval EFI_UNSUPPORTED The flash device access is unsupported.\r
- @retval EFI_INVALID_PARAMETER The input parameter is not valid.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-PerformFlashWrite (\r
- IN PLATFORM_FIRMWARE_TYPE FirmwareType,\r
- IN EFI_PHYSICAL_ADDRESS FlashAddress,\r
- IN FLASH_ADDRESS_TYPE FlashAddressType,\r
- IN VOID *Buffer,\r
- IN UINTN Length\r
- )\r
-{\r
- return PerformFlashWriteWithProgress (\r
- FirmwareType,\r
- FlashAddress,\r
- FlashAddressType,\r
- Buffer,\r
- Length,\r
- NULL,\r
- 0,\r
- 0\r
- );\r
-}\r
-\r
-/**\r
- Perform microcode write operation.\r
-\r
- @param[in] FlashAddress The address of flash device to be accessed.\r
- @param[in] Buffer The pointer to the data buffer.\r
- @param[in] Length The length of data buffer in bytes.\r
-\r
- @retval EFI_SUCCESS The operation returns successfully.\r
- @retval EFI_WRITE_PROTECTED The flash device is read only.\r
- @retval EFI_UNSUPPORTED The flash device access is unsupported.\r
- @retval EFI_INVALID_PARAMETER The input parameter is not valid.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MicrocodeFlashWrite (\r
- IN EFI_PHYSICAL_ADDRESS FlashAddress,\r
- IN VOID *Buffer,\r
- IN UINTN Length\r
- )\r
-{\r
- EFI_PHYSICAL_ADDRESS AlignedFlashAddress;\r
- VOID *AlignedBuffer;\r
- UINTN AlignedLength;\r
- UINTN OffsetHead;\r
- UINTN OffsetTail;\r
- EFI_STATUS Status;\r
-\r
- DEBUG((DEBUG_INFO, "MicrocodeFlashWrite - 0x%x - 0x%x\n", (UINTN)FlashAddress, Length));\r
-\r
- //\r
- // Need make buffer 64K aligned to support ERASE\r
- //\r
- // [Aligned] FlashAddress [Aligned]\r
- // | | |\r
- // V V V\r
- // +--------------+========+------------+\r
- // | OffsetHeader | Length | OffsetTail |\r
- // +--------------+========+------------+\r
- // ^\r
- // |<-----------AlignedLength----------->\r
- // |\r
- // AlignedFlashAddress\r
- //\r
- OffsetHead = FlashAddress & (ALINGED_SIZE - 1);\r
- OffsetTail = (FlashAddress + Length) & (ALINGED_SIZE - 1);\r
- if (OffsetTail != 0) {\r
- OffsetTail = ALINGED_SIZE - OffsetTail;\r
- }\r
-\r
- if ((OffsetHead != 0) || (OffsetTail != 0)) {\r
- AlignedFlashAddress = FlashAddress - OffsetHead;\r
- AlignedLength = Length + OffsetHead + OffsetTail;\r
-\r
- AlignedBuffer = AllocatePool(AlignedLength);\r
- if (AlignedBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Save original buffer\r
- //\r
- if (OffsetHead != 0) {\r
- CopyMem((UINT8 *)AlignedBuffer, (VOID *)(UINTN)AlignedFlashAddress, OffsetHead);\r
- }\r
- if (OffsetTail != 0) {\r
- CopyMem((UINT8 *)AlignedBuffer + OffsetHead + Length, (VOID *)(UINTN)(AlignedFlashAddress + OffsetHead + Length), OffsetTail);\r
- }\r
- //\r
- // Override new buffer\r
- //\r
- CopyMem((UINT8 *)AlignedBuffer + OffsetHead, Buffer, Length);\r
- } else {\r
- AlignedFlashAddress = FlashAddress;\r
- AlignedBuffer = Buffer;\r
- AlignedLength = Length;\r
- }\r
-\r
- Status = PerformFlashWrite(\r
- PlatformFirmwareTypeSystemFirmware,\r
- AlignedFlashAddress,\r
- FlashAddressTypeAbsoluteAddress,\r
- AlignedBuffer,\r
- AlignedLength\r
- );\r
- if ((OffsetHead != 0) || (OffsetTail != 0)) {\r
- FreePool (AlignedBuffer);\r
- }\r
- return Status;\r
-}\r
-\r
-/**\r
- Platform Flash Access Lib Constructor.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-PerformFlashAccessLibConstructor (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- mInternalFdAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32(PcdFlashAreaBaseAddress);\r
- DEBUG((DEBUG_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiSpiProtocolGuid,\r
- NULL,\r
- (VOID **) &mSpiProtocol\r
- );\r
- ASSERT_EFI_ERROR(Status);\r
-\r
- return EFI_SUCCESS;\r
-}\r