+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