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/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.