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 ECBF578003C for ; Fri, 19 Jan 2024 14:57:29 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=aF3WmViAPDIapIZOG6WMXD2c+YxSKvo05EdJdYe+zsA=; 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=1705676248; v=1; b=UgrojL8VtgQuxSJVIMBM269Fg5WrdIVsHCW7xFfvD1ASX6lLLM0cCoBpWAraFsXa4nwe8Ole bDhhhbv4UQIjv6N8EuKaF/eb8PmdhyjG5jeX8Mwi1iP+wqmmqRaFTmHtF4KotAdARTMO+D7hFnf 6Uu0NaBHWEA8q3Ovu0Y+GYp4= X-Received: by 127.0.0.2 with SMTP id 5SuWYY7687511xiU7rnJmmbc; Fri, 19 Jan 2024 06:57:28 -0800 X-Received: from NAM12-MW2-obe.outbound.protection.outlook.com (NAM12-MW2-obe.outbound.protection.outlook.com [40.107.244.72]) by mx.groups.io with SMTP id smtpd.web10.5968.1705560678489842241 for ; Wed, 17 Jan 2024 22:51:18 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JV9XyklLcEYdo9Ihyox7W7VC3GP22rXdwuMEWcRF0CPc+lptxym1FRKlbs5XqwtwSx9JyQirwi3yOkyVYt1AnD58pVgpxsliKwvRsrzwRKpXHPn/LzwoIdr7+Y+bibw5lUztiZQkB31RQXegqoCL0etCD0qDwOfKD8pPky2XhBD70jmTmlKEdyvZfV86wWNO8trUwMTUASHGrq8TY8crL9btzOHntvghhiBcj0/WRIxhe8ZtO+IDS1XKO2aPzt6lt4aaNNM692ftJCp+y6ByyV+Vc3a4yRSPS3DI9j6aJr+ZVLk6zoUfcvxQuMRqz1YHxSOckmTqH54lXpcYn2jGTw== 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=FWuvxAzMeUiGlTxznJBbvugda17++JmTIwZeH45z2T4=; b=FgVOUyzybS4AniNB7U06P8kEVrX+B92pNbj0YaV3lISG2nHGx5Y5kyr7VLGSFGYDaC8XQAM/qUDb5ITmGqFfQbwy+r9pC6tbBVp/EnaIFP/vgqCeDgqxFtRYkFATVArZ6Vb/V715ThwYDTGgB8JYGxXIYgYL9ypHAeKBkTnw2HL9yilhN3p7bBh9KhFrZiDz2Q7dXPaBYaAisXwSqyo/q2OTY+Onrj5o+sdwKFI2+OmPlLHKqXAwDfRxCLeFctqBB1MJpP3CHvQ7RTLQa0B0IsFLTUr4LQWaXa38PBrtYnHg1t8Wclmtnb6yLEYV+0ObdAZswhBQuqefyYXHII0+vw== 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 BYAPR03CA0016.namprd03.prod.outlook.com (2603:10b6:a02:a8::29) by DM4PR12MB6038.namprd12.prod.outlook.com (2603:10b6:8:ab::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7181.21; Thu, 18 Jan 2024 06:51:15 +0000 X-Received: from CO1PEPF000044F4.namprd05.prod.outlook.com (2603:10b6:a02:a8:cafe::4e) by BYAPR03CA0016.outlook.office365.com (2603:10b6:a02:a8::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7202.23 via Frontend Transport; Thu, 18 Jan 2024 06:51:14 +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=SATLEXMB03.amd.com; pr=C X-Received: from SATLEXMB03.amd.com (165.204.84.17) by CO1PEPF000044F4.mail.protection.outlook.com (10.167.241.74) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7202.16 via Frontend Transport; Thu, 18 Jan 2024 06:51:14 +0000 X-Received: from SATLEXMB05.amd.com (10.181.40.146) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Thu, 18 Jan 2024 00:51:13 -0600 X-Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB05.amd.com (10.181.40.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Thu, 18 Jan 2024 00:51:13 -0600 X-Received: from SHA-LX-MINGXZHA.amd.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2507.34 via Frontend Transport; Thu, 18 Jan 2024 00:51:12 -0600 From: "duke.zhai via groups.io" To: CC: Eric Xing , Ken Yao , Igniculus Fu , Abner Chang Subject: [edk2-devel] [PATCH 13/33] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Date: Thu, 18 Jan 2024 14:50:26 +0800 Message-ID: <20240118065046.961-14-duke.zhai@amd.com> In-Reply-To: <20240118065046.961-1-duke.zhai@amd.com> References: <20240118065046.961-1-duke.zhai@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000044F4:EE_|DM4PR12MB6038:EE_ X-MS-Office365-Filtering-Correlation-Id: 8fd57812-4700-4fb5-4ee0-08dc17f1dd53 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: 7eMJhdasBf7MFkMDmy1kv1L23GISTMHxPevs/r72N90IBVn2YtHZpOVbi2XaOKbn/w9x/g5gPPBzsWqS73KJaJA+Gvt7rTQSQ95n36NbaDjKtSSnaP7+BAn7MpJCsAA6X3cyc6Qn2Tzcn0K0xuHtCMUo2Bd4SOxai60Wdw5XLOq9VNxsYQWDPJeUunTapFXpzFDheu99Y8eS1f6edQs305FDtd/uvP6SpzSOepy34gBlBbMUAD/elXDFePIFwgWFEEhvtPvzc6LnTegIPCjozIE4zQhudTnnMhBfLXCBkHJNB0UrcfnZy1vo1QFerk6UipZk60Frr/tuPvpogx+9JK7KolbME3B4pK8ZL/4aG8mEjlFElMjSu3MLElTiQifR7E2YyN7f9+CU8PQDbb0K8wMhtd/sYNOoZselD+6n2AeiA+3lfU4FgAECQVXmMLY4zGea3skeLLZbCJ5rHAzDRssrsc71SsD/A4Pla7NCfv0Bn6zult+2YVMQv5OLMZLPjdNlJkdR9Sgtt2elz/G5MIfV8ez50/7iLkxbJyTnhBrCa5jaCvYjqGVkZU+qbMgz1WQ4sFB0qVI1oCxK1zGObe5KKTSwnUf+jMZRPqB5SjFz9Tn8mL6rvyZ+gROxsQ1OhOYtNgdMaejLW12qhoL84JG0RmG95tF5Ev+/L+mt5YbSjihm0nmAfEz/1CJNfynkWuW+8lZG59zE5Pl4/GTnmyuhxmuJJbJw86UfqXMBKQ69YKrL84Ykk3eQtcGqUnkpNjtABes5Hwi1rAdjPh3XVw== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Jan 2024 06:51:14.6143 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8fd57812-4700-4fb5-4ee0-08dc17f1dd53 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=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000044F4.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM4PR12MB6038 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: QwShUbBurwLSqh4QxnUnlhSlx7686176AA= 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=UgrojL8V; 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 Initial AMD PlatformFlashAccessLib, It provides flash access protocol for o= ther 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 | 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/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..e1fb1c31d9 --- /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..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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +// This file includes code originally published under the following licens= e. + +/** @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 IMPLI= ED. + + +**/ + +#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..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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +// This file includes code originally published under the following licens= e. + +/** @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 IMPLI= ED. + +**/ + +#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..a0a967b838 --- /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..5a668203b2 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAcces= sLib/PlatformFlashAccessLib.c @@ -0,0 +1,541 @@ +/** @file + Implements PlatformFlashAccessLib.c + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file + Platform Flash Access library. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ +#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..53d65339aa --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAcces= sLib/PlatformFlashAccessLib.inf @@ -0,0 +1,64 @@ +## @file +# Platform Flash AccessLib +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +## @file +# Platform Flash Access library. +# +# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD 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 IM= PLIED. +# +## + +[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 -- 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 (#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] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-