/** @file\r
Platform Flash Access library.\r
\r
- Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\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/DebugLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/PlatformFlashAccessLib.h>\r
-#include <Library/FlashDeviceLib.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 SECTOR_SIZE_64KB 0x10000 // Common 64kBytes sector size\r
-#define ALINGED_SIZE SECTOR_SIZE_64KB\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 opreation.\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
**/\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
+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;\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, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));\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
- DEBUG((DEBUG_INFO, " - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));\r
- LibFvbFlashDeviceBlockLock(FlashAddress, Length, FALSE);\r
+ CountOfBlocks = (UINTN) (Length / BLOCK_SIZE);\r
+ Address = FlashAddress;\r
\r
- //\r
- // Erase & Write\r
- //\r
- Status = LibFvbFlashDeviceBlockErase((UINTN)FlashAddress, Length);\r
- ASSERT_EFI_ERROR(Status);\r
- if (EFI_ERROR(Status)) {\r
- LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);\r
- DEBUG((DEBUG_ERROR, "Flash Erase error\n"));\r
- return Status;\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
- Status = LibFvbFlashDeviceWrite((UINTN)FlashAddress, &Length, Buffer);\r
- ASSERT_EFI_ERROR(Status);\r
- if (EFI_ERROR(Status)) {\r
- LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);\r
- DEBUG((DEBUG_ERROR, "Flash write error\n"));\r
- return Status;\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
- LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);\r
+ if (FlashError) {\r
+ return EFI_WRITE_PROTECTED;\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Perform microcode write opreation.\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
// Save original buffer\r
//\r
if (OffsetHead != 0) {\r
- CopyMem((UINT8 *)AlignedBuffer, (VOID *)AlignedFlashAddress, OffsetHead);\r
+ CopyMem((UINT8 *)AlignedBuffer, (VOID *)(UINTN)AlignedFlashAddress, OffsetHead);\r
}\r
if (OffsetTail != 0) {\r
- CopyMem((UINT8 *)AlignedBuffer + OffsetHead + Length, (VOID *)(AlignedFlashAddress + OffsetHead + Length), OffsetTail);\r
+ CopyMem((UINT8 *)AlignedBuffer + OffsetHead + Length, (VOID *)(UINTN)(AlignedFlashAddress + OffsetHead + Length), OffsetTail);\r
}\r
//\r
// Override new buffer\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