From nobody Mon Sep 16 19:37:54 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+114506+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1706248953079374.99517339307647; Thu, 25 Jan 2024 22:02:33 -0800 (PST) Return-Path: DKIM-Signature: a=rsa-sha256; bh=oGAP+ZJXQ29dLkOmDrsDDZ8M331btlE2i3k+49Xekh8=; 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=1706248952; v=1; b=U+5mSLl4BAoCRYjlOBoYp7MbWI1AaxjevvywFd3obbhOiKjuMOKXWm62sEGxCKPlWNI6C6iM JOy1+Tewh94zyHo0D6EDOKuLY3wvJdUFcEI9Iy0OtmlExQ5GRadpwxVwNeLkQwPqWRlUCGwUZV/ 00a+Tm0GzpNUFYBlYqY/nMbI= X-Received: by 127.0.0.2 with SMTP id aO6HYY1788612xjeVICgXSAa; Thu, 25 Jan 2024 22:02:32 -0800 X-Received: from NAM10-MW2-obe.outbound.protection.outlook.com (NAM10-MW2-obe.outbound.protection.outlook.com [40.107.94.63]) by mx.groups.io with SMTP id smtpd.web10.9831.1706248951967764807 for ; Thu, 25 Jan 2024 22:02:32 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=CJXPUNjlOYzQnwmCPTm2XeeHdMPdcW4mkOb4VOcpsMm3LZsMJ2MSvhcippZLtFPoWliVtWiXZZwUhhXx4BEYXUBpraiSY780Z6toMx5knVVChp+eZuBA+ShcDpGI5zgUddwPrvRdtZqQLt5gzr8aPLjDC9nEpf/iVOQxR99hFKsz1T1oifq64fG4bkvEOJqjjhQLXvDDRGp554viq395g8Ys0yXjmUJUila0yW/s5QP4xfLCu7b1q5KVgqDdmJX54jeE5tfarhKNr4Wj1IS4gT6b2cfY/4VKDQfpoe+mwTjfp/lm3Diy3NkXVh0zS9ioccNmiaeG2MjctpciypPyqA== 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=3fSca/gl6jwMBZnBcguqXWskanYIKL0IIXAFeUIa29U=; b=Cob6SHmRbFajKwn4lFNLYonVflGfuqVdOeQwGdt+odZZWYAAJAN0mm3/gpIMj7vFy043wtKrk/hLEZKuiBj6w3HuvAmdBo8dPowM3ClU8TnNa+tR5Fd3eJ4ilkKwDui99ENj/3PaiDM2RSr0lRMqOj+91bLSB10QrRa+urRkfYtvWJX8dskPeL4KiwMQvUzpoiC2h1xbWamOJPDhYlufMaALvy6oMEJUl+tTViP36i9mTeYVpb/lh2xccZJE+3A/Ns/fX4Om7jp93SX4ZLU1VzNHc3pfXFdCV8w+wnhsVWgJLy5fmSdJinUJq5QDjt2mXCtz68vtkVUmO/REfkdI8A== 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 CH2PR12CA0013.namprd12.prod.outlook.com (2603:10b6:610:57::23) by CY5PR12MB6369.namprd12.prod.outlook.com (2603:10b6:930:21::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.27; Fri, 26 Jan 2024 06:02:27 +0000 X-Received: from DS2PEPF0000343D.namprd02.prod.outlook.com (2603:10b6:610:57:cafe::b4) by CH2PR12CA0013.outlook.office365.com (2603:10b6:610:57::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.26 via Frontend Transport; Fri, 26 Jan 2024 06:02:26 +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 (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+114506+1787277+3901457@groups.io; helo=mail02.groups.io; 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 DS2PEPF0000343D.mail.protection.outlook.com (10.167.18.40) 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 06:02:26 +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 00:02:24 -0600 From: "Zhai, MingXin (Duke) via groups.io" To: CC: Eric Xing , Ken Yao , Igniculus Fu , Abner Chang Subject: [edk2-devel] [PATCH V2 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Date: Fri, 26 Jan 2024 14:00:31 +0800 Message-ID: <20240126060050.1725-14-duke.zhai@amd.com> In-Reply-To: <20240126060050.1725-1-duke.zhai@amd.com> References: <20240126060050.1725-1-duke.zhai@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DS2PEPF0000343D:EE_|CY5PR12MB6369:EE_ X-MS-Office365-Filtering-Correlation-Id: 261e10c8-9103-4bb6-32ce-08dc1e345f67 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: Q+o4JtzGB9qS2nl24W1/m2qwdewmAWg89mFPRJ73Zl1w+AQJMFLn5QLMqHXThP3j99+iDGSzZw2SWvt5NTTRPsAIEgbtz0N3XhqxueUEdee4wq3yz2PnkL+UIv9sqHal9IQ4REGVo/gyieeJDMlVUMazbP4wr7/vzuD8b6c5vOhRTgbDo9t5m1e+ScOAmVzZ2Rj2pFAXl9xzoH/sIVNwaM+wnB0FyseNx0AsYgQJzSIbKQNEQKOOmBITQFMBnaB8ENBWrVYbiZq35mP0e5aLhJ+B0VKxbnc7DmB+tK8YlRwLg4HcUw8UTeyuHrKlRIc8WD1DYFKopbinxGaUKWw5mwps+Tr+h98gNMeDH58J40vlQdjw6XUWgEdUYM+rCnr4gZ93/P1IeqZj5k8Wz0+TU+kBGHUd+szsKdicKaD/MyJt2dbn3KP/mXYxM4J8Yz+9IfwieaqmBHw50XlMrZLkjr5zpKTmd2zTbz7us0ejJWps43hu17tp0nuIk82qGyDELDhp+XyH8GMqOX5O+FQv8ZJj+iyeom5LXYcnv2cm4lKHtVnicyocRP9E1BNc+aZsS1mxllxejV3ia1SNcsrNY97NnRSq1RPYFiakmuW0eMlG8F+4iE4kLj4wsML2xcWHdhunFfbaPgbwfsWizSwrURSA5zSZ7VbKoIvFuYew675eIAYYI0gofup+ABoLsuyfKvBPox8xzR1f3zTHh5cK1zi6FdNSPHMNAiBONCd6kmlpz1CGsfr+Ht4D/VZfMaiQcukW0+/kIt+tisPdJ39bcA== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2024 06:02:26.6561 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 261e10c8-9103-4bb6-32ce-08dc1e345f67 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: DS2PEPF0000343D.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY5PR12MB6369 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: bmtLJ5j3VyqUrar2GxgMnSlsx1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1706248955202100021 Content-Type: text/plain; charset="utf-8" From: Duke Zhai BZ #:4640 In V2: Improve coding style. 1.Remove the leading underscore and use double underscore at trailing in = C header files. 2.Remove old tianocore licenses and redundant license description. 3.Improve coding style. For example: remove space between @param. In V1: Initial AMD PlatformFlashAccessLib, It provides flash access protocol for= other modules. Signed-off-by: Duke Zhai 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 | 64 +++ 6 files changed, 1396 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..a6ec077f05 --- /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..c7c3591479 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h @@ -0,0 +1,346 @@ +/** @file + Implements AMD Spi + This file defines the EFI SPI Protocol which implements the + Intel(R) ICH SPI Host Controller Compatibility Interface. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ 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..832669bbf4 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon= .h @@ -0,0 +1,247 @@ +/** @file + Implements AMD SpiCommon + Header file for the PCH SPI Common Driver. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ 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..3689a3bae3 --- /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 end + 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 the + 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 may + be used to report progress during the flash + write operation. + + @retval EFI_SUCCESS The operation returns successfully. + @retval EFI_WRITE_PROTECTED The flash device is read only. + @retval EFI_UNSUPPORTED The flash device access is unsupported. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. +**/ +EFI_STATUS +EFIAPI +PerformFlashWriteWithProgress ( + IN PLATFORM_FIRMWARE_TYPE FirmwareType, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN FLASH_ADDRESS_TYPE FlashAddressType, + IN VOID *Buffer, + IN UINTN Length, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL + IN UINTN StartPercentage, + IN UINTN EndPercentage + ) +{ + EFI_STATUS Status =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_CONSUMES + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize ## SOMETIMES_CONSUMES -- 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 (#114506): https://edk2.groups.io/g/devel/message/114506 Mute This Topic: https://groups.io/mt/103971403/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-