From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 47C84AC108D for ; Fri, 26 Jan 2024 13:12:28 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=8bqbSQXTPsgMcr9J0TXXgJm62HAtL3WhrdXKypRJIAA=; c=relaxed/simple; d=groups.io; h=ARC-Seal:ARC-Message-Signature:ARC-Authentication-Results:Received-SPF:From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding:Content-Type; s=20140610; t=1706274747; v=1; b=GOYTtCSfYJz8cXA+WLUpkXI9w5egnDXm+9/R1kDCX6iFCEGh1zSS3E69xooho76z0N4l1rWb NqHeON32R/9yMDrHJSwRr/mFRmzOaGLFpyUuu2dy51dp5pBd1QRmwJvo1Rb1chKKHE7TwJAuSlm WmDRjRfTmxklAgtDbAERuyj4= X-Received: by 127.0.0.2 with SMTP id VsUyYY7687511xMA0frw6Ydm; Fri, 26 Jan 2024 05:12:27 -0800 X-Received: from NAM10-DM6-obe.outbound.protection.outlook.com (NAM10-DM6-obe.outbound.protection.outlook.com [40.107.93.73]) by mx.groups.io with SMTP id smtpd.web10.15473.1706274745701865739 for ; Fri, 26 Jan 2024 05:12:25 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=fmlLqoEPd0WPF67WF8GZlW4HQhYuMrakNUyuZo4E/r/g75UZ5KCRAIdSR5jHwfQQ7lN2WOLLVaLGzo5Dz1hu1VRDAdOF6sA639liukzw07gfPBYB0AMUbt/ggjJgNZCJiA9QYbLsK7QPONTJ7vUdnSaF71qPAd2vevxQ4j7bU1UTT6gP0gSwWxIIMHCQm1ooLlRL2/LfmvS6OPbY4Lf6AjtJkaKlQ51fQErs4APOgXD5i38/Xe0PW/jEbSi4vPDXLV9kWoBSznJ72uqFivxpBYQM2o3mz/qgcfMhsBvlitxUbxRKxqDsHvsay95PJ8HPRniO0/axfbdRcRn27jj2hw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Kovy/TdBZhM0YNLG+6zYQwCWTy9jXYHy7JmorjJVF68=; b=ZnhEPBX2nt2OHHazNiw7c10IhYyYbvxjRl+ccAAyaVwEgnH43mxRhSMVwYGBDp9zQpf4bZnNstv6dBZp75HAaA9tRxwXu+mFzcXmUw5q9mx4fknmdrjG6Hs1EQWHHkc3MvloOQQLZ0Au4i9PDKvs9Yxm7Sh6eIlAvEF9ZvEob8N5tfnkmD8wJascop3siMfvxtKAjrMcYLg8w+lekyxuc1azgpipTig/G4qPLdiGioH1i47r/pRogwOBNxHlW3BkbmywJRUQDOWF3nOtfGj+6IJkY1o5yNG+Ruz6uPQKFoMzXwYJRkpjOnY9Vo9+x+diTdZMJo02uDvG/erz+3uXgA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) X-Received: from CY5PR15CA0130.namprd15.prod.outlook.com (2603:10b6:930:68::21) by DM4PR12MB7576.namprd12.prod.outlook.com (2603:10b6:8:10c::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.22; Fri, 26 Jan 2024 13:12:22 +0000 X-Received: from CY4PEPF0000E9CE.namprd03.prod.outlook.com (2603:10b6:930:68:cafe::d9) by CY5PR15CA0130.outlook.office365.com (2603:10b6:930:68::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.22 via Frontend Transport; Fri, 26 Jan 2024 13:12:21 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C X-Received: from SATLEXMB04.amd.com (165.204.84.17) by CY4PEPF0000E9CE.mail.protection.outlook.com (10.167.241.141) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7228.16 via Frontend Transport; Fri, 26 Jan 2024 13:12:21 +0000 X-Received: from SHA-LX-MINGXZHA.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Fri, 26 Jan 2024 07:12:19 -0600 From: "Zhai, MingXin (Duke) via groups.io" To: CC: Eric Xing , Ken Yao , Igniculus Fu , Abner Chang Subject: [edk2-devel] [PATCH V3 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Date: Fri, 26 Jan 2024 21:11:06 +0800 Message-ID: <20240126131125.1881-14-duke.zhai@amd.com> In-Reply-To: <20240126131125.1881-1-duke.zhai@amd.com> References: <20240126131125.1881-1-duke.zhai@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9CE:EE_|DM4PR12MB7576:EE_ X-MS-Office365-Filtering-Correlation-Id: df31245e-c33a-421f-5f9a-08dc1e706e88 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: 68qnv8waMCItO40GWGvARzHTjNesJO1ttEQ/FLlLaMc2EHXJFRNS5ptPF9Qy7Y4hnmd4qlXgy70OxR+BWo08LB/nwQ2CPYZpCp0Kabs97hodc56tCe0sggKZ/qc+9PHNN6eTHKzBRy+0PM4n2OBHsU/pSKcMIoUE5OtooDgWM/yyejg2MxAbys9zygrAqiOZBo/ucHHmv43qb/UmlbZA3l5sh83pZUABhCdMkDd7ovzwzvNrTrUA6cioSpwtTQ5fitntHJ8GBANaLks7Hu0Fw5Oj/izWi0ww5/0yoAiKNkCzjMaOYXCtIFs52KF96+hmXWKWX9Y0kwKc5TwHN7ralznPhQGj6JItppi4ukuofYD/1KQ0MdbJ90pgYMwIY766VcrpM5LcwXGaU6Hh713mKIbBbBEVfh825usFM9vVGcNithF1EAs49SrD/cwd3ugFOkmb0df+3G6WUqiCaU7v0pxWhZ0HEhxyeETZjTxG0fWXo8mUIFVys2UGH3OJFCGO3QRoCQvLPKBqSd2LNiuojAiimkkfmUcO7sMBaTGlFa9l2FZ30UutoRFNnsSawzP7ktnkAbOEoYhaO+vkubSpcoObeclh9+LhSCwNK3bR5aNwbxBOUyXcA+XUw4o04768sZ0jVLgAG/zQhmQrXX/i3cC87PXBLWZs+W2IubSHtdvFlDIveYrn6/VUv6GPtT2fCLqxyKoXYLtY7wTuRZMoivha5o2eVIIhveCITIXSvczrleIcSR3khjDVw7H05IGL+svbuS4ZQ0qgHP8zcVRYjQ== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2024 13:12:21.8275 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: df31245e-c33a-421f-5f9a-08dc1e706e88 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000E9CE.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM4PR12MB7576 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,duke.zhai@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: c6ORPUcoG21ucNdA3kN0jEx9x7686176AA= Content-Transfer-Encoding: quoted-printable Content-Type: text/plain X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=GOYTtCSf; arc=reject ("signature check failed: fail, {[1] = sig:microsoft.com:reject}"); dmarc=none; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io From: Duke Zhai BZ #:4640 In V3: Improve coding style follow edk2 C coding standard. 1.Remove macro definition extra underscores. 2.Putting some AMD copyright in the right place. 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 Cc: Eric Xing Cc: Ken Yao Cc: Igniculus Fu Cc: Abner Chang --- .../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 | 52 ++ 6 files changed, 1384 insertions(+) create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Libr= ary/SpiFlashDeviceLib.h create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Prot= ocol/Spi.h create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Prot= ocol/SpiCommon.h create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Prot= ocol/SpiFlashUpdate.h create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/Plat= formFlashAccessLib/PlatformFlashAccessLib.c create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/Plat= formFlashAccessLib/PlatformFlashAccessLib.inf diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/Spi= FlashDeviceLib.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Libra= ry/SpiFlashDeviceLib.h new file mode 100644 index 0000000000..391453f512 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDe= viceLib.h @@ -0,0 +1,59 @@ +/** @file + Implements SpiFlashDevice.h + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SPI_FLASH_DEVICE_LIB_H_ +#define SPI_FLASH_DEVICE_LIB_H_ + +#include + +// +// Provides mSpiInitTable and the total number of flash part in mSpiInitTa= ble 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 d= evice 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_COMM= AND_WRITE_ENABLE +#define SPI_EWSR_INDEX 1 // Prefix Opcode 1: SPI_COMM= AND_WRITE_S_EN +#define BIOS_CTRL 0xDC + +#endif diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Sp= i.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h new file mode 100644 index 0000000000..9702d34f7c --- /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.
+ Copyright (c) 2013-2015 Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SPI_H_ +#define SPI_H_ + +#include + +// +// 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 T= able 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 =3D 0x1000, + EnumSpiOperationErase_8K_Byte =3D 0x2000, + EnumSpiOperationErase_64K_Byte =3D 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 regi= ster) +// Operation Which Hardware Sequencing required operation this opc= ode 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 l= isted, 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 co= ntroller +// OpcodeMenu Opcodes which are loaded into the SPI host controlle= r Opcode Menu +// BiosStartOffset The offset of the start of the BIOS image relative t= o the flash device. +// Please note this is a Flash Linear Address, NOT a me= mory space address. +// This value is platform specific and depends on the s= ystem flash map. +// This value is only used on non Descriptor mode. +// BiosSize The the BIOS Image size in flash. This value is plat= form specific +// and depends on the system flash map. Please note BIO= S 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 Ima= ge is supposed to be +// placed at the top end of the BIOS Region (in Descrip= tor 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 interfa= ce. +// OpcodeIndex must be less then SPI_NUM_OPCODE for operation to be suppor= ted. +// +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 ato= mic cycle sequence. + DataCycle TRUE if the SPI cycle contains data + Atomic TRUE if the SPI cycle is atomic and interleave c= ycles 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 R= egion, 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 o= f 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 c= ycle. + Buffer Pointer to caller-allocated buffer containing th= e dada received or sent during the SPI cycle. + SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumS= piRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatfo= rmData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is appli= cable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiReg= ionOffset" is actually relative + to base of the 1st flash device (i.e., it is a F= lash 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 loca= tion. + +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/Sp= iCommon.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi= Common.h new file mode 100644 index 0000000000..1488c9715b --- /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.
+ Copyright (c) 2013-2015 Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SPI_COMMON_H_ +#define SPI_COMMON_H_ + +#include "Protocol/Spi.h" + +#include +#include +#include +#include +#include +// #include + +#include + +// +// Maximum time allowed while waiting the SPI cycle to complete +// Wait Time =3D 6 seconds =3D 6000000 microseconds +// Wait Period =3D 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 h= as 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 s= ystem 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 M= MIO 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 at= omic 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 dat= a 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 th= e 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 offse= t 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 BIO= S 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 fu= nction ensures each operation does + not cross 256 byte flash address boundary. + *NOTE: if there is some SPI chip that has a str= icter 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 add= ress boundaries, and it's the + caller's reponsibility to pass in a properly cu= t DataByteCount parameter. + @param Buffer Pointer to caller-allocated buffer containing t= he dada received or sent during the + SPI cycle. + @param SpiRegionType SPI Region type. Values EnumSpiRegionBios, Enum= SpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatf= ormData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is appl= icable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRe= gionOffset" 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 at= omic 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 dat= a 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 th= e 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 offse= t 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 BIO= S 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 fu= nction ensures each operation does + not cross 256 byte flash address boundary. + *NOTE: if there is some SPI chip that has a str= icter 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 add= ress boundaries, and it's the + caller's reponsibility to pass in a properly cu= t DataByteCount parameter. + @param Buffer Data received or sent during the SPI cycle. + @param SpiRegionType SPI Region type. Values EnumSpiRegionBios, Enum= SpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatf= ormData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is appl= icable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRe= gionOffset" 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 abnorma= lly. + @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 Hardwa= re + 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 interfac= e. + +**/ +BOOLEAN +WaitForSpiCycleComplete ( + IN EFI_SPI_PROTOCOL *This + ) +; + +#endif diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Sp= iFlashUpdate.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protoco= l/SpiFlashUpdate.h new file mode 100644 index 0000000000..e1271e2244 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashU= pdate.h @@ -0,0 +1,152 @@ +/** @file + Implements AMD PcRtc + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SPI_FLASH_UPDATE_H_ +#define SPI_FLASH_UPDATE_H_ + +#include + +// +// 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, 0= x8c \ + } +#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_PROTOCO= L; + +// +// 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 dev= ice. + @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/PlatformFla= shAccessLib/PlatformFlashAccessLib.c b/Platform/AMD/VanGoghBoard/VanGoghCom= monPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c new file mode 100644 index 0000000000..61c5983c44 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAcces= sLib/PlatformFlashAccessLib.c @@ -0,0 +1,528 @@ +/** @file + Implements PlatformFlashAccessLib.c + Platform Flash Access library. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 wri= te. + @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 !=3D NULL) && (Buffer !=3D NULL)); + ASSERT (Address >=3D (UINTN)PcdGet32 (PcdFlashAreaBaseAddress)); + + Offset =3D Address - (UINTN)PcdGet32 (PcdFlashAreaBaseAddress); + ASSERT ((*NumBytes + Offset) <=3D (UINTN)(PcdGet32 (PcdFlashAreaSize)*2)= ); + Status =3D EFI_SUCCESS; + RemainingBytes =3D *NumBytes; + + while (RemainingBytes > 0) { + if (RemainingBytes > SIZE_4KB) { + Length =3D SIZE_4KB; + } else { + Length =3D RemainingBytes; + } + + Status =3D mSpiProtocol->Execute ( + mSpiProtocol, + SPI_OPCODE_WRITE_INDEX, + SPI_WREN, + TRUE, + TRUE, + TRUE, + (UINT32)Offset, + Length, + Buffer, + EnumSpiRegionAll + ); + if (EFI_ERROR (Status)) { + break; + } + + RemainingBytes -=3D Length; + Offset +=3D Length; + Buffer +=3D Length; + } + + // + // Actual number of bytes written + // + *NumBytes -=3D 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 buffe= r 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 =3D BLOCK_SIZE; + + Status =3D SpiFlashRead ((UINTN)BaseAddress, &BlockSize, ReadBuffer); + + return Status; +} + +/** + Erase the block starting at Address. + + @param[in] Address The starting physical address of the block t= o be erased. + This library assume that caller garantee tha= t 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 !=3D NULL); + ASSERT (Address >=3D (UINTN)PcdGet32 (PcdFlashAreaBaseAddress)); + + Offset =3D Address - (UINTN)PcdGet32 (PcdFlashAreaBaseAddress); + + ASSERT ((*NumBytes % SIZE_4KB) =3D=3D 0); + // - ASSERT ((*NumBytes + Offset) <=3D (UINTN)PcdGet32 (PcdFlashAreaSiz= e)); + ASSERT ((*NumBytes + Offset) <=3D (UINTN)(PcdGet32 (PcdFlashAreaSize)*2)= ); + Status =3D EFI_SUCCESS; + RemainingBytes =3D *NumBytes; + + while (RemainingBytes > 0) { + Status =3D mSpiProtocol->Execute ( + mSpiProtocol, + SPI_OPCODE_ERASE_INDEX, + SPI_WREN, + FALSE, + TRUE, + TRUE, + (UINT32)Offset, + 0, + NULL, + EnumSpiRegionAll + ); + if (EFI_ERROR (Status)) { + break; + } + + RemainingBytes -=3D SIZE_4KB; + Offset +=3D SIZE_4KB; + } + + // + // Actual number of bytes erased + // + *NumBytes -=3D 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 =3D BLOCK_SIZE; + + Status =3D 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 =3D BLOCK_SIZE; + CompareBuffer =3D AllocatePool (NumBytes); + if (CompareBuffer =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status =3D SpiFlashRead ((UINTN)BaseAddress, &NumBytes, CompareBuffer); + if (EFI_ERROR (Status)) { + goto Done; + } + + CompareResult =3D CompareMem (CompareBuffer, Buffer, BLOCK_SIZE); + if (CompareResult !=3D 0) { + Status =3D EFI_VOLUME_CORRUPTED; + } + +Done: + if (CompareBuffer !=3D 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 =3D SpiFlashWrite ((UINTN)BaseAddress, &BufferSize, Buffer); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "\nFlash write error.")); + return Status; + } + + WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)BaseAddress, BLOCK_SIZ= E); + + Status =3D InternalCompareBlock (BaseAddress, Buffer); + Status =3D EFI_SUCCESS; + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "\nError when writing to BaseAddress %x with diff= erent 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 en= d + completion percentage values are passed into this function. If the requ= ested + flash write operation is broken up, then completion percentage between t= he + start and end values may be passed to the provided Progress function. T= he + caller of this function is required to call the Progress function for th= e + start and end completion percentage values. This allows the Progress, + StartPercentage, and EndPercentage parameters to be ignored if the reque= sted + 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 param= eter + 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 ma= y + 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 =3D EFI_SUCCESS; + UINTN Index; + EFI_PHYSICAL_ADDRESS Address; + UINTN CountOfBlocks; + EFI_TPL OldTpl; + BOOLEAN FlashError; + UINT8 *Buf; + + Index =3D 0; + Address =3D 0; + CountOfBlocks =3D 0; + FlashError =3D FALSE; + Buf =3D Buffer; + + DEBUG ((DEBUG_INFO | DEBUG_ERROR, "PerformFlashWrite - 0x%x(%x) - 0x%x\n= ", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length)); + if (FlashAddressType =3D=3D FlashAddressTypeRelativeAddress) { + FlashAddress =3D FlashAddress + mInternalFdAddress; + } + + CountOfBlocks =3D (UINTN)(Length / BLOCK_SIZE); + Address =3D FlashAddress; + + // + // Raise TPL to TPL_NOTIFY to block any event handler, + // while still allowing RaiseTPL(TPL_NOTIFY) within + // output driver during Print() + // + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); + for (Index =3D 0; Index < CountOfBlocks; Index++) { + if (Progress !=3D NULL) { + Progress (StartPercentage + ((Index * (EndPercentage - StartPercenta= ge)) / 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 =3D InternalEraseBlock (Address); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + FlashError =3D TRUE; + goto Done; + } + + Status =3D InternalWriteBlock ( + Address, + Buf, + (UINT32)(Length > BLOCK_SIZE ? BLOCK_SIZE : Length) + ); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + FlashError =3D TRUE; + goto Done; + } + } + + // + // Move to next block to update. + // + Address +=3D BLOCK_SIZE; + Buf +=3D BLOCK_SIZE; + if (Length > BLOCK_SIZE) { + Length -=3D BLOCK_SIZE; + } else { + Length =3D 0; + } + } + + gBS->RestoreTPL (OldTpl); + +Done: + + if (Progress !=3D 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 =3D (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdFlashAr= eaBaseAddress); + DEBUG ((DEBUG_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddre= ss)); + + Status =3D gBS->LocateProtocol ( + &gEfiSpiProtocolGuid, + NULL, + (VOID **)&mSpiProtocol + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFla= shAccessLib/PlatformFlashAccessLib.inf b/Platform/AMD/VanGoghBoard/VanGoghC= ommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf new file mode 100644 index 0000000000..6dc967efcd --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAcces= sLib/PlatformFlashAccessLib.inf @@ -0,0 +1,52 @@ +## @file +# Platform Flash AccessLib +# Platform Flash Access library. +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PlatformFlashAccessLib + FILE_GUID =3D 31CF9CEC-DA4E-4505-AA20-33364A291A95 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PlatformFlashAccessLib + CONSTRUCTOR =3D PerformFlashAccessLibConstructor + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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 ## G= UID + +[Protocols] + gEfiSpiProtocolGuid ## CONSUMES + +[Pcd] + gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress ## SOMETIMES_CONSUME= S + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize ## SOMETIMES_CONSUME= S --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114589): https://edk2.groups.io/g/devel/message/114589 Mute This Topic: https://groups.io/mt/103975454/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-