public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "duke.zhai 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 13/33] AMD/VanGoghBoard: Check in PlatformFlashAccessLib
Date: Thu, 18 Jan 2024 14:50:26 +0800	[thread overview]
Message-ID: <20240118065046.961-14-duke.zhai@amd.com> (raw)
In-Reply-To: <20240118065046.961-1-duke.zhai@amd.com>

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


BZ #:4640

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   | 361 ++++++++++++

 .../Include/Protocol/SpiCommon.h              | 261 +++++++++

 .../Include/Protocol/SpiFlashUpdate.h         | 152 +++++

 .../PlatformFlashAccessLib.c                  | 541 ++++++++++++++++++

 .../PlatformFlashAccessLib.inf                |  64 +++

 6 files changed, 1438 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..e1fb1c31d9

--- /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..0487946a70

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h

@@ -0,0 +1,361 @@

+/** @file

+  Implements AMD Spi

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+// This file includes code originally published under the following license.

+

+/** @file

+This file defines the EFI SPI Protocol which implements the

+Intel(R) ICH SPI Host Controller Compatibility Interface.

+

+Copyright (c) 2013-2015 Intel Corporation.

+

+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.

+

+

+**/

+

+#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..254b4b0e87

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h

@@ -0,0 +1,261 @@

+/** @file

+  Implements AMD SpiCommon

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+// This file includes code originally published under the following license.

+

+/** @file

+Header file for the PCH SPI Common Driver.

+

+Copyright (c) 2013-2015 Intel Corporation.

+

+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.

+

+**/

+

+#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..a0a967b838

--- /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..5a668203b2

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c

@@ -0,0 +1,541 @@

+/** @file

+  Implements PlatformFlashAccessLib.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  Platform Flash Access library.

+

+  Copyright (c) 2016 - 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.

+

+**/

+#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 (#114060): https://edk2.groups.io/g/devel/message/114060
Mute This Topic: https://groups.io/mt/103831172/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-19 14:57 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-18  6:50 [edk2-devel] [PATCH 00/33] Introduce AMD Vangogh platform reference code duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 01/33] AMD/AmdPlatformPkg: Check in AMD S3 logo duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 02/33] AMD/VanGoghBoard: Check in ACPI tables duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 03/33] AMD/VanGoghBoard: Check in Capsule update duke.zhai via groups.io
2024-01-23  4:42   ` Chang, Abner via groups.io
2024-01-25  8:25     ` Zhai, MingXin (Duke) via groups.io
2024-01-25 11:45       ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 04/33] AMD/VanGoghBoard: Check in AgesaPublic pkg duke.zhai via groups.io
2024-01-23  4:44   ` Chang, Abner via groups.io
2024-01-25  8:17     ` Xing, Eric via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 05/33] AMD/VanGoghBoard: Check in PlatformSecLib duke.zhai via groups.io
2024-01-23  4:46   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 06/33] AMD/VanGoghBoard: Check in AmdIdsExtLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 07/33] AMD/VanGoghBoard: Check in PciPlatform duke.zhai via groups.io
2024-01-23  4:50   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 08/33] AMD/VanGoghBoard: Check in UDKFlashUpdate duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 09/33] AMD/VanGoghBoard: Check in Flash_AB duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 10/33] AMD/VanGoghBoard: Check in FlashUpdate duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 11/33] AMD/VanGoghBoard: Check in FvbServices duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 12/33] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib duke.zhai via groups.io
2024-01-18  6:50 ` duke.zhai via groups.io [this message]
2024-01-18  6:50 ` [edk2-devel] [PATCH 14/33] AMD/VanGoghBoard: Check in SmbiosLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 15/33] AMD/VanGoghBoard: Check in SpiFlashDeviceLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 16/33] AMD/VanGoghBoard: Check in BaseTscTimerLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 17/33] AMD/VanGoghBoard: Check in Smm access module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 18/33] AMD/VanGoghBoard: Check in PciHostBridge module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 19/33] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 20/33] AMD/VanGoghBoard: Check in FTPM module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 21/33] AMD/VanGoghBoard: Check in SignedCapsule duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 22/33] AMD/VanGoghBoard: Check in Vtf0 duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 23/33] AMD/VanGoghBoard: Check in AcpiPlatform duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 24/33] AMD/VanGoghBoard: Check in FchSpi module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 25/33] AMD/VanGoghBoard: Check in PlatformInitPei module duke.zhai via groups.io
2024-01-23  6:35   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 26/33] AMD/VanGoghBoard: Check in Smbios platform dxe drivers duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 27/33] AMD/VanGoghBoard: Check in Fsp2WrapperPkg duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 28/33] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module duke.zhai via groups.io
2024-01-23  5:14   ` Chang, Abner via groups.io
2024-01-23 10:20     ` Xing, Eric via groups.io
2024-01-23 10:44       ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 29/33] AMD/VanGoghBoard: Check in SmramSaveState module duke.zhai via groups.io
2024-01-20 14:37   ` Abdul Lateef Attar via groups.io
2024-01-23  5:15     ` Chang, Abner via groups.io
2024-01-23 10:27       ` Xing, Eric via groups.io
2024-01-23 10:44         ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 30/33] AMD/VanGoghBoard: Check in EDK2 override files duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 31/33] AMD/VanGoghBoard: Check in AMD SmmControlPei module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 32/33] AMD/VanGoghBoard: Check in Chachani board project files and build script duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 33/33] AMD/VanGoghBoard: Improvement coding style duke.zhai 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=20240118065046.961-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