From nobody Fri Nov 1 05:22:41 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1523339626247150.22421635333387; Mon, 9 Apr 2018 22:53:46 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 11D6C225FA070; Mon, 9 Apr 2018 22:53:44 -0700 (PDT) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id EDBA1225FA052 for ; Mon, 9 Apr 2018 22:53:42 -0700 (PDT) Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Apr 2018 22:53:42 -0700 Received: from mdkinney-mobl2.amr.corp.intel.com ([10.254.74.27]) by fmsmga004.fm.intel.com with ESMTP; 09 Apr 2018 22:53:41 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.115; helo=mga14.intel.com; envelope-from=michael.d.kinney@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,430,1517904000"; d="scan'208";a="44905372" From: "Kinney, Michael D" To: edk2-devel@lists.01.org Date: Mon, 9 Apr 2018 22:53:38 -0700 Message-Id: <20180410055339.17532-2-michael.d.kinney@intel.com> X-Mailer: git-send-email 2.14.2.windows.3 In-Reply-To: <20180410055339.17532-1-michael.d.kinney@intel.com> References: <20180410055339.17532-1-michael.d.kinney@intel.com> Subject: [edk2] [Patch 1/2] SignedCapsulePkg/SystemFirmwareUpdateDxe: Single FMP X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael D Kinney , Jiewen Yao MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" https://bugzilla.tianocore.org/show_bug.cgi?id=3D928 Uninstall all System FMP Protocols for the current FW device. If an FMP Protocol for the current FW device is already present, then install the new System FMP protocol onto the same handle as the FMP Protocol. Otherwise, install the FMP protocol onto a new handle. This supports use cases where multiple capsules for the same system firmware device are processed on the same boot of the platform. It guarantees there is at most one FMP protocol for each system firmware device. Cc: Jiewen Yao Signed-off-by: Michael D Kinney Contributed-under: TianoCore Contribution Agreement 1.1 --- .../SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c | 343 +++++++++++++++++= ++-- 1 file changed, 322 insertions(+), 21 deletions(-) diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmware= UpdateDxe.c b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwar= eUpdateDxe.c index fd6641eb3e..d0b1c9913c 100644 --- a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateD= xe.c +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateD= xe.c @@ -8,7 +8,7 @@ =20 FmpSetImage() will receive untrusted input and do basic validation. =20 - Copyright (c) 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -476,54 +476,355 @@ FmpSetImage ( return Status; } =20 +/** + Get the set of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures from an FMP Prot= ocol. + + @param[in] Handle Handle with an FMP Protocol or a System F= MP + Protocol. + @param[in] ProtocolGuid Pointer to the FMP Protocol GUID or Syste= m FMP + Protocol GUID. + @param[out] FmpImageInfoCount Pointer to the number of + EFI_FIRMWARE_IMAGE_DESCRIPTOR structures. + @param[out] DescriptorSize Pointer to the size, in bytes, of each + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure. + + @return NULL No EFI_FIRMWARE_IMAGE_DESCRIPTOR structures found. + @return !NULL Pointer to a buffer of EFI_FIRMWARE_IMAGE_DESCRIPTOR stru= ctures + allocated using AllocatePool(). Caller must free buffer = with + FreePool(). +**/ +EFI_FIRMWARE_IMAGE_DESCRIPTOR * +GetFmpImageDescriptors ( + IN EFI_HANDLE Handle, + IN EFI_GUID *ProtocolGuid, + OUT UINT8 *FmpImageInfoCount, + OUT UINTN *DescriptorSize + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; + UINTN ImageInfoSize; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; + UINT32 FmpImageInfoDescriptorVer; + UINT32 PackageVersion; + CHAR16 *PackageVersionName; + + *FmpImageInfoCount =3D 0; + *DescriptorSize =3D 0; + + Status =3D gBS->HandleProtocol ( + Handle, + ProtocolGuid, + (VOID **)&Fmp + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Determine the size required for the set of EFI_FIRMWARE_IMAGE_DESCRIP= TORs. + // + ImageInfoSize =3D 0; + Status =3D Fmp->GetImageInfo ( + Fmp, // FMP Pointer + &ImageInfoSize, // Buffer Size (in this cas= e 0) + NULL, // NULL so we can get size + &FmpImageInfoDescriptorVer, // DescriptorVersion + FmpImageInfoCount, // DescriptorCount + DescriptorSize, // DescriptorSize + &PackageVersion, // PackageVersion + &PackageVersionName // PackageVersionName + ); + if (Status !=3D EFI_BUFFER_TOO_SMALL) { + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Unexpected Failure. St= atus =3D %r\n", Status)); + return NULL; + } + + // + // Allocate buffer for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + // + FmpImageInfoBuf =3D NULL; + FmpImageInfoBuf =3D AllocateZeroPool (ImageInfoSize); + if (FmpImageInfoBuf =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to allocate memo= ry for descriptors.\n")); + return NULL; + } + + // + // Retrieve the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + // + PackageVersionName =3D NULL; + Status =3D Fmp->GetImageInfo ( + Fmp, + &ImageInfoSize, // ImageInfoSize + FmpImageInfoBuf, // ImageInfo + &FmpImageInfoDescriptorVer, // DescriptorVersion + FmpImageInfoCount, // DescriptorCount + DescriptorSize, // DescriptorSize + &PackageVersion, // PackageVersion + &PackageVersionName // PackageVersionName + ); + + // + // Free unused PackageVersionName return buffer + // + if (PackageVersionName !=3D NULL) { + FreePool (PackageVersionName); + PackageVersionName =3D NULL; + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failure in GetImageInfo= . Status =3D %r\n", Status)); + if (FmpImageInfoBuf !=3D NULL) { + FreePool (FmpImageInfoBuf); + } + return NULL; + } + + return FmpImageInfoBuf; +} + +/** + Search for handles with an FMP protocol whose EFI_FIRMWARE_IMAGE_DESCRIP= TOR + ImageTypeId matches the ImageTypeId produced by this module. + + @param[in] ProtocolGuid Pointer to the GUID of the protocol to search. + @param[out] HandleCount Pointer to the number of returned handles. + + @return NULL No matching handles found. + @return !NULL Pointer to a buffer of handles allocated using AllocatePo= ol(). + Caller must free buffer with FreePool(). +**/ +EFI_HANDLE * +FindMatchingFmpHandles ( + IN EFI_GUID *ProtocolGuid, + OUT UINTN *HandleCount + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN Index; + UINTN Index2; + UINTN Index3; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *OriginalFmpImageInfoBuf; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; + UINT8 FmpImageInfoCount; + UINTN DescriptorSize; + BOOLEAN MatchFound; + + *HandleCount =3D 0; + HandleBuffer =3D NULL; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + ProtocolGuid, + NULL, + HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + *HandleCount =3D 0; + return NULL; + } + + for (Index =3D 0; Index < *HandleCount; Index++) { + OriginalFmpImageInfoBuf =3D GetFmpImageDescriptors ( + HandleBuffer[Index], + ProtocolGuid, + &FmpImageInfoCount, + &DescriptorSize + ); + + // + // Loop through the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + // + FmpImageInfoBuf =3D OriginalFmpImageInfoBuf; + MatchFound =3D FALSE; + for (Index2 =3D 0; Index2 < FmpImageInfoCount; Index2++) { + for (Index3 =3D 0; Index3 < mSystemFmpPrivate->DescriptorCount; Inde= x3++) { + MatchFound =3D CompareGuid ( + &FmpImageInfoBuf->ImageTypeId, + &mSystemFmpPrivate->ImageDescriptor[Index3].ImageTy= peId + ); + if (MatchFound) { + break; + } + } + if (MatchFound) { + break; + } + // + // Increment the buffer pointer ahead by the size of the descriptor + // + FmpImageInfoBuf =3D (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpI= mageInfoBuf) + DescriptorSize); + } + if (!MatchFound) { + HandleBuffer[Index] =3D NULL; + } + + FreePool (OriginalFmpImageInfoBuf); + } + return HandleBuffer; +} + +/** + Uninstall System FMP Protocol instances that may have been installed by + SystemFirmwareUpdateDxe drivers dispatches by other capsules. + + @retval EFI_SUCCESS All System FMP Protocols found were uninstalled. + @return Other One or more System FMP Protocols could not be unins= talled. + +**/ +EFI_STATUS +UninstallMatchingSystemFmpProtocols ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *SystemFmp; + + // + // Uninstall SystemFmpProtocol instances that may have been produced by + // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules. + // + HandleBuffer =3D FindMatchingFmpHandles ( + &gSystemFmpProtocolGuid, + &HandleCount + ); + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching System F= MP instances\n", HandleCount)); + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol( + HandleBuffer[Index], + &gSystemFmpProtocolGuid, + (VOID **)&SystemFmp + ); + if (EFI_ERROR (Status)) { + continue; + } + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Uninstall SystemFmp prod= uced by another capsule\n")); + Status =3D gBS->UninstallProtocolInterface ( + HandleBuffer[Index], + &gSystemFmpProtocolGuid, + SystemFmp + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to uninstall S= ystemFmp %r. Exiting.\n", Status)); + FreePool (HandleBuffer); + return Status; + } + } + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + /** System FMP module entrypoint =20 - @param ImageHandle The firmware allocated handle for the EFI imag= e. - @param SystemTable A pointer to the EFI System Table. + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. =20 - @return EFI_SUCCESS System FMP module is initialized. + @retval EFI_SUCCESS System FMP module is initialized. + @retval EFI_OUT_OF_RESOURCES There are not enough resources avaulable to + initialize this module. + @retval Other System FMP Protocols could not be uninstal= led. + @retval Other System FMP Protocol could not be installed. + @retval Other FMP Protocol could not be installed. **/ EFI_STATUS EFIAPI SystemFirmwareUpdateMainDxe ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; =20 // // Initialize SystemFmpPrivateData // - mSystemFmpPrivate =3D AllocateZeroPool (sizeof(SYSTEM_FMP_PRIVATE_DATA)); + mSystemFmpPrivate =3D AllocateZeroPool (sizeof (SYSTEM_FMP_PRIVATE_DATA)= ); if (mSystemFmpPrivate =3D=3D NULL) { return EFI_OUT_OF_RESOURCES; } =20 - Status =3D InitializePrivateData(mSystemFmpPrivate); - if (EFI_ERROR(Status)) { - FreePool(mSystemFmpPrivate); + Status =3D InitializePrivateData (mSystemFmpPrivate); + if (EFI_ERROR (Status)) { + FreePool (mSystemFmpPrivate); mSystemFmpPrivate =3D NULL; return Status; } =20 // - // Install FMP protocol. + // Uninstall SystemFmpProtocol instances that may have been produced by + // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules. // - Status =3D gBS->InstallMultipleProtocolInterfaces ( - &mSystemFmpPrivate->Handle, - &gEfiFirmwareManagementProtocolGuid, - &mSystemFmpPrivate->Fmp, - &gSystemFmpProtocolGuid, - &mSystemFmpPrivate->Fmp, - NULL - ); + Status =3D UninstallMatchingSystemFmpProtocols (); if (EFI_ERROR (Status)) { - FreePool(mSystemFmpPrivate); + FreePool (mSystemFmpPrivate); mSystemFmpPrivate =3D NULL; return Status; } =20 + // + // Look for a handle with matching Firmware Management Protocol + // + HandleCount =3D 0; + HandleBuffer =3D FindMatchingFmpHandles ( + &gEfiFirmwareManagementProtocolGuid, + &HandleCount + ); + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching FMP inst= ances\n", HandleCount)); + + switch (HandleCount) { + case 0: + // + // Install FMP protocol onto a new handle. + // + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install FMP onto a new h= andle\n")); + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mSystemFmpPrivate->Handle, + &gEfiFirmwareManagementProtocolGuid, + &mSystemFmpPrivate->Fmp, + NULL + ); + break; + case 1: + // + // Install System FMP protocol onto handle with matching FMP Protocol + // + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install System FMP onto = matching FMP handle\n")); + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &HandleBuffer[0], + &gSystemFmpProtocolGuid, + &mSystemFmpPrivate->Fmp, + NULL + ); + break; + default: + // + // More than one matching handle is not expected. Unload driver. + // + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: More than one matching = FMP handle. Unload driver.\n")); + Status =3D EFI_DEVICE_ERROR; + break; + } + + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + if (EFI_ERROR (Status)) { + FreePool (mSystemFmpPrivate); + mSystemFmpPrivate =3D NULL; + } + return Status; } --=20 2.14.2.windows.3 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel