]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for update.
[mirror_edk2.git] / QuarkPlatformPkg / Feature / Capsule / Library / PlatformFlashAccessLib / PlatformFlashAccessLibDxe.c
diff --git a/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
new file mode 100644 (file)
index 0000000..839c3a7
--- /dev/null
@@ -0,0 +1,206 @@
+/** @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
+\r
+**/\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/UefiBootServicesTableLib.h>\r
+#include <Protocol/Spi.h>\r
+\r
+//\r
+// SPI default opcode slots\r
+//\r
+#define SPI_OPCODE_JEDEC_ID_INDEX        0\r
+#define SPI_OPCODE_READ_ID_INDEX         1\r
+#define SPI_OPCODE_WRITE_S_INDEX         2\r
+#define SPI_OPCODE_WRITE_INDEX           3\r
+#define SPI_OPCODE_READ_INDEX            4\r
+#define SPI_OPCODE_ERASE_INDEX           5\r
+#define SPI_OPCODE_READ_S_INDEX          6\r
+#define SPI_OPCODE_CHIP_ERASE_INDEX      7\r
+\r
+#define SPI_ERASE_SECTOR_SIZE            SIZE_4KB  //This is the chipset requirement\r
+\r
+STATIC EFI_PHYSICAL_ADDRESS     mInternalFdAddress;\r
+EFI_SPI_PROTOCOL                *mSpiProtocol;\r
+\r
+/**\r
+  Writes specified number of bytes from the input buffer to the address\r
+\r
+  @param[in]      WriteAddress  The flash address to be written.\r
+  @param[in, out] NumBytes      The number of bytes.\r
+  @param[in]      Buffer        The data buffer to be written.\r
+\r
+  @return The status of flash write.\r
+**/\r
+EFI_STATUS\r
+FlashFdWrite (\r
+  IN  UINTN                               WriteAddress,\r
+  IN OUT UINTN                            *NumBytes,\r
+  IN  UINT8                               *Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  Status = mSpiProtocol->Execute (\r
+                           mSpiProtocol,\r
+                           SPI_OPCODE_WRITE_INDEX, // OpcodeIndex\r
+                           0,                      // PrefixOpcodeIndex\r
+                           TRUE,                   // DataCycle\r
+                           TRUE,                   // Atomic\r
+                           TRUE,                   // ShiftOut\r
+                           WriteAddress,           // Address\r
+                           (UINT32) (*NumBytes),   // Data Number\r
+                           Buffer,\r
+                           EnumSpiRegionBios\r
+                           );\r
+  DEBUG((DEBUG_INFO, "FlashFdWrite - 0x%x - %r\n", (UINTN)WriteAddress, Status));\r
+\r
+  AsmWbinvd ();\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Erase a certain block from address LbaWriteAddress\r
+\r
+  @param[in] WriteAddress  The flash address to be erased.\r
+\r
+  @return The status of flash erase.\r
+**/\r
+EFI_STATUS\r
+FlashFdErase (\r
+  IN UINTN                                WriteAddress\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = mSpiProtocol->Execute (\r
+                           mSpiProtocol,\r
+                           SPI_OPCODE_ERASE_INDEX, // OpcodeIndex\r
+                           0,                      // PrefixOpcodeIndex\r
+                           FALSE,                  // DataCycle\r
+                           TRUE,                   // Atomic\r
+                           FALSE,                  // ShiftOut\r
+                           WriteAddress,           // Address\r
+                           0,                      // Data Number\r
+                           NULL,\r
+                           EnumSpiRegionBios       // SPI_REGION_TYPE\r
+                           );\r
+  DEBUG((DEBUG_INFO, "FlashFdErase - 0x%x - %r\n", (UINTN)WriteAddress, Status));\r
+\r
+  AsmWbinvd ();\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Perform flash write opreation.\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
+  EFI_STATUS          Status;\r
+  UINTN               SectorNum;\r
+  UINTN               Index;\r
+  UINTN               NumBytes;\r
+\r
+  DEBUG((DEBUG_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));\r
+  if (FlashAddressType == FlashAddressTypeAbsoluteAddress) {\r
+    FlashAddress = FlashAddress - mInternalFdAddress;\r
+  }\r
+\r
+  //\r
+  // Erase & Write\r
+  //\r
+  SectorNum = Length / SPI_ERASE_SECTOR_SIZE;\r
+  for (Index = 0; Index < SectorNum; Index++){\r
+    if (CompareMem(\r
+          (UINT8 *)(UINTN)(FlashAddress + mInternalFdAddress) + Index * SPI_ERASE_SECTOR_SIZE,\r
+          (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE,\r
+          SPI_ERASE_SECTOR_SIZE) == 0) {\r
+      DEBUG((DEBUG_INFO, "Sector - 0x%x - skip\n", Index));\r
+      continue;\r
+    }\r
+    DEBUG((DEBUG_INFO, "Sector - 0x%x - update...\n", Index));\r
+\r
+    Status = FlashFdErase (\r
+               (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE\r
+               );\r
+    if (Status != EFI_SUCCESS){\r
+      break;\r
+    }\r
+    NumBytes = SPI_ERASE_SECTOR_SIZE;\r
+    Status = FlashFdWrite (\r
+               (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE,\r
+               &NumBytes,\r
+               (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE\r
+               );\r
+    if (Status != EFI_SUCCESS){\r
+      break;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Platform Flash Access Lib Constructor.\r
+\r
+  @param[in]  ImageHandle       The firmware allocated handle for the EFI image.\r
+  @param[in]  SystemTable       A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS  Constructor returns successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PerformFlashAccessLibConstructor (\r
+  IN EFI_HANDLE                         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                   *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  mInternalFdAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32(PcdFlashAreaBaseAddress);\r
+  DEBUG((DEBUG_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));\r
+\r
+  Status = gBS->LocateProtocol(&gEfiSpiProtocolGuid, NULL, (VOID **)&mSpiProtocol);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  return EFI_SUCCESS;\r
+}\r