From nobody Mon Sep 16 20:05:17 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+114587+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 1706274745206680.8543045018299; Fri, 26 Jan 2024 05:12:25 -0800 (PST) Return-Path: DKIM-Signature: a=rsa-sha256; bh=iG2LkDjelGGnkE9TMdSFS6mk6MiVVJ2rz5tiBHrj+Ls=; 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=1706274744; v=1; b=YLA5WXIGSxNxsH6+lW6jYigo3mZT0zCi6u0KonStZtf1fR4jloY/magQfjkdQ32bwWktQT2Q ngBU/toVkMyx9aEqopwKsk/BjYp0A1Jgcfo5gGx4Fn1Ztno8ia6G59lAWHVgI20OzL+0OCJCh4S PiB3tP16zV1QpXdfaoy320FU= X-Received: by 127.0.0.2 with SMTP id jzygYY1788612x2m1R91tJQs; Fri, 26 Jan 2024 05:12:24 -0800 X-Received: from NAM12-DM6-obe.outbound.protection.outlook.com (NAM12-DM6-obe.outbound.protection.outlook.com [40.107.243.82]) by mx.groups.io with SMTP id smtpd.web10.15472.1706274744118576268 for ; Fri, 26 Jan 2024 05:12:24 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=S/frpkR4wIE2d8ZlCfhtCgHxw4M+WZ5CJIrCwIdeEqn9MyQsvModf60FubUvC1ms+/CTARbdW7jwO6oRjS8Mg/aAXQagcrxnu4isiS4kh4CFieuqJxkDBfbsJ+QNCkfoJy9osFpo6lDj4sHNElPf4ezGjzEberq28criDECWaHD3wNcM/2FNHldKENwaefDLyiwLyAzuFh2id934d/R8xQ6IOboDBb3VHDf56qRG6eYCxgFuvnMyvEXA43p1g6lJy4VqcY8AArFI97+moNbQWfeSm6WqLxXBWTaglMQbpuAu8TSds1OkyDMUpA1z5kzjB/n+CM6eSfPOf07X8avEww== 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=kQvGqqheFshwm7L/WgHV60AlcaY+rfGjGzt4DCdnrk0=; b=Sr48bVspb78rXitoX+oAgznRopUtO4UQpSrNQWIamhB047OQ4vKvPsI3+ifnvXdoVoN+UT5/SEz2naK71e41yeC/gfpbzKxlNkEuHJ3K3IwaIyFLACmyIC1rQHPpAgBW5hychHEc3lyoAZyUNXnYtlEZDbLI6L0lUJNulEcSYEEyD4sPQdJiULHgGKa4PEqoFp9xSXtX0x9Qsm0x+VaQXjPMVX2/G3eNtGGTOQ5uqgReI1qE3byoWn1HdqzMfs2zhm9q/dnuEIMa5W4CESxkIvt/cLycYYgdY3uS3ETdB6tfnFOpq5GpgFgOFOls2thw8vHF4SXU1llE/A1tga6lGg== 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 CYZPR05CA0035.namprd05.prod.outlook.com (2603:10b6:930:a3::27) by PH7PR12MB5784.namprd12.prod.outlook.com (2603:10b6:510:1d3::22) 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 13:12:18 +0000 X-Received: from CY4PEPF0000E9D3.namprd03.prod.outlook.com (2603:10b6:930:a3:cafe::3) by CYZPR05CA0035.outlook.office365.com (2603:10b6:930:a3::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7249.14 via Frontend Transport; Fri, 26 Jan 2024 13:12:17 +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+114587+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 CY4PEPF0000E9D3.mail.protection.outlook.com (10.167.241.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7228.16 via Frontend Transport; Fri, 26 Jan 2024 13:12:17 +0000 X-Received: from SHA-LX-MINGXZHA.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Fri, 26 Jan 2024 07:12:15 -0600 From: "Zhai, MingXin (Duke) via groups.io" To: CC: Eric Xing , Ken Yao , Igniculus Fu , Abner Chang Subject: [edk2-devel] [PATCH V3 11/32] AMD/VanGoghBoard: Check in FvbServices Date: Fri, 26 Jan 2024 21:11:04 +0800 Message-ID: <20240126131125.1881-12-duke.zhai@amd.com> In-Reply-To: <20240126131125.1881-1-duke.zhai@amd.com> References: <20240126131125.1881-1-duke.zhai@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9D3:EE_|PH7PR12MB5784:EE_ X-MS-Office365-Filtering-Correlation-Id: 18831d21-9ef9-43b2-3d9a-08dc1e706c28 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: Eu4OUiPWqBHU1LslMXzvUZGjDZWN1A61ngVCy9Mz+O2/j5IHmDUYZ/IGmJJ/15yPv0wx7/w6n9DkJUmTc21tgBXEAXpESFEURZxqqMjDGWiyPYodNrdgiFkRi6WABGlS4WepDvVjqR189WbWacYR24FciTQWa9dLxrdObdYhoNMiJ1J4cvlZ8VxgrxLCJpmpxB0H+N4xBMlrhm5/6x59lswW8U0WWCvyoMOGWegYirtafv6QOrmmTTKv64r48mpJ5LDfUgq+2POqNwAgwErtAkxegCidiV8wTZCSK7cJCijciLE8f1FxeJUS+CKMvp9vrJ7dVtusybVqBC6qttgerVSruFqZkSEWWKlivnoRy9rPrlLDoYeKku5+9QjO4Yaqab+VSd1HcBIHoR80j1SuTC4tnAeE6Rpn7nwyMOLJWuYdMXTAuKXqrU7OGkFCcMJ4ShIPF/Gknk8i8WKriHW7I4w2td9Tv1uUPL0RhvLUWXF2T0P/Vb4mz7FMH5zwZsMzL6BAfDgC+9x/WnWatfxXnunoo2khGnG0vtBAIxPpBkoCzwqpClRMzzedTIEu4LfHVLC1BwXUJi2SC6pNbsMu3H0mO7dTOPraVUlsqqh/iu6i2Ao8ldiDxzC18Ekn+rKIymUJrqEw816f0PmSC72naNV6NofQXdoIlP1J+zoD74uCWaB654Wx1d+oAWKrha17dwnOeqMH3aJRwf56dQK5NrQBM21N3jxakRwA88czAxQAocZ0w7nS23w37VlNXIB/2EMihSwaC+AplsJsAcAiEw== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2024 13:12:17.8421 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 18831d21-9ef9-43b2-3d9a-08dc1e706c28 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: CY4PEPF0000E9D3.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5784 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: L2nnFdCSjNC2Nf0QlCMXMjNFx1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1706274746045100002 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 FvbServices module. It describes platform flash IC information for FlashUpdate module to send command correctly. Different flash ICs may use the different Opcodes. Signed-off-by: Duke Zhai Cc: Eric Xing Cc: Ken Yao Cc: Igniculus Fu Cc: Abner Chang --- .../VanGoghCommonPkg/FvbServices/FvbInfo.c | 120 ++ .../FvbServices/FwBlockService.c | 1285 +++++++++++++++++ .../FvbServices/FwBlockService.h | 515 +++++++ .../FvbServices/PlatformSmmSpi.inf | 68 + 4 files changed, 1988 insertions(+) create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/= FvbInfo.c create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/= FwBlockService.c create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/= FwBlockService.h create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/= PlatformSmmSpi.inf diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FvbInfo= .c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FvbInfo.c new file mode 100644 index 0000000000..c0be635864 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FvbInfo.c @@ -0,0 +1,120 @@ +/** @file +Defines data structure that is the volume header found.These data is intent +to decouple FVB driver with FV header. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2013 Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +// +// The package level header files this module uses +// +#include + +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define FVB_MEDIA_BLOCK_SIZE (0x00010000) + +#define SYSTEM_NV_BLOCK_NUM ((FixedPcdGet32(PcdFlashNvStorageVariableSize= )+ FixedPcdGet32(PcdFlashNvStorageFtwWorkingSize) + FixedPcdGet32(PcdFlashN= vStorageFtwSpareSize))/ FVB_MEDIA_BLOCK_SIZE) + +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_FIRMWARE_VOLUME_HEADER FvbInfo; + // + // EFI_FV_BLOCK_MAP_ENTRY ExtraBlockMap[n];//n=3D0 + // + EFI_FV_BLOCK_MAP_ENTRY End[1]; +} EFI_FVB2_MEDIA_INFO; + +EFI_FVB2_MEDIA_INFO mPlatformFvbMediaInfo =3D + // + // Systen NvStorage FVB + // +{ + 0, + { + { + 0, + }, // ZeroVector[16] + EFI_SYSTEM_NV_DATA_FV_GUID, + FVB_MEDIA_BLOCK_SIZE *SYSTEM_NV_BLOCK_NUM, + EFI_FVH_SIGNATURE, + EFI_FVB2_MEMORY_MAPPED | + EFI_FVB2_READ_ENABLED_CAP | + EFI_FVB2_READ_STATUS | + EFI_FVB2_WRITE_ENABLED_CAP | + EFI_FVB2_WRITE_STATUS | + EFI_FVB2_ERASE_POLARITY | + EFI_FVB2_ALIGNMENT_16, + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0xFBFF, // CheckSum + 0, // ExtHeaderOffset + { + 0, + }, // Reserved[1] + 2, // Revision + { + { + SYSTEM_NV_BLOCK_NUM, + FVB_MEDIA_BLOCK_SIZE, + } + } + }, + { + { + 0, + 0 + } + } +}; + +/** + Get Fvb information. + + @param[in] BaseAddress The base address compare with NvStorageVariabl= e base address. + @param[out] FvbInfo Fvb information. + + @retval EFI_SUCCESS Get Fvb information successfully. + @retval EFI_NOT_FOUND Not find Fvb information. + +**/ +EFI_STATUS +EFIAPI +GetFvbInfo ( + IN UINT64 BaseAddress, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ) +{ + mPlatformFvbMediaInfo.BaseAddress =3D PcdGet32 (PcdFlashNvStorageVariabl= eBase); + + if (mPlatformFvbMediaInfo.BaseAddress =3D=3D BaseAddress) { + *FvbInfo =3D &mPlatformFvbMediaInfo.FvbInfo; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlock= Service.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockS= ervice.c new file mode 100644 index 0000000000..f514ad772a --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService= .c @@ -0,0 +1,1285 @@ +/** @file + Implements FvbServicesSmm + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (c) 2013-2016 Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifdef _MSC_VER + #pragma optimize( "", off ) +#endif + +#ifdef __GNUC__ + #ifndef __clang__ + #pragma GCC push_options + #pragma GCC optimize ("O0") + #else + #pragma clang optimize off + #endif +#endif + +#include "FwBlockService.h" + +#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | E= FI_FVB2_LOCK_STATUS) + +ESAL_FWB_GLOBAL *mFvbModuleGlobal; + +FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate =3D { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) + } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS)0, + (EFI_PHYSICAL_ADDRESS)0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate =3D { + { + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + { + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) + } + }, + { 0 } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate =3D { + FVB_DEVICE_SIGNATURE, + NULL, + 0, + { + FvbProtocolGetAttributes, + FvbProtocolSetAttributes, + FvbProtocolGetPhysicalAddress, + FvbProtocolGetBlockSize, + FvbProtocolRead, + FvbProtocolWrite, + FvbProtocolEraseBlocks, + NULL + } +}; + +/** + Retrieves the physical address of a memory mapped FV + + @param[in] Instance The FV instance whose base address is going to b= e returned. + + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains all ins= tance data. + + @param[out] FwhInstance The EFI_FW_VOL_INSTANCE fimrware instance struct= ure + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS Successfully returns + @retval EFI_INVALID_PARAMETER Instance not found - + +**/ +EFI_STATUS +GetFvbInstance ( + IN UINTN Instance, + IN ESAL_FWB_GLOBAL *Global, + OUT EFI_FW_VOL_INSTANCE **FwhInstance, + IN BOOLEAN Virtual + ) +{ + EFI_FW_VOL_INSTANCE *FwhRecord; + + if (Instance >=3D Global->NumFv) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the right instance of the FVB private data + // + FwhRecord =3D Global->FvInstance[Virtual]; + while (Instance > 0) { + FwhRecord =3D (EFI_FW_VOL_INSTANCE *) + ( + (UINTN)((UINT8 *)FwhRecord) + FwhRecord->VolumeHeader.Hea= derLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLU= ME_HEADER)) + ); + Instance--; + } + + *FwhInstance =3D FwhRecord; + + return EFI_SUCCESS; +} + +/** + Retrieves the physical address of a memory mapped FV + + @param[in] Instance The FV instance whose base address is going to be = returned. + + @param[out] Address Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base addre= ss + of the firmware volume. + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS Successfully returns + @retval EFI_INVALID_PARAMETER Instance not found - + - + +**/ +EFI_STATUS +FvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *Address, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + + FwhInstance =3D NULL; + + // + // Find the right instance of the FVB private data + // + Status =3D GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + *Address =3D FwhInstance->FvBase[Virtual]; + + return EFI_SUCCESS; +} + +/** + Retrieves attributes, insures positive polarity of attribute bits, retur= ns + resulting attributes in output parameter + + @param[in] Instance The FV instance whose attributes is going to be + returned + @param[out] Attributes Output buffer which contains attributes + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS Successfully returns + @retval EFI_INVALID_PARAMETER Instance not found + +**/ +EFI_STATUS +FvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + + FwhInstance =3D NULL; + + // + // Find the right instance of the FVB private data + // + Status =3D GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + *Attributes =3D FwhInstance->VolumeHeader.Attributes; + + return EFI_SUCCESS; +} + +/** + Retrieves the starting address of an LBA in an FV + + @param[in] Instance The FV instance which the Lba belong= s to + @param[in] Lba The logical block address + @param[out] LbaAddress On output, contains the physical sta= rting address + of the Lba + @param[out] LbaLength On output, contains the length of th= e block + @param[out] NumOfBlocks A pointer to a caller allocated UINT= N in which the + number of consecutive blocks startin= g with Lba is + returned. All blocks in this range h= ave a size of + BlockSize + @param[in] Global Pointer to ESAL_FWB_GLOBAL that cont= ains all + instance data + @param[in] Virtual Whether CPU is in virtual or physica= l mode + @retval EFI_SUCCESS Successfully returns + @retval EFI_INVALID_PARAMETER Instance not found + +**/ +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINT32 NumBlocks; + UINT32 BlockLength; + UINTN Offset; + EFI_LBA StartLba; + EFI_LBA NextLba; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_STATUS Status; + + FwhInstance =3D NULL; + + // + // Find the right instance of the FVB private data + // + Status =3D GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + + StartLba =3D 0; + Offset =3D 0; + BlockMap =3D &(FwhInstance->VolumeHeader.BlockMap[0]); + + // + // Parse the blockmap of the FV to find which map entry the Lba belongs = to + // + while (TRUE) { + NumBlocks =3D BlockMap->NumBlocks; + BlockLength =3D BlockMap->Length; + + if ((NumBlocks =3D=3D 0) || (BlockLength =3D=3D 0)) { + return EFI_INVALID_PARAMETER; + } + + NextLba =3D StartLba + NumBlocks; + + // + // The map entry found + // + if ((Lba >=3D StartLba) && (Lba < NextLba)) { + Offset =3D Offset + (UINTN)MultU64x32 ((Lba - StartLba), BlockLength= ); + if (LbaAddress) { + *LbaAddress =3D FwhInstance->FvBase[Virtual] + Offset; + } + + if (LbaLength) { + *LbaLength =3D BlockLength; + } + + if (NumOfBlocks) { + *NumOfBlocks =3D (UINTN)(NextLba - Lba); + } + + return EFI_SUCCESS; + } + + StartLba =3D NextLba; + Offset =3D Offset + NumBlocks * BlockLength; + BlockMap++; + } +} + +/** + Reads specified number of bytes into a buffer from the specified block + + @param[in] Instance The FV instance to be read from + @param[in] Lba The logical block address to be read from + @param[in] BlockOffset Offset into the block at which to begin r= eading + @param[in, out] NumBytes Pointer that on input contains the total = size of + the buffer. On output, it contains the to= tal number + of bytes read + @param[in] Buffer Pointer to a caller allocated buffer that= will be + used to hold the data read + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains = all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS The firmware volume was read successful= ly and + contents are in Buffer + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. O= n output, + NumBytes contains the total number of b= ytes returned + in Buffer + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisab= led state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be read + @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer= are NULL + +**/ +EFI_STATUS +FvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) + +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "Smm %a() enter\n", __FUNCTION__)); + + // + // Check for invalid conditions + // + if ((NumBytes =3D=3D NULL) || (Buffer =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*NumBytes =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + + Status =3D FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NUL= L, Global, Virtual); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check if the FV is read enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB2_READ_STATUS) =3D=3D 0) { + return EFI_ACCESS_DENIED; + } + + // + // Perform boundary checks and adjust NumBytes + // + if (BlockOffset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + BlockOffset)) { + *NumBytes =3D (UINT32)(LbaLength - BlockOffset); + Status =3D EFI_BAD_BUFFER_SIZE; + } + + // DEBUG ((DEBUG_INFO, "ReadAddress: 0x%x, NumBytes: 0x%x\n", (UINT8 *) = (LbaAddress + BlockOffset), *NumBytes)); + CopyMem (Buffer, (UINT8 *)(LbaAddress + BlockOffset), (UINTN)(*NumBytes)= ); + + return Status; +} + +/** + Writes specified number of bytes from the input buffer to the block + + @param[in] Instance The FV instance to be written to + @param[in] Lba The starting logical block index to write= to + @param[in] BlockOffset Offset into the block at which to begin w= riting + @param[in, out] NumBytes Pointer that on input contains the total = size of + the buffer. On output, it contains the to= tal number + of bytes actually written + @param[in] Buffer Pointer to a caller allocated buffer that= contains + the source for the write + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains = all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS The firmware volume was written success= fully + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. = On output, + NumBytes contains the total number of b= ytes + actually written + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisa= bled state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be written + @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer= are NULL + +**/ +EFI_STATUS +FvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Check for invalid conditions + // + if ((NumBytes =3D=3D NULL) || (Buffer =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*NumBytes =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + + Status =3D FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NUL= L, Global, Virtual); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check if the FV is write enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB2_WRITE_STATUS) =3D=3D 0) { + return EFI_ACCESS_DENIED; + } + + // + // Perform boundary checks and adjust NumBytes + // + if (BlockOffset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + BlockOffset)) { + *NumBytes =3D (UINT32)(LbaLength - BlockOffset); + Status =3D EFI_BAD_BUFFER_SIZE; + } + + // + // Write data + // + Status =3D FlashFdWrite ( + LbaAddress + BlockOffset, + LbaAddress, + NumBytes, + Buffer, + LbaLength + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return Status; +} + +/** + Erases and initializes a firmware volume block + + @param[in] Instance The FV instance to be erased + @param[in] Lba The logical block index to be erased + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS The erase request was successfully comp= leted + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisa= bled state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be written. Firmware device m= ay have been + partially erased + @retval EFI_INVALID_PARAMETER Instance not found + +**/ +EFI_STATUS +FvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Check if the FV is write enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB2_WRITE_STATUS) =3D=3D 0) { + return EFI_ACCESS_DENIED; + } + + // + // Get the starting address of the block for erase. + // + Status =3D FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NUL= L, Global, Virtual); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D FlashFdErase (LbaAddress, LbaLength); + + return Status; +} + +/** + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + + @param[in] Instance The FV instance whose attributes is g= oing to be + modified + @param[in, out] Attributes On input, it is a pointer to EFI_FVB_= ATTRIBUTES_2 + containing the desired firmware volum= e settings. + On successful return, it contains the= new settings + of the firmware volume + @param[in] Global Pointer to ESAL_FWB_GLOBAL that conta= ins all + instance data + @param[in] Virtual Whether CPU is in virtual or physical= mode + + @retval EFI_SUCCESS Successfully returns + @retval EFI_ACCESS_DENIED The volume setting is locked and cannot= be modified + @retval EFI_INVALID_PARAMETER Instance not found, or The attributes r= equested are + in conflict with the capabilities as de= clared in the + firmware volume header + +**/ +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FVB_ATTRIBUTES_2 OldAttributes; + EFI_FVB_ATTRIBUTES_2 *AttribPtr; + UINT32 Capabilities; + UINT32 OldStatus; + UINT32 NewStatus; + EFI_STATUS Status; + EFI_FVB_ATTRIBUTES_2 UnchangedAttributes; + + FwhInstance =3D NULL; + // + // Find the right instance of the FVB private data + // + Status =3D GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + + AttribPtr =3D (EFI_FVB_ATTRIBUTES_2 *)&(FwhInstance->VolumeHeader.At= tributes); + OldAttributes =3D *AttribPtr; + Capabilities =3D OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP \ + ); + OldStatus =3D OldAttributes & EFI_FVB2_STATUS; + NewStatus =3D *Attributes & EFI_FVB2_STATUS; + + UnchangedAttributes =3D EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP | \ + EFI_FVB2_STICKY_WRITE | \ + EFI_FVB2_MEMORY_MAPPED | \ + EFI_FVB2_ERASE_POLARITY | \ + EFI_FVB2_READ_LOCK_CAP | \ + EFI_FVB2_WRITE_LOCK_CAP | \ + EFI_FVB2_ALIGNMENT; + + // + // Some attributes of FV is read only can *not* be set + // + if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttr= ibutes)) { + return EFI_INVALID_PARAMETER; + } + + // + // If firmware volume is locked, no status bit can be updated + // + if (OldAttributes & EFI_FVB2_LOCK_STATUS) { + if (OldStatus ^ NewStatus) { + return EFI_ACCESS_DENIED; + } + } + + // + // Test read disable + // + if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) =3D=3D 0) { + if ((NewStatus & EFI_FVB2_READ_STATUS) =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test read enable + // + if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) =3D=3D 0) { + if (NewStatus & EFI_FVB2_READ_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test write disable + // + if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) =3D=3D 0) { + if ((NewStatus & EFI_FVB2_WRITE_STATUS) =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test write enable + // + if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) =3D=3D 0) { + if (NewStatus & EFI_FVB2_WRITE_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test lock + // + if ((Capabilities & EFI_FVB2_LOCK_CAP) =3D=3D 0) { + if (NewStatus & EFI_FVB2_LOCK_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + *AttribPtr =3D (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); + *AttribPtr =3D (*AttribPtr) | NewStatus; + *Attributes =3D *AttribPtr; + + return EFI_SUCCESS; +} + +/** + Retrieves the physical address of the device. + + @param[in] This Calling context + @param[out] Address Output buffer containing the address. + + @retval EFI_SUCCESS Successfully returns + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGl= obal, FALSE); // Hard coded to FALSE for SMM driver. +} + +/** + Retrieve the size of a logical block + + @param[in] This alling context + @param[in] Lba Indicates which block to return the size for. + @param[out] BlockSize A pointer to a caller allocated UINTN in whi= ch + the size of the block is returned + @param[out] NumOfBlocks a pointer to a caller allocated UINTN in whi= ch the + number of consecutive blocks starting with L= ba is + returned. All blocks in this range have a si= ze of + BlockSize + + @retval EFI_SUCCESS The firmware volume was read successfully and + contents are in Buffer + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) + +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + return FvbGetLbaAddress ( + FvbDevice->Instance, + Lba, + NULL, + BlockSize, + NumOfBlocks, + mFvbModuleGlobal, + // EfiGoneVirtual () + FALSE // Hard coded to FALSE for SMM driver. + ); +} + +/** + Retrieves Volume attributes. No polarity translations are done. + + @param[in] This Calling context + @param[out] Attributes output buffer which contains attribu= tes + + @retval EFI_SUCCESS Successfully returns + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) + +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModu= leGlobal, FALSE); // Hard coded to FALSE for SMM driver. +} + +/** + Sets Volume attributes. No polarity translations are done. + + @param[in] This Calling context + @param[out] Attributes output buffer which contains attribu= tes + + @retval EFI_SUCCESS Successfully returns + +**/ +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + // return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbM= oduleGlobal, EfiGoneVirtual ()); + return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModu= leGlobal, FALSE); // Hard coded to FALSE for SMM driver. +} + +/** + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be veri= fied + prior to erasing any blocks. If a block is requested that does not exist + within the associated firmware volume (it has a larger index than the la= st + block of the firmware volume), the EraseBlock() function must return + EFI_INVALID_PARAMETER without modifying the contents of the firmware vol= ume. + + @param[in] This Calling context + @param[in] ... Starting LBA followed by Number of L= ba to erase. + a -1 to terminate the list. + + @retval EFI_SUCCESS The erase request was successfully comp= leted + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisa= bled state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be written. Firmware device m= ay have been + partially erased. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN NumOfBlocks; + VA_LIST args; + EFI_LBA StartingLba; + UINTN NumOfLba; + EFI_STATUS Status; + + FwhInstance =3D NULL; + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + // Status =3D GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, = &FwhInstance, EfiGoneVirtual ()); + Status =3D GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhIn= stance, FALSE); // Hard coded to FALSE for SMM driver. + ASSERT_EFI_ERROR (Status); + + NumOfBlocks =3D FwhInstance->NumOfBlocks; + + VA_START (args, This); + + do { + StartingLba =3D VA_ARG (args, EFI_LBA); + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba =3D VA_ARG (args, UINTN); + + // + // Check input parameters + // + if ((NumOfLba =3D=3D 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) { + VA_END (args); + return EFI_INVALID_PARAMETER; + } + } while (TRUE); + + VA_END (args); + + VA_START (args, This); + do { + StartingLba =3D VA_ARG (args, EFI_LBA); + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba =3D VA_ARG (args, UINTN); + + while (NumOfLba > 0) { + // Status =3D FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbM= oduleGlobal, EfiGoneVirtual ()); + Status =3D FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModu= leGlobal, FALSE); // Hard coded to FALSE for SMM driver. + if (EFI_ERROR (Status)) { + VA_END (args); + return Status; + } + + StartingLba++; + NumOfLba--; + } + } while (TRUE); + + VA_END (args); + + return EFI_SUCCESS; +} + +/** + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + @param[in] This Calling context + @param[in] Lba Block in which to begin write + @param[in] Offset Offset in the block at which to = begin write + @param[in, out] NumBytes On input, indicates the requeste= d write size. On + output, indicates the actual num= ber of bytes written + @param[in] Buffer Buffer containing source data fo= r the write. + + @retval EFI_SUCCESS The firmware volume was written successf= ully + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. O= n output, + NumBytes contains the total number of by= tes + actually written + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisab= led state + @retval EFI_DEVICE_ERROR The block device is not functioning corr= ectly and + could not be written + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL + +**/ +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + return FvbWriteBlock (FvbDevice->Instance, (EFI_LBA)Lba, (UINTN)Offset, = NumBytes, (UINT8 *)Buffer, mFvbModuleGlobal, FALSE); // Hard coded to FALSE= for SMM driver. +} + +/** + Reads data beginning at Lba:Offset from FV. The Read terminates either + when *NumBytes of data have been read, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + @param[in] This Calling context + @param[in] Lba Block in which to begin Read + @param[in] Offset Offset in the block at which to begin Read + @param[out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes Read + @param[in] Buffer Buffer containing source data for the Read. + + @retval EFI_SUCCESS The firmware volume was read successful= ly and + contents are in Buffer + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. O= n output, + NumBytes contains the total number of b= ytes returned + in Buffer + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisab= led state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be read + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL + +**/ +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + IN CONST UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + // return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buff= er, mFvbModuleGlobal, EfiGoneVirtual ()); + return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer,= mFvbModuleGlobal, FALSE); // Hard coded to FALSE for SMM driver. +} + +/** + Check the integrity of firmware volume header + + @param[in] FwVolHeader A pointer to a firmware volume header + + @retval EFI_SUCCESS The firmware volume is consistent + @retval EFI_NOT_FOUND The firmware volume has corrupted. So it= is not an FV + +**/ +EFI_STATUS +ValidateFvHeader ( + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +{ + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ((FwVolHeader->Revision !=3D EFI_FVH_REVISION) || + (FwVolHeader->Signature !=3D EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength =3D=3D ((UINTN)-1)) || + ((FwVolHeader->HeaderLength & 0x01) !=3D 0) + ) + { + return EFI_NOT_FOUND; + } + + // + // Verify the header checksum + // + if (CalculateCheckSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLengt= h) !=3D 0) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + + This function does common initialization for FVB services + + @param[in] ImageHandle A pointer to a image volume header + @param[in] SystemTable Pointer to the System Table + + @retval EFI_SUCCESS initialization for FVB services succe= ssfully + +**/ +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_DXE_SERVICES *DxeServices; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINT32 BufferSize; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + EFI_HANDLE FwbHandle; + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + UINT32 MaxLbaSize; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINTN NumOfBlocks; + UINT32 PlatformFvBaseAddress; + + // + // Get the DXE services table + // + DxeServices =3D gDS; + + // + // Allocate runtime services data for global variable, which contains + // the private data of all firmware volume block instances + // + mFvbModuleGlobal =3D AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL)); + ASSERT (mFvbModuleGlobal); + + Status =3D gSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOI= D **)&mFvbModuleGlobal->SpiProtocol); + ASSERT_EFI_ERROR (Status); + + // + // Calculate the total size for all firmware volume block instances + // + BufferSize =3D 0; + PlatformFvBaseAddress =3D PcdGet32 (PcdFlashNvStorageVariableBase); + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PlatformF= vBaseAddress; + BufferSize +=3D (FwVolHeader->HeaderLength + + sizeof (EFI_FW_VOL_INSTANCE) - + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + ); + + // + // Only need to allocate once. There is only one copy of physical memory= for + // the private data of each FV instance. But in virtual mode or in physi= cal + // mode, the address of the the physical memory may be different. + // + mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] =3D AllocateRuntimePool (Buff= erSize); + ASSERT (mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] !=3D NULL); + + // + // Make a virtual copy of the FvInstance pointer. + // + FwhInstance =3D mFvbModuleGlobal->FvInstan= ce[FVB_PHYSICAL]; + mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] =3D FwhInstance; + + mFvbModuleGlobal->NumFv =3D 0; + MaxLbaSize =3D 0; + + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PlatformFvBaseAddre= ss; + BaseAddress =3D (UINTN)FwVolHeader; + + // + // Check if it is a "real" flash + // + Status =3D DxeServices->GetMemorySpaceDescriptor ( + BaseAddress, + &Descriptor + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress; + Status =3D ValidateFvHeader (FwVolHeader); + if (EFI_ERROR (Status)) { + // + // Get FvbInfo to provide in FwhInstance. + // + Status =3D GetFvbInfo (BaseAddress, &FwVolHeader); + // + // Write healthy FV header back. + // + CopyMem ( + (VOID *)(UINTN)BaseAddress, + (VOID *)FwVolHeader, + FwVolHeader->HeaderLength + ); + } + + FwhInstance->FvBase[FVB_PHYSICAL] =3D (UINTN)BaseAddress; + FwhInstance->FvBase[FVB_VIRTUAL] =3D (UINTN)BaseAddress; + + CopyMem ((UINTN *)&(FwhInstance->VolumeHeader), (UINTN *)FwVolHeader, Fw= VolHeader->HeaderLength); + FwVolHeader =3D &(FwhInstance->VolumeHeader); + EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL); + + NumOfBlocks =3D 0; + + for (PtrBlockMapEntry =3D FwVolHeader->BlockMap; PtrBlockMapEntry->NumBl= ocks !=3D 0; PtrBlockMapEntry++) { + // + // Get the maximum size of a block. + // + if (MaxLbaSize < PtrBlockMapEntry->Length) { + MaxLbaSize =3D PtrBlockMapEntry->Length; + } + + NumOfBlocks =3D NumOfBlocks + PtrBlockMapEntry->NumBlocks; + } + + // + // The total number of blocks in the FV. + // + FwhInstance->NumOfBlocks =3D NumOfBlocks; + + // + // Add a FVB Protocol Instance + // + FvbDevice =3D AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE)); + ASSERT (FvbDevice !=3D NULL); + + CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE= )); + + FvbDevice->Instance =3D mFvbModuleGlobal->NumFv; + mFvbModuleGlobal->NumFv++; + + // + // Set up the devicepath + // + if (FwVolHeader->ExtHeaderOffset =3D=3D 0) { + // + // FV does not contains extension header, then produce MEMMAP_DEVICE_P= ATH + // + FvbDevice->DevicePath = =3D (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_MEMM= AP_DEVICE_PATH), &mFvMemmapDevicePathTemplate); + ((FV_MEMMAP_DEVICE_PATH *)FvbDevice->DevicePath)->MemMapDevPath.Starti= ngAddress =3D BaseAddress; + ((FV_MEMMAP_DEVICE_PATH *)FvbDevice->DevicePath)->MemMapDevPath.Ending= Address =3D BaseAddress + FwVolHeader->FvLength - 1; + } else { + FvbDevice->DevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool= (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate); + CopyGuid ( + &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName, + (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset) + ); + } + + FwbHandle =3D NULL; + Status =3D gSmst->SmmInstallProtocolInterface ( + &FwbHandle, + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + EFI_NATIVE_INTERFACE, + &FvbDevice->FwVolBlockInstance + ); + ASSERT_EFI_ERROR (Status); + FwhInstance =3D (EFI_FW_VOL_INSTANCE *) + ( + (UINTN)((UINT8 *)FwhInstance) + FwVolHeader->HeaderLength= + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLU= ME_HEADER)) + ); + + return EFI_SUCCESS; +} + +/** + Writes specified number of bytes from the input buffer to the address + + @param[in] WriteAddress The FV address to be written to + @param[in] Address The FV address to be written to + @param[in, out] NumBytes Pointer that on input contains the to= tal size of + the buffer. On output, it contains th= e total number + of bytes actually written + @param[in] Buffer Pointer to a caller allocated buffer = that contains + the source for the write + @param[in] LbaLength contains the length of the Buffer. + + @return The status returned from SpiProtocol(). + +**/ +EFI_STATUS +FlashFdWrite ( + IN UINTN WriteAddress, + IN UINTN Address, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN UINTN LbaLength + ) +{ + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + + // + // TODO: Suggested that this code be "critical section" + // + WriteAddress -=3D (PcdGet32 (PcdFlashAreaBaseAddress)); + Status =3D mFvbModuleGlobal->SpiProtocol->Execute ( + mFvbModuleGlobal->SpiPr= otocol, + SPI_OPCODE_WRITE_INDEX,= // OpcodeIndex + 0, = // PrefixOpcodeIndex + TRUE, = // DataCycle + TRUE, = // Atomic + TRUE, = // ShiftOut + WriteAddress, = // Address + (UINT32)(*NumBytes), = // Data Number + Buffer, + EnumSpiRegionBios + ); + + AsmWbinvd (); + + return Status; +} + +/** + Erase specified FV address + + @param[in] WriteAddress The FV address to be written to + @param[in] LbaLength contains the length of the Buffer. + + @return The status returned from SpiProtocol(). + +**/ +EFI_STATUS +FlashFdErase ( + IN UINTN WriteAddress, + IN UINTN LbaLength + ) +{ + EFI_STATUS Status; + SPI_INSTANCE *SpiInstance; + + Status =3D EFI_SUCCESS; + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (mFvbModuleGlobal->SpiPr= otocol); + WriteAddress -=3D (PcdGet32 (PcdFlashAreaBaseAddress)); + while ((INTN)LbaLength > 0) { + if ((WriteAddress >=3D 0) && (WriteAddress + LbaLength <=3D SpiInstanc= e->SpiInitTable.BiosSize)) { + Status =3D mFvbModuleGlobal->SpiProtocol->Execute ( + mFvbModuleGlobal->SpiProto= col, + SPI_OPCODE_ERASE_INDEX, //= OpcodeIndex + 0, //= PrefixOpcodeIndex + FALSE, //= DataCycle + TRUE, //= Atomic + TRUE, //= ShiftOut + WriteAddress, //= Address + 0, //= Data Number + NULL, + EnumSpiRegionBios // S= PI_REGION_TYPE + ); + + if (Status !=3D EFI_SUCCESS) { + return Status; + } + } + + WriteAddress +=3D SpiInstance->SpiInitTable.OpcodeMenu[SPI_OPCODE_ERAS= E_INDEX].Operation; + LbaLength -=3D SpiInstance->SpiInitTable.OpcodeMenu[SPI_OPCODE_ERAS= E_INDEX].Operation; + } + + AsmWbinvd (); + + return Status; +} + +#ifdef _MSC_VER + #pragma optimize( "", on ) +#endif +#ifdef __GNUC__ + #ifndef __clang__ + #pragma GCC pop_options + #endif +#endif diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlock= Service.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockS= ervice.h new file mode 100644 index 0000000000..a604f3be4b --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService= .h @@ -0,0 +1,515 @@ +/** @file + Implements FvbServicesSmm + Firmware volume block driver for SPI device + + 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 FW_BLOCK_SERVICE_SMM_H_ +#define FW_BLOCK_SERVICE_SMM_H_ + +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define FVB_PHYSICAL 0 +#define FVB_VIRTUAL 1 + +typedef struct { + EFI_LOCK FvbDevLock; + UINTN FvBase[2]; + UINTN NumOfBlocks; + EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; +} EFI_FW_VOL_INSTANCE; + +typedef struct { + UINT32 NumFv; + EFI_FW_VOL_INSTANCE *FvInstance[2]; + UINT8 *FvbScratchSpace[2]; + EFI_SPI_PROTOCOL *SpiProtocol; +} ESAL_FWB_GLOBAL; + +// +// Fvb Protocol instance data +// +#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, Fw= VolBlockInstance, FVB_DEVICE_SIGNATURE) +#define FVB_EXTEND_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, Fv= bExtension, FVB_DEVICE_SIGNATURE) +#define FVB_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'V', 'B', 'N') + +typedef struct { + MEDIA_FW_VOL_DEVICE_PATH FvDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_PIWG_DEVICE_PATH; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_MEMMAP_DEVICE_PATH; + +typedef struct { + UINTN Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN Instance; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; +} EFI_FW_VOL_BLOCK_DEVICE; + +/** + Get Fvb information. + + @param[in] BaseAddress The base address compare with NvStorageVariabl= e base address. + @param[out] FvbInfo Fvb information. + + @retval EFI_SUCCESS Get Fvb information successfully. + @retval EFI_NOT_FOUND Not find Fvb information. + +**/ +EFI_STATUS +GetFvbInfo ( + IN UINT64 FvLength, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ); + +/** + Reads specified number of bytes into a buffer from the specified block + + @param[in] Instance The FV instance to be read from + @param[in] Lba The logical block address to be read from + @param[in] BlockOffset Offset into the block at which to begin r= eading + @param[in, out] NumBytes Pointer that on input contains the total = size of + the buffer. On output, it contains the to= tal number + of bytes read + @param[in] Buffer Pointer to a caller allocated buffer that= will be + used to hold the data read + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains = all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS The firmware volume was read successful= ly and + contents are in Buffer + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. O= n output, + NumBytes contains the total number of b= ytes returned + in Buffer + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisab= led state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be read + @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer= are NULL + +**/ +EFI_STATUS +FvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + Writes specified number of bytes from the input buffer to the block + + @param[in] Instance The FV instance to be written to + @param[in] Lba The starting logical block index to write= to + @param[in] BlockOffset Offset into the block at which to begin w= riting + @param[in, out] NumBytes Pointer that on input contains the total = size of + the buffer. On output, it contains the to= tal number + of bytes actually written + @param[in] Buffer Pointer to a caller allocated buffer that= contains + the source for the write + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains = all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS The firmware volume was written success= fully + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. = On output, + NumBytes contains the total number of b= ytes + actually written + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisa= bled state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be written + @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer= are NULL + +**/ +EFI_STATUS +FvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + Erases and initializes a firmware volume block + + @param[in] Instance The FV instance to be erased + @param[in] Lba The logical block index to be erased + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS The erase request was successfully comp= leted + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisa= bled state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be written. Firmware device m= ay have been + partially erased + @retval EFI_INVALID_PARAMETER Instance not found + +**/ +EFI_STATUS +FvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + + @param[in] Instance The FV instance whose attributes is g= oing to be + modified + @param[in, out] Attributes On input, it is a pointer to EFI_FVB_= ATTRIBUTES_2 + containing the desired firmware volum= e settings. + On successful return, it contains the= new settings + of the firmware volume + @param[in] Global Pointer to ESAL_FWB_GLOBAL that conta= ins all + instance data + @param[in] Virtual Whether CPU is in virtual or physical= mode + + @retval EFI_SUCCESS Successfully returns + @retval EFI_ACCESS_DENIED The volume setting is locked and cannot= be modified + @retval EFI_INVALID_PARAMETER Instance not found, or The attributes r= equested are + in conflict with the capabilities as de= clared in the + firmware volume header + +**/ +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + Retrieves attributes, insures positive polarity of attribute bits, retur= ns + resulting attributes in output parameter + + @param[in] Instance The FV instance whose attributes is going to be + returned + @param[out] Attributes Output buffer which contains attributes + @param[in] Global Pointer to ESAL_FWB_GLOBAL that contains all + instance data + @param[in] Virtual Whether CPU is in virtual or physical mode + + @retval EFI_SUCCESS Successfully returns + @retval EFI_INVALID_PARAMETER Instance not found + +**/ +EFI_STATUS +FvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + Retrieves the physical address of the device. + + @param[in] This Calling context + @param[out] Address Output buffer containing the address. + + @retval EFI_SUCCESS Successfully returns + +**/ +EFI_STATUS +FvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *Address, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + + This function does common initialization for FVB services + + @param[in] ImageHandle A pointer to a image volume header + @param[in] SystemTable Pointer to the System Table + + @retval EFI_SUCCESS initialization for FVB services succe= ssfully + +**/ +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Retrieves the starting address of an LBA in an FV + + @param[in] Instance The FV instance which the Lba belong= s to + @param[in] Lba The logical block address + @param[out] LbaAddress On output, contains the physical sta= rting address + of the Lba + @param[out] LbaLength On output, contains the length of th= e block + @param[out] NumOfBlocks A pointer to a caller allocated UINT= N in which the + number of consecutive blocks startin= g with Lba is + returned. All blocks in this range h= ave a size of + BlockSize + @param[in] Global Pointer to ESAL_FWB_GLOBAL that cont= ains all + instance data + @param[in] Virtual Whether CPU is in virtual or physica= l mode + @retval EFI_SUCCESS Successfully returns + @retval EFI_INVALID_PARAMETER Instance not found + +**/ +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + Retrieves Volume attributes. No polarity translations are done. + + @param[in] This Calling context + @param[out] Attributes Output buffer which contains attribu= tes + + @retval EFI_SUCCESS Successfully returns + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +/** + Sets Volume attributes. No polarity translations are done. + + @param[in] This Calling context + @param[out] Attributes output buffer which contains attribu= tes + + @retval EFI_SUCCESS Successfully returns + +**/ +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +/** + Retrieves the physical address of the device. + + @param[in] This Calling context + @param[out] Address Output buffer containing the address. + + @retval EFI_SUCCESS Successfully returns + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +/** + Retrieve the size of a logical block + + @param[in] This alling context + @param[in] Lba Indicates which block to return the size for. + @param[out] BlockSize A pointer to a caller allocated UINTN in whi= ch + the size of the block is returned + @param[out] NumOfBlocks a pointer to a caller allocated UINTN in whi= ch the + number of consecutive blocks starting with L= ba is + returned. All blocks in this range have a si= ze of + BlockSize + + @retval EFI_SUCCESS The firmware volume was read successfully and + contents are in Buffer + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ); + +/** + Reads data beginning at Lba:Offset from FV. The Read terminates either + when *NumBytes of data have been read, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + @param[in] This Calling context + @param[in] Lba Block in which to begin Read + @param[in] Offset Offset in the block at which to begin Read + @param[out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes Read + @param[in] Buffer Buffer containing source data for the Read. + + @retval EFI_SUCCESS The firmware volume was read successful= ly and + contents are in Buffer + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. O= n output, + NumBytes contains the total number of b= ytes returned + in Buffer + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisab= led state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be read + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL + +**/ +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + IN CONST UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +/** + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + @param[in] This Calling context + @param[in] Lba Block in which to begin write + @param[in] Offset Offset in the block at which to = begin write + @param[in, out] NumBytes On input, indicates the requeste= d write size. On + output, indicates the actual num= ber of bytes written + @param[in] Buffer Buffer containing source data fo= r the write. + + @retval EFI_SUCCESS The firmware volume was written successf= ully + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. O= n output, + NumBytes contains the total number of by= tes + actually written + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisab= led state + @retval EFI_DEVICE_ERROR The block device is not functioning corr= ectly and + could not be written + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL + +**/ +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +/** + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be veri= fied + prior to erasing any blocks. If a block is requested that does not exist + within the associated firmware volume (it has a larger index than the la= st + block of the firmware volume), the EraseBlock() function must return + EFI_INVALID_PARAMETER without modifying the contents of the firmware vol= ume. + + @param[in] This Calling context + @param[in] ... Starting LBA followed by Number of L= ba to erase. + a -1 to terminate the list. + + @retval EFI_SUCCESS The erase request was successfully comp= leted + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisa= bled state + @retval EFI_DEVICE_ERROR The block device is not functioning cor= rectly and + could not be written. Firmware device m= ay have been + partially erased. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ); + +/** + Writes specified number of bytes from the input buffer to the address + + @param[in] WriteAddress The FV address to be written to + @param[in] Address The FV address to be written to + @param[in, out] NumBytes Pointer that on input contains the to= tal size of + the buffer. On output, it contains th= e total number + of bytes actually written + @param[in] Buffer Pointer to a caller allocated buffer = that contains + the source for the write + @param[in] LbaLength contains the length of the Buffer. + + @return The status returned from SpiProtocol(). + +**/ +EFI_STATUS +FlashFdWrite ( + IN UINTN WriteAddress, + IN UINTN Address, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN UINTN LbaLength + ); + +/** + Erase specified FV address + + @param[in] WriteAddress The FV address to be written to + @param[in] LbaLength contains the length of the Buffer. + + @return The status returned from SpiProtocol(). + +**/ +EFI_STATUS +FlashFdErase ( + IN UINTN WriteAddress, + IN UINTN LbaLength + ); + +#endif diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/Platfor= mSmmSpi.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/Platfo= rmSmmSpi.inf new file mode 100644 index 0000000000..0a620662d2 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/PlatformSmmSpi= .inf @@ -0,0 +1,68 @@ +## @file +# FvbServicesSmm +# Component description file for SpiFvbServices Module +# +# 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 +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D FvbServicesSmm + FILE_GUID =3D 72A87810-D3A3-36BE-4788-49AA4003DFD3 + MODULE_TYPE =3D DXE_SMM_DRIVER + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x0001000A + ENTRY_POINT =3D FvbInitialize + +[Sources] + FwBlockService.c + FwBlockService.h + FvbInfo.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + VanGoghCommonPkg/AmdCommonPkg.dec + ChachaniBoardPkg/Project.dec + +[LibraryClasses] + UefiLib + UefiDriverEntryPoint + BaseLib + DebugLib + BaseMemoryLib + MemoryAllocationLib + DxeServicesTableLib + UefiBootServicesTableLib + SmmServicesTableLib + DevicePathLib + HobLib + PcdLib + +[Guids] + gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED Create = Event: EVENT_GROUP_GUID + gEfiSystemNvDataFvGuid + +[Protocols] + gEfiSmmFirmwareVolumeBlockProtocolGuid + gEfiSmmSpiProtocolGuid + +[FixedPcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize + gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + + +[Depex] + gEfiSmmBase2ProtocolGuid AND + gEfiSmmSpiProtocolGuid --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114587): https://edk2.groups.io/g/devel/message/114587 Mute This Topic: https://groups.io/mt/103975452/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-