public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Zhai, MingXin (Duke) via groups.io" <duke.zhai=amd.com@groups.io>
To: <devel@edk2.groups.io>
Cc: Eric Xing <eric.xing@amd.com>, Ken Yao <ken.yao@amd.com>,
	Igniculus Fu <igniculus.fu@amd.com>,
	Abner Chang <abner.chang@amd.com>
Subject: [edk2-devel] [PATCH V2 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib
Date: Fri, 26 Jan 2024 14:00:31 +0800	[thread overview]
Message-ID: <20240126060050.1725-14-duke.zhai@amd.com> (raw)
In-Reply-To: <20240126060050.1725-1-duke.zhai@amd.com>

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial AMD PlatformFlashAccessLib, It provides flash access protocol for other modules.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Include/Library/SpiFlashDeviceLib.h       |  59 ++
 .../VanGoghCommonPkg/Include/Protocol/Spi.h   | 346 ++++++++++++
 .../Include/Protocol/SpiCommon.h              | 247 ++++++++
 .../Include/Protocol/SpiFlashUpdate.h         | 152 +++++
 .../PlatformFlashAccessLib.c                  | 528 ++++++++++++++++++
 .../PlatformFlashAccessLib.inf                |  64 +++
 6 files changed, 1396 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h
new file mode 100644
index 0000000000..a6ec077f05
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h
@@ -0,0 +1,59 @@
+/** @file
+  Implements SpiFlashDevice.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_FLASH_DEVICE_LIB_H__
+#define SPI_FLASH_DEVICE_LIB_H__
+
+#include <Protocol/Spi.h>
+
+//
+// Provides mSpiInitTable and the total number of flash part in mSpiInitTable for other modules.
+//
+extern SPI_INIT_TABLE  mSpiInitTable[];
+extern UINT8           mNumSpiFlashMax;
+
+//
+// Flash Device commands
+//
+// If a supported device uses a command different from the list below, a device specific command
+// will be defined just below it's JEDEC id section.
+//
+#define SPI_COMMAND_WRITE             0x02
+#define SPI_COMMAND_WRITE_AAI         0xAD
+#define SPI_COMMAND_READ              0x03
+#define SPI_COMMAND_ERASE             0x20
+#define SPI_COMMAND_WRITE_DISABLE     0x04
+#define SPI_COMMAND_READ_S            0x05
+#define SPI_COMMAND_WRITE_ENABLE      0x06
+#define SPI_COMMAND_READ_ID           0xAB
+#define SPI_COMMAND_JEDEC_ID          0x9F
+#define SPI_COMMAND_WRITE_S_EN        0x50
+#define SPI_COMMAND_WRITE_S           0x01
+#define SPI_COMMAND_CHIP_ERASE        0xC7
+#define SPI_COMMAND_BLOCK_ERASE       0xD8
+#define SPI_COMMAND_READ_SFDP         0x5A
+#define SPI_COMMAND_RPMC_OP1          0x9B
+#define SPI_COMMAND_RPMC_OP2          0x96
+#define SPI_COMMAND_Enter_4Byte_Addr  0xB7
+#define SPI_COMMAND_Exit_4Byte_Addr   0xE9
+
+//
+// Winbond 256Mbit parts
+//
+#define SF_VENDOR_ID_WINBOND     0xEF
+#define SF_DEVICE_ID1_W25Q256JW  0x19          // Capacity 256Mbit
+#define SF_DEVICE_ID0_W25Q256JW  0x60
+
+//
+// index for prefix opcodes
+//
+#define SPI_WREN_INDEX  0                     // Prefix Opcode 0: SPI_COMMAND_WRITE_ENABLE
+#define SPI_EWSR_INDEX  1                     // Prefix Opcode 1: SPI_COMMAND_WRITE_S_EN
+#define BIOS_CTRL       0xDC
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h
new file mode 100644
index 0000000000..c7c3591479
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h
@@ -0,0 +1,346 @@
+/** @file
+  Implements AMD Spi
+  This file defines the EFI SPI Protocol which implements the
+  Intel(R) ICH SPI Host Controller Compatibility Interface.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_H__
+#define SPI_H__
+
+#include <Uefi/UefiBaseType.h>
+
+//
+// Define the SPI protocol GUID
+//
+// EDK and EDKII have different GUID formats
+//
+#if !defined (EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define EFI_SPI_PROTOCOL_GUID \
+  { \
+    0x1156efc6, 0xea32, 0x4396, 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 \
+  }
+#define EFI_SMM_SPI_PROTOCOL_GUID \
+  { \
+    0xD9072C35, 0xEB8F, 0x43ad, 0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 \
+  }
+#else
+#define EFI_SPI_PROTOCOL_GUID \
+  { \
+    0x1156efc6, 0xea32, 0x4396, \
+    { \
+      0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 \
+    } \
+  }
+#define EFI_SMM_SPI_PROTOCOL_GUID \
+  { \
+    0xD9072C35, 0xEB8F, 0x43ad, \
+    { \
+      0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 \
+    } \
+  }
+#endif
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID  gEfiSpiProtocolGuid;
+extern EFI_GUID  gEfiSmmSpiProtocolGuid;
+
+#define FCH_SPI_MMIO_REG00    0x00           // SPI_
+#define FCH_SPI_OPCODE        0x000000FFl    //
+#define FCH_SPI_TX_COUNT      0x00000F00l    //
+#define FCH_SPI_RX_COUNT      0x0000F000l    //
+#define FCH_SPI_EXEC_OPCODE   0x00010000l    //
+#define FCH_SPI_FIFO_PTR_CRL  0x00100000l    //
+#define FCH_SPI_FIFO_PTR_INC  0x00200000l    //
+#define FCH_SPI_BUSY          0x80000000l    //
+#define FCH_SPI_MMIO_REG0C    0x0C           // SPI_Cntrl1 Register
+#define FCH_SPI_PARAMETER     0x000000FFl    //
+#define FCH_SPI_FIFO_PTR      0x00000700l    //
+#define FCH_SPI_BYTE_PROGRAM  0xFF000000l    //
+#define FCH_SPI_MMIO_REG1C    0x1C           //
+#define FCH_SPI_RETRY_TIMES   0x3            //
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _EFI_SPI_PROTOCOL EFI_SPI_PROTOCOL;
+
+//
+// SPI protocol data structures and definitions
+//
+//
+// Number of Prefix Opcodes allowed on the SPI interface
+//
+#define SPI_NUM_PREFIX_OPCODE  2
+
+//
+// Number of Opcodes in the Opcode Menu
+//
+#define SPI_NUM_OPCODE  12
+
+//
+// Opcode Type
+//    EnumSpiOpcodeCommand: Command without address
+//    EnumSpiOpcodeRead: Read with address
+//    EnumSpiOpcodeWrite: Write with address
+//
+typedef enum {
+  EnumSpiOpcodeReadNoAddr,
+  EnumSpiOpcodeWriteNoAddr,
+  EnumSpiOpcodeRead,
+  EnumSpiOpcodeWrite,
+  EnumSpiOpcodeMax
+} SPI_OPCODE_TYPE;
+
+typedef enum {
+  EnumSpiRegionAll,
+  EnumSpiRegionBios,
+  EnumSpiRegionMe,
+  EnumSpiRegionGbE,
+  EnumSpiRegionDescriptor,
+  EnumSpiRegionPlatformData,
+  EnumSpiRegionMax
+} SPI_REGION_TYPE;
+
+//
+// Hardware Sequencing required operations (as listed in CougarPoint EDS Table 5-55: "Hardware
+// Sequencing Commands and Opcode Requirements"
+//
+typedef enum {
+  EnumSpiOperationWriteStatus,
+  EnumSpiOperationProgramData_1_Byte,
+  EnumSpiOperationProgramData_64_Byte,
+  EnumSpiOperationReadData,
+  EnumSpiOperationWriteDisable,
+  EnumSpiOperationReadStatus,
+  EnumSpiOperationWriteEnable,
+  EnumSpiOperationFastRead,
+  EnumSpiOperationEnableWriteStatus,
+  EnumSpiOperationErase_256_Byte,
+  EnumSpiOperationErase_4K_Byte  = 0x1000,
+  EnumSpiOperationErase_8K_Byte  = 0x2000,
+  EnumSpiOperationErase_64K_Byte = 0x10000,
+  EnumSpiOperationFullChipErase,
+  EnumSpiOperationJedecId,
+  EnumSpiOperationDualOutputFastRead,
+  EnumSpiOperationDiscoveryParameters,
+  EnumSpiOperationOther,
+  EnumSpiOperationMax
+} SPI_OPERATION;
+
+//
+// Opcode menu entries
+//   Type            Operation Type (value to be programmed to the OPTYPE register)
+//   Code            The opcode (value to be programmed to the OPMENU register)
+//   Operation       Which Hardware Sequencing required operation this opcode respoinds to.
+//                   The required operations are listed in EDS Table 5-55: "Hardware
+//                   Sequencing Commands and Opcode Requirements"
+//                   If the opcode does not corresponds to any operation listed, use
+//                   EnumSpiOperationOther
+//
+typedef struct _SPI_OPCODE_MENU_ENTRY {
+  SPI_OPCODE_TYPE    Type;
+  UINT8              Code;
+  SPI_OPERATION      Operation;
+} SPI_OPCODE_MENU_ENTRY;
+
+//
+// Initialization data table loaded to the SPI host controller
+//    VendorId        Vendor ID of the SPI device
+//    DeviceId0       Device ID0 of the SPI device
+//    DeviceId1       Device ID1 of the SPI device
+//    PrefixOpcode    Prefix opcodes which are loaded into the SPI host controller
+//    OpcodeMenu      Opcodes which are loaded into the SPI host controller Opcode Menu
+//    BiosStartOffset The offset of the start of the BIOS image relative to the flash device.
+//                    Please note this is a Flash Linear Address, NOT a memory space address.
+//                    This value is platform specific and depends on the system flash map.
+//                    This value is only used on non Descriptor mode.
+//    BiosSize        The the BIOS Image size in flash. This value is platform specific
+//                    and depends on the system flash map. Please note BIOS Image size may
+//                    be smaller than BIOS Region size (in Descriptor Mode) or the flash size
+//                    (in Non Descriptor Mode), and in this case, BIOS Image is supposed to be
+//                    placed at the top end of the BIOS Region (in Descriptor Mode) or the flash
+//                    (in Non Descriptor Mode)
+//
+typedef struct _SPI_INIT_TABLE {
+  UINT8                    VendorId;
+  UINT8                    DeviceId0;
+  UINT8                    DeviceId1;
+  UINT8                    PrefixOpcode[SPI_NUM_PREFIX_OPCODE];
+  SPI_OPCODE_MENU_ENTRY    OpcodeMenu[SPI_NUM_OPCODE];
+  UINTN                    BiosStartOffset;
+  UINTN                    BiosSize;
+} SPI_INIT_TABLE;
+
+//
+// Public Info struct to show current initialized state of the spi interface.
+// OpcodeIndex must be less then SPI_NUM_OPCODE for operation to be supported.
+//
+typedef struct _SPI_INIT_INFO {
+  SPI_INIT_TABLE    *InitTable;
+  UINT8             JedecIdOpcodeIndex;
+  UINT8             OtherOpcodeIndex;
+  UINT8             WriteStatusOpcodeIndex;
+  UINT8             ProgramOpcodeIndex;
+  UINT8             ReadOpcodeIndex;
+  UINT8             EraseOpcodeIndex;
+  UINT8             ReadStatusOpcodeIndex;
+  UINT8             FullChipEraseOpcodeIndex;
+} SPI_INIT_INFO;
+
+//
+// Protocol member functions
+//
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_INIT)(
+  IN EFI_SPI_PROTOCOL     *This
+  );
+
+/*++
+
+Routine Description:
+
+  Initializes the host controller to execute SPI commands.
+
+Arguments:
+
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.
+
+Returns:
+
+  EFI_SUCCESS             Opcode initialization on the SPI host controller completed.
+  EFI_ACCESS_DENIED       The SPI configuration interface is locked.
+  EFI_OUT_OF_RESOURCES    Not enough resource available to initialize the device.
+  EFI_DEVICE_ERROR        Device error, operation failed.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_LOCK)(
+  IN EFI_SPI_PROTOCOL     *This
+  );
+
+/*++
+
+Routine Description:
+
+  Lock the SPI Static Configuration Interface.
+  Once locked, the interface is no longer open for configuration changes.
+  The lock state automatically clears on next system reset.
+
+Arguments:
+
+  This      Pointer to the EFI_SPI_PROTOCOL instance.
+
+Returns:
+
+  EFI_SUCCESS             Lock operation succeed.
+  EFI_DEVICE_ERROR        Device error, operation failed.
+  EFI_ACCESS_DENIED       The interface has already been locked.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_EXECUTE)(
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT8              OpcodeIndex,
+  IN     UINT8              PrefixOpcodeIndex,
+  IN     BOOLEAN            DataCycle,
+  IN     BOOLEAN            Atomic,
+  IN     BOOLEAN            ShiftOut,
+  IN     UINTN              Address,
+  IN     UINT32             DataByteCount,
+  IN OUT UINT8              *Buffer,
+  IN     SPI_REGION_TYPE    SpiRegionType
+  );
+
+/*++
+
+Routine Description:
+
+  Execute SPI commands from the host controller.
+
+Arguments:
+
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.
+  OpcodeIndex             Index of the command in the OpCode Menu.
+  PrefixOpcodeIndex       Index of the first command to run when in an atomic cycle sequence.
+  DataCycle               TRUE if the SPI cycle contains data
+  Atomic                  TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  ShiftOut                If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  Address                 In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                          Region, this value specifies the offset from the Region Base; for BIOS Region,
+                          this value specifies the offset from the start of the BIOS Image. In Non
+                          Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                          Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                          Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                          supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                          the flash (in Non Descriptor Mode)
+  DataByteCount           Number of bytes in the data portion of the SPI cycle.
+  Buffer                  Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+  SpiRegionType           SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                          EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                          Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                          and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                          to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+Returns:
+
+  EFI_SUCCESS             Command succeed.
+  EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  EFI_UNSUPPORTED         Command not supported.
+  EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_INFO)(
+  IN EFI_SPI_PROTOCOL     *This,
+  OUT SPI_INIT_INFO      **InitInfoPtr
+  );
+
+/*++
+
+Routine Description:
+
+  Return info about SPI host controller, to help callers usage of Execute
+  service.
+
+  If 0xff is returned as an opcode index in init info struct
+  then device does not support the operation.
+
+Arguments:
+
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.
+  InitInfoPtr             Pointer to init info written to this memory location.
+
+Returns:
+
+  EFI_SUCCESS             Information returned.
+  EFI_INVALID_PARAMETER   Invalid parameter.
+  EFI_NOT_READY           Required resources not setup.
+  Others                  Unexpected error happened.
+
+--*/
+
+//
+// Protocol definition
+//
+struct _EFI_SPI_PROTOCOL {
+  EFI_SPI_INIT       Init;
+  EFI_SPI_LOCK       Lock;
+  EFI_SPI_EXECUTE    Execute;
+  EFI_SPI_INFO       Info;
+};
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h
new file mode 100644
index 0000000000..832669bbf4
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h
@@ -0,0 +1,247 @@
+/** @file
+  Implements AMD SpiCommon
+  Header file for the PCH SPI Common Driver.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_COMMON_H__
+#define SPI_COMMON_H__
+
+#include "Protocol/Spi.h"
+
+#include <Library/PciLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+// #include <Library/SpiFlashDeviceLib.h>
+
+#include <Uefi/UefiBaseType.h>
+
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+//  Wait Time = 6 seconds = 6000000 microseconds
+//  Wait Period = 10 microseconds
+//
+#define WAIT_TIME    6000000
+#define WAIT_PERIOD  10
+
+//
+// Private data structure definitions for the driver
+//
+#define FCH_SPI_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('F', 'S', 'P', 'I')
+
+//
+// SPI default opcode slots
+//
+#define SPI_OPCODE_JEDEC_ID_INDEX           0
+#define SPI_OPCODE_WRITE_S_INDEX            1
+#define SPI_OPCODE_WRITE_INDEX              2
+#define SPI_OPCODE_READ_INDEX               3
+#define SPI_OPCODE_ERASE_INDEX              4
+#define SPI_OPCODE_READ_S_INDEX             5
+#define SPI_OPCODE_CHIP_ERASE_INDEX         6
+#define SPI_OPCODE_READ_SFDP_INDEX          7
+#define SPI_COMMAND_RPMC_OP1_INDEX          8
+#define SPI_COMMAND_RPMC_OP2_INDEX          9
+#define SPI_COMMAND_Enter_4Byte_Addr_INDEX  10
+#define SPI_COMMAND_Exit_4Byte_Addr_INDEX   11
+
+typedef struct {
+  UINTN               Signature;
+  EFI_HANDLE          Handle;
+  EFI_SPI_PROTOCOL    SpiProtocol;
+  SPI_INIT_TABLE      SpiInitTable;
+  UINTN               SpiBar;
+  BOOLEAN             InitDone; // Set to TRUE on SpiProtocolInit SUCCESS.
+  SPI_INIT_INFO       InitInfo;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a)  CR (a, SPI_INSTANCE, SpiProtocol, FCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+/**
+
+  Initialize an SPI protocol instance.
+  The function will assert in debug if FCH SPI has not been initialized
+
+  @param SpiInstance   - Pointer to SpiInstance to initialize
+
+  @retval EFI_SUCCESS     The protocol instance was properly initialized
+  @retval EFI_UNSUPPORTED The FCH is not supported by this module
+
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+  SPI_INSTANCE  *SpiInstance
+  )
+;
+
+/**
+
+  Initialize the host controller to execute SPI command.
+
+  @param This                    Pointer to the EFI_SPI_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Initialization completed.
+  @retval EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.
+  @retval EFI_INVALID_PARAMETER   Bad input parameters.
+  @retval EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolInit (
+  IN EFI_SPI_PROTOCOL  *This
+  )
+;
+
+/**
+
+  Lock the SPI Static Configuration Interface.
+  Once locked, the interface can not be changed and can only be clear by system reset.
+
+  @param This      Pointer to the EFI_SPI_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Lock operation succeed.
+  @retval EFI_DEVICE_ERROR        Device error, operation failed.
+  @retval EFI_ACCESS_DENIED       The interface has already been locked.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolLock (
+  IN EFI_SPI_PROTOCOL  *This
+  )
+;
+
+/**
+
+  Execute SPI commands from the host controller.
+  This function would be called by runtime driver, please do not use any MMIO marco here
+
+  @param This              Pointer to the EFI_SPI_PROTOCOL instance.
+  @param OpcodeIndex       Index of the command in the OpCode Menu.
+  @param PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+  @param DataCycle         TRUE if the SPI cycle contains data
+  @param Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  @param ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  @param Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                           Region, this value specifies the offset from the Region Base; for BIOS Region,
+                           this value specifies the offset from the start of the BIOS Image. In Non
+                           Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                           Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                           Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                           supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                           the flash (in Non Descriptor Mode)
+  @param DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
+                           data transfer into multiple operations. This function ensures each operation does
+                           not cross 256 byte flash address boundary.
+                           *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+                           (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+                           function to cut the data transfer at proper address boundaries, and it's the
+                           caller's reponsibility to pass in a properly cut DataByteCount parameter.
+  @param Buffer            Pointer to caller-allocated buffer containing the dada received or sent during the
+                           SPI cycle.
+  @param SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                           EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                           Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                           and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                           to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_UNSUPPORTED         Command not supported.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolExecute (
+  IN     EFI_SPI_PROTOCOL  *This,
+  IN     UINT8             OpcodeIndex,
+  IN     UINT8             PrefixOpcodeIndex,
+  IN     BOOLEAN           DataCycle,
+  IN     BOOLEAN           Atomic,
+  IN     BOOLEAN           ShiftOut,
+  IN     UINTN             Address,
+  IN     UINT32            DataByteCount,
+  IN OUT UINT8             *Buffer,
+  IN     SPI_REGION_TYPE   SpiRegionType
+  )
+;
+
+/**
+
+  This function sends the programmed SPI command to the slave device.
+
+  @param OpcodeIndex       Index of the command in the OpCode Menu.
+  @param PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+  @param DataCycle         TRUE if the SPI cycle contains data
+  @param Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  @param ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  @param Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                           Region, this value specifies the offset from the Region Base; for BIOS Region,
+                           this value specifies the offset from the start of the BIOS Image. In Non
+                           Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                           Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                           Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                           supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                           the flash (in Non Descriptor Mode)
+  @param DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
+                           data transfer into multiple operations. This function ensures each operation does
+                           not cross 256 byte flash address boundary.
+                           *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+                           (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+                           function to cut the data transfer at proper address boundaries, and it's the
+                           caller's reponsibility to pass in a properly cut DataByteCount parameter.
+  @param Buffer            Data received or sent during the SPI cycle.
+  @param SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                           EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                           Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                           and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                           to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+  @retval EFI_SUCCESS             SPI command completes successfully.
+  @retval EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
+  @retval EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+
+**/
+EFI_STATUS
+SendSpiCmd (
+  IN     EFI_SPI_PROTOCOL  *This,
+  IN     UINT8             OpcodeIndex,
+  IN     UINT8             PrefixOpcodeIndex,
+  IN     BOOLEAN           DataCycle,
+  IN     BOOLEAN           Atomic,
+  IN     BOOLEAN           ShiftOut,
+  IN     UINTN             Address,
+  IN     UINT32            DataByteCount,
+  IN OUT UINT8             *Buffer,
+  IN     SPI_REGION_TYPE   SpiRegionType
+  )
+;
+
+/**
+
+  Wait execution cycle to complete on the SPI interface. Check both Hardware
+  and Software Sequencing status registers
+
+  @param This   The SPI protocol instance
+
+  @retval TRUE  SPI cycle completed on the interface.
+  @retval FALSE Time out while waiting the SPI cycle to complete.
+             It's not safe to program the next command on the SPI interface.
+
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+  IN     EFI_SPI_PROTOCOL  *This
+  )
+;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h
new file mode 100644
index 0000000000..3689a3bae3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h
@@ -0,0 +1,152 @@
+/** @file
+  Implements AMD PcRtc
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_FLASH_UPDATE_H__
+#define SPI_FLASH_UPDATE_H__
+
+#include <Uefi/UefiBaseType.h>
+
+//
+// Spi Flash Update Protocol GUID
+// EDK and EDKII have different GUID formats
+//
+#if !defined (EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define EFI_SPI_FLASH_UPDATE_PROTOCOL_GUID \
+  { \
+    0x9cf897ac, 0xc8cd, 0x4564, 0x8d, 0x8f, 0x1b, 0x88, 0xd4, 0xcf, 0xde, 0x22 \
+  }
+#define EFI_SMM_SPI_FLASH_UPDATE_PROTOCOL_GUID \
+  { \
+    0xc5922181, 0x7a76, 0x4777, 0x96, 0x85, 0x8a, 0xd3, 0x4e, 0xca, 0x0, 0x8c \
+  }
+#else
+#define EFI_SPI_FLASH_UPDATE_PROTOCOL_GUID \
+  { \
+    0x9cf897ac, 0xc8cd, 0x4564, \
+    { \
+      0x8d, 0x8f, 0x1b, 0x88, 0xd4, 0xcf, 0xde, 0x22 \
+    } \
+  }
+#define EFI_SMM_SPI_FLASH_UPDATE_PROTOCOL_GUID \
+  { \
+    0xc5922181, 0x7a76, 0x4777, \
+    { \
+      0x96, 0x85, 0x8a, 0xd3, 0x4e, 0xca, 0x0, 0x8c \
+    } \
+  }
+#endif
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID  gEfiSpiFlashUpdateProtocolGuid;
+extern EFI_GUID  gEfiSmmSpiFlashUpdateProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _EFI_SPI_FLASH_UPDATE_PROTOCOL EFI_SPI_FLASH_UPDATE_PROTOCOL;
+
+//
+// SMM SPI Flash Update protocol structure is the same as SPI Flash Update
+// protocol. The SMM one is intend to run in SMM environment.
+//
+typedef EFI_SPI_FLASH_UPDATE_PROTOCOL EFI_SMM_SPI_FLASH_UPDATE_PROTOCOL;
+
+//
+// Protocol member functions
+//
+
+/**
+  Read data from flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[out] Buffer                      Buffer contain the read data.
+
+  @retval EFI_SUCCESS                     Read successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_FLASH_UPDATE_FD_READ)(
+  IN  UINTN            FlashAddress,
+  IN  UINTN            NumBytes,
+  OUT VOID             *Buffer
+  );
+
+/**
+  Erase flash region according to input in a block size.
+
+  @param[in] FlashAddress                 Physical flash address.
+  @param[in] NumBytes                     Number in Byte, a block size in flash device.
+
+  @retval EFI_SUCCESS                     Erase successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_FLASH_UPDATE_FD_ERASE)(
+  IN  UINTN       FlashAddress,
+  IN  UINTN       NumBytes
+  );
+
+/**
+  Write data to flash device.
+
+  Write Buffer(FlashAddress|NumBytes) to flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[in]  Buffer                      Buffer contain the write data.
+
+  @retval EFI_SUCCESS                     Write successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_FLASH_UPDATE_FD_Write)(
+  IN  UINTN           FlashAddress,
+  IN  UINTN           NumBytes,
+  IN  UINT8           *Buffer
+  );
+
+/**
+  Get flash device size and flash block size.
+
+  @param[out] FlashSize                   Pointer to the size of flash device.
+  @param[out] BlockSize                   Pointer to the size of block in flash device.
+
+  @retval EFI_SUCCESS                     Get successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_FLASH_GET_FLASH_SIZE_BLOCK_SIZE)(
+  OUT  UINTN            *FlashSize,
+  OUT  UINTN            *BlockSize
+  );
+
+//
+// Protocol definition
+//
+struct _EFI_SPI_FLASH_UPDATE_PROTOCOL {
+  EFI_SPI_FLASH_UPDATE_FD_READ               Read;
+  EFI_SPI_FLASH_UPDATE_FD_ERASE              Erase;
+  EFI_SPI_FLASH_UPDATE_FD_Write              Write;
+  EFI_SPI_FLASH_GET_FLASH_SIZE_BLOCK_SIZE    GetFlashSizeBlockSize;
+};
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
new file mode 100644
index 0000000000..61c5983c44
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
@@ -0,0 +1,528 @@
+/** @file
+  Implements PlatformFlashAccessLib.c
+  Platform Flash Access library.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/Spi.h>
+#include <Protocol/SpiCommon.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PrintLib.h>
+
+#define BLOCK_SIZE  0x1000
+
+//
+// Prefix Opcode Index on the host SPI controller
+//
+typedef enum {
+  SPI_WREN,             // Prefix Opcode 0: Write Enable
+  SPI_EWSR,             // Prefix Opcode 1: Enable Write Status Register
+} PREFIX_OPCODE_INDEX;
+
+STATIC EFI_PHYSICAL_ADDRESS  mInternalFdAddress;
+
+EFI_SPI_PROTOCOL  *mSpiProtocol;
+
+/**
+  Read NumBytes bytes of data from the address specified by
+  PAddress into Buffer.
+
+  @param[in]      Address       The starting physical address of the read.
+  @param[in,out]  NumBytes      On input, the number of bytes to read. On output, the number
+                                of bytes actually read.
+  @param[out]     Buffer        The destination data buffer for the read.
+
+  @retval         EFI_SUCCESS       Opertion is successful.
+  @retval         EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+  IN     UINTN   Address,
+  IN OUT UINT32  *NumBytes,
+  OUT UINT8      *Buffer
+  )
+{
+  CopyMem (Buffer, (VOID *)Address, *NumBytes);
+  return EFI_SUCCESS;
+}
+
+/**
+  Write NumBytes bytes of data from Buffer to the address specified by
+  PAddresss.
+
+  @param[in]      Address         The starting physical address of the write.
+  @param[in,out]  NumBytes        On input, the number of bytes to write. On output,
+                                  the actual number of bytes written.
+  @param[in]      Buffer          The source data buffer for the write.
+
+  @retval         EFI_SUCCESS       Opertion is successful.
+  @retval         EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+  IN     UINTN   Address,
+  IN OUT UINT32  *NumBytes,
+  IN     UINT8   *Buffer
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Offset;
+  UINT32      Length;
+  UINT32      RemainingBytes;
+
+  ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+  ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashAreaBaseAddress));
+
+  Offset = Address - (UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+  ASSERT ((*NumBytes + Offset) <= (UINTN)(PcdGet32 (PcdFlashAreaSize)*2));
+  Status         = EFI_SUCCESS;
+  RemainingBytes = *NumBytes;
+
+  while (RemainingBytes > 0) {
+    if (RemainingBytes > SIZE_4KB) {
+      Length = SIZE_4KB;
+    } else {
+      Length = RemainingBytes;
+    }
+
+    Status = mSpiProtocol->Execute (
+                             mSpiProtocol,
+                             SPI_OPCODE_WRITE_INDEX,
+                             SPI_WREN,
+                             TRUE,
+                             TRUE,
+                             TRUE,
+                             (UINT32)Offset,
+                             Length,
+                             Buffer,
+                             EnumSpiRegionAll
+                             );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    RemainingBytes -= Length;
+    Offset         += Length;
+    Buffer         += Length;
+  }
+
+  //
+  // Actual number of bytes written
+  //
+  *NumBytes -= RemainingBytes;
+
+  return Status;
+}
+
+/**
+  Read the block starting at Address.
+
+  @param[in]      BaseAddress         The starting physical address of the block to be read.
+  @param[in,out]  ReadBuffer          The pointer to a system memory buffer receiving the data read.
+
+  @return         The status returned from SpiFlashRead().
+
+**/
+EFI_STATUS
+InternalReadBlock (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
+  OUT VOID                  *ReadBuffer
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      BlockSize;
+
+  BlockSize = BLOCK_SIZE;
+
+  Status = SpiFlashRead ((UINTN)BaseAddress, &BlockSize, ReadBuffer);
+
+  return Status;
+}
+
+/**
+  Erase the block starting at Address.
+
+  @param[in]  Address         The starting physical address of the block to be erased.
+                              This library assume that caller garantee that the PAddress
+                              is at the starting address of this block.
+  @param[in]  NumBytes        On input, the number of bytes of the logical block to be erased.
+                              On output, the actual number of bytes erased.
+
+  @retval     EFI_SUCCESS.      Opertion is successful.
+  @retval     EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+  IN UINTN  Address,
+  IN UINTN  *NumBytes
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Offset;
+  UINTN       RemainingBytes;
+
+  ASSERT (NumBytes != NULL);
+  ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashAreaBaseAddress));
+
+  Offset = Address - (UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+
+  ASSERT ((*NumBytes % SIZE_4KB) == 0);
+  // -  ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashAreaSize));
+  ASSERT ((*NumBytes + Offset) <= (UINTN)(PcdGet32 (PcdFlashAreaSize)*2));
+  Status         = EFI_SUCCESS;
+  RemainingBytes = *NumBytes;
+
+  while (RemainingBytes > 0) {
+    Status = mSpiProtocol->Execute (
+                             mSpiProtocol,
+                             SPI_OPCODE_ERASE_INDEX,
+                             SPI_WREN,
+                             FALSE,
+                             TRUE,
+                             TRUE,
+                             (UINT32)Offset,
+                             0,
+                             NULL,
+                             EnumSpiRegionAll
+                             );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    RemainingBytes -= SIZE_4KB;
+    Offset         += SIZE_4KB;
+  }
+
+  //
+  // Actual number of bytes erased
+  //
+  *NumBytes -= RemainingBytes;
+
+  return Status;
+}
+
+/**
+  Erase the whole block.
+
+  @param[in]  BaseAddress    Base address of the block to be erased.
+
+  @retval  EFI_SUCCESS   The command completed successfully.
+  @retval  Other         Device error or wirte-locked, operation failed.
+
+**/
+EFI_STATUS
+InternalEraseBlock (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       NumBytes;
+
+  NumBytes = BLOCK_SIZE;
+
+  Status = SpiFlashBlockErase ((UINTN)BaseAddress, &NumBytes);
+
+  return Status;
+}
+
+/**
+  Compare the block value with buggfer.
+
+  @param[in]  BaseAddress    Base address of the block to be compare.
+  @param[in]  Buffer         The buffer to be compare.
+
+  @retval  EFI_SUCCESS                  The command compare successfully.
+  @retval  EFI_OUT_OF_RESOURCES         The resource has run out..
+
+**/
+EFI_STATUS
+InternalCompareBlock (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN  UINT8                 *Buffer
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *CompareBuffer;
+  UINT32      NumBytes;
+  INTN        CompareResult;
+
+  NumBytes      = BLOCK_SIZE;
+  CompareBuffer = AllocatePool (NumBytes);
+  if (CompareBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  Status = SpiFlashRead ((UINTN)BaseAddress, &NumBytes, CompareBuffer);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  CompareResult = CompareMem (CompareBuffer, Buffer, BLOCK_SIZE);
+  if (CompareResult != 0) {
+    Status = EFI_VOLUME_CORRUPTED;
+  }
+
+Done:
+  if (CompareBuffer != NULL) {
+    FreePool (CompareBuffer);
+  }
+
+  return Status;
+}
+
+/**
+  Write a block of data.
+
+  @param[in]  BaseAddress    Base address of the block.
+  @param[in]  Buffer         Data buffer.
+  @param[in]  BufferSize     Size of the buffer.
+
+  @retval  EFI_SUCCESS             The command completed successfully.
+  @retval  EFI_INVALID_PARAMETER   Invalid parameter, can not proceed.
+  @retval  Other                   Device error or wirte-locked, operation failed.
+
+**/
+EFI_STATUS
+InternalWriteBlock (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN  UINT8                 *Buffer,
+  IN  UINT32                BufferSize
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = SpiFlashWrite ((UINTN)BaseAddress, &BufferSize, Buffer);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "\nFlash write error."));
+    return Status;
+  }
+
+  WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)BaseAddress, BLOCK_SIZE);
+
+  Status = InternalCompareBlock (BaseAddress, Buffer);
+  Status = EFI_SUCCESS;
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "\nError when writing to BaseAddress %x with different at offset %x.\n", BaseAddress, Status));
+  } else {
+    DEBUG ((DEBUG_INFO, "\nVerified data written to Block at %x is correct.\n", BaseAddress));
+  }
+
+  return Status;
+}
+
+/**
+  Perform flash write operation with progress indicator.  The start and end
+  completion percentage values are passed into this function.  If the requested
+  flash write operation is broken up, then completion percentage between the
+  start and end values may be passed to the provided Progress function.  The
+  caller of this function is required to call the Progress function for the
+  start and end completion percentage values.  This allows the Progress,
+  StartPercentage, and EndPercentage parameters to be ignored if the requested
+  flash write operation can not be broken up
+
+  @param[in] FirmwareType      The type of firmware.
+  @param[in] FlashAddress      The address of flash device to be accessed.
+  @param[in] FlashAddressType  The type of flash device address.
+  @param[in] Buffer            The pointer to the data buffer.
+  @param[in] Length            The length of data buffer in bytes.
+  @param[in] Progress          A function used report the progress of the
+                               firmware update.  This is an optional parameter
+                               that may be NULL.
+  @param[in] StartPercentage   The start completion percentage value that may
+                               be used to report progress during the flash
+                               write operation.
+  @param[in] EndPercentage     The end completion percentage value that may
+                               be used to report progress during the flash
+                               write operation.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWriteWithProgress (
+  IN PLATFORM_FIRMWARE_TYPE FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS FlashAddress,
+  IN FLASH_ADDRESS_TYPE FlashAddressType,
+  IN VOID *Buffer,
+  IN UINTN Length,
+  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
+  IN UINTN                                          StartPercentage,
+  IN UINTN                                          EndPercentage
+  )
+{
+  EFI_STATUS            Status = EFI_SUCCESS;
+  UINTN                 Index;
+  EFI_PHYSICAL_ADDRESS  Address;
+  UINTN                 CountOfBlocks;
+  EFI_TPL               OldTpl;
+  BOOLEAN               FlashError;
+  UINT8                 *Buf;
+
+  Index         = 0;
+  Address       = 0;
+  CountOfBlocks = 0;
+  FlashError    = FALSE;
+  Buf           = Buffer;
+
+  DEBUG ((DEBUG_INFO | DEBUG_ERROR, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
+  if (FlashAddressType == FlashAddressTypeRelativeAddress) {
+    FlashAddress = FlashAddress + mInternalFdAddress;
+  }
+
+  CountOfBlocks = (UINTN)(Length / BLOCK_SIZE);
+  Address       = FlashAddress;
+
+  //
+  // Raise TPL to TPL_NOTIFY to block any event handler,
+  // while still allowing RaiseTPL(TPL_NOTIFY) within
+  // output driver during Print()
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+  for (Index = 0; Index < CountOfBlocks; Index++) {
+    if (Progress != NULL) {
+      Progress (StartPercentage + ((Index * (EndPercentage - StartPercentage)) / CountOfBlocks));
+    }
+
+    //
+    // Handle block based on address and contents.
+    //
+    if (!EFI_ERROR (InternalCompareBlock (Address, Buf))) {
+      DEBUG ((DEBUG_INFO, "Skipping block at 0x%lx (already programmed)\n", Address));
+    } else {
+      //
+      // Make updating process uninterruptable,
+      // so that the flash memory area is not accessed by other entities
+      // which may interfere with the updating process
+      //
+      Status = InternalEraseBlock (Address);
+      if (EFI_ERROR (Status)) {
+        gBS->RestoreTPL (OldTpl);
+        FlashError = TRUE;
+        goto Done;
+      }
+
+      Status = InternalWriteBlock (
+                 Address,
+                 Buf,
+                 (UINT32)(Length > BLOCK_SIZE ? BLOCK_SIZE : Length)
+                 );
+      if (EFI_ERROR (Status)) {
+        gBS->RestoreTPL (OldTpl);
+        FlashError = TRUE;
+        goto Done;
+      }
+    }
+
+    //
+    // Move to next block to update.
+    //
+    Address += BLOCK_SIZE;
+    Buf     += BLOCK_SIZE;
+    if (Length > BLOCK_SIZE) {
+      Length -= BLOCK_SIZE;
+    } else {
+      Length = 0;
+    }
+  }
+
+  gBS->RestoreTPL (OldTpl);
+
+Done:
+
+  if (Progress != NULL) {
+    Progress (EndPercentage);
+  }
+
+  (VOID)FlashError;
+  return Status;
+}
+
+/**
+  Perform flash write operation.
+
+  @param[in] FirmwareType      The type of firmware.
+  @param[in] FlashAddress      The address of flash device to be accessed.
+  @param[in] FlashAddressType  The type of flash device address.
+  @param[in] Buffer            The pointer to the data buffer.
+  @param[in] Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite (
+  IN PLATFORM_FIRMWARE_TYPE  FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS    FlashAddress,
+  IN FLASH_ADDRESS_TYPE      FlashAddressType,
+  IN VOID                    *Buffer,
+  IN UINTN                   Length
+  )
+{
+  return PerformFlashWriteWithProgress (
+           FirmwareType,
+           FlashAddress,
+           FlashAddressType,
+           Buffer,
+           Length,
+           NULL,
+           0,
+           0
+           );
+}
+
+/**
+  Platform Flash Access Lib Constructor.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashAccessLibConstructor (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  mInternalFdAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+  DEBUG ((DEBUG_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));
+
+  Status = gBS->LocateProtocol (
+                  &gEfiSpiProtocolGuid,
+                  NULL,
+                  (VOID **)&mSpiProtocol
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
new file mode 100644
index 0000000000..53d65339aa
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
@@ -0,0 +1,64 @@
+## @file
+#  Platform Flash AccessLib
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+#  Platform Flash Access library.
+#
+#  Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformFlashAccessLib
+  FILE_GUID                      = 31CF9CEC-DA4E-4505-AA20-33364A291A95
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformFlashAccessLib
+  CONSTRUCTOR                    = PerformFlashAccessLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PlatformFlashAccessLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SignedCapsulePkg/SignedCapsulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  IoLib
+  PcdLib
+  DebugLib
+  MemoryAllocationLib
+  CacheMaintenanceLib
+
+[Guids]
+  gEdkiiSystemFmpCapsuleConfigFileGuid          ## SOMETIMES_CONSUMES ## GUID
+
+[Protocols]
+  gEfiSpiProtocolGuid                          ## CONSUMES
+
+[Pcd]
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress  ## SOMETIMES_CONSUMES
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize         ## SOMETIMES_CONSUMES
--
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114506): https://edk2.groups.io/g/devel/message/114506
Mute This Topic: https://groups.io/mt/103971403/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-01-26  6:02 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-26  6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
2024-01-26  9:19   ` Chang, Abner via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 02/32] AMD/VanGoghBoard: Check in ACPI tables Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 03/32] AMD/VanGoghBoard: Check in Capsule update Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 04/32] AMD/VanGoghBoard: Check in AgesaPublic pkg Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 05/32]AMD/VanGoghBoard: Check in PlatformSecLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 07/32] AMD/VanGoghBoard: Check in PciPlatform Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 09/32] AMD/VanGoghBoard: Check in Flash_AB Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 10/32] AMD/VanGoghBoard: Check in FlashUpdate Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 11/32] AMD/VanGoghBoard: Check in FvbServices Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` Zhai, MingXin (Duke) via groups.io [this message]
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 14/32] AMD/VanGoghBoard: Check in SmbiosLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 17/32] AMD/VanGoghBoard: Check in Smm access module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 18/32] AMD/VanGoghBoard: Check in PciHostBridge module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 20/32] AMD/VanGoghBoard: Check in FTPM module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule Zhai, MingXin (Duke) via groups.io
2024-01-26  9:28   ` Chang, Abner via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 22/32] AMD/VanGoghBoard: Check in Vtf0 Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 23/32] AMD/VanGoghBoard: Check in AcpiPlatform Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 24/32] AMD/VanGoghBoard: Check in FchSpi module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg Zhai, MingXin (Duke) via groups.io
2024-01-26  9:34   ` Chang, Abner via groups.io
2024-01-26  9:36     ` Chang, Abner via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 29/32] AMD/VanGoghBoard: Check in SmramSaveState module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 30/32] AMD/VanGoghBoard: Check in EDK2 override files Zhai, MingXin (Duke) via groups.io
2024-01-26  9:37   ` Chang, Abner via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script Zhai, MingXin (Duke) via groups.io
2024-01-26  9:48 ` [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Chang, Abner via groups.io

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240126060050.1725-14-duke.zhai@amd.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox