From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM02-SN1-obe.outbound.protection.outlook.com (NAM02-SN1-obe.outbound.protection.outlook.com [40.92.5.28]) by mx.groups.io with SMTP id smtpd.web11.8889.1603152024120301753 for ; Mon, 19 Oct 2020 17:00:24 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@outlook.com header.s=selector1 header.b=QXOGLy5D; spf=pass (domain: outlook.com, ip: 40.92.5.28, mailfrom: michael.kubacki@outlook.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=F8xmI+eu30NSvQfd/cINzLjqmrvUcJcQquX0q0Z1Xof0jXRs9WMsQNlq6EcYJzwtNV5OsnMaERiSyO8ttpWANUBKlmcp7tjcpRgexP9zDv0ec0bZz4CwEMuyYeb3rTe4uGx7wa5tRNq0hg4auvRWX9A4CnBWLtL6TGxDiiVNkveUcMUf/wEt3BT5kiAvxPV48COa3p3HYlbSOYPgUJIt5saMewSg6tCzAdBuKSzjADsDMnvWG2AkoyoCUjY7USSS4mjX0gd3/gnWmRspIAZQrK5FvKtvqsXToQZ7ffKJc509rO8gJGro+enX7XHxpi1hArxX72gN8UfZbpNvWw6ONQ== 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-SenderADCheck; bh=bPBiybKReVhVAwpnUpy/PZroED/HvQ0py2VIhyDco90=; b=a4esZk8n2/vkUSEoxxaym77NYwiwT9GH1wezvnxdhPMexFxisD8tH/N+LYqaW5tni7AFBjNTNXEQROjepbuAwD5ISDVk4xxjUgBuc9wIFkUOT1GlDiLOQQUDUQXvtrd99F2ipLp1RTv2toJvKfb3ltWztZ3tpQrvIuHABoDKT4E1RFh+M8H+WbGgH2olOAkxlVmIccDdxBowmg9f1SaC2Vf7BDRbg+VNVtR8Ns+n+WRH+xsqhhLOeuiyQuiDTJZK3eCfRd8CdrrAjJVuQYMC1Dp4FNpkx1ZX4djg9OEvsj4zBA61nk66BqbCOun/qHDeDGDuJEwgkugEpgV1tzBxpQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=bPBiybKReVhVAwpnUpy/PZroED/HvQ0py2VIhyDco90=; b=QXOGLy5D5HVkQ+kD2EmUErG/aVujkFn9iZo4Qb2cdZ595HV+c2KiIpz4Jercl2WqZ8+xqQYSzpLObs6jhwRq9O+G7EFUf0kNDSCCH/5RXjgfLR7Oltxsde0hXYyTPkgSg9jzJ4hY2bR8XSRux0P1VckhupMic01W9tnN+ZLpbTGLuv7woGDOo1WWK0z66ASZssXWqISHnDvo5FznVWvPdfMWAZ1PnlIeoqgWhhMYl4ay9LjWWP2GJh8BWRED7PrnY0yW+rgCluHR0paLcbRv8DEGdsPRE4gxarbblaFBxx36oJto0/mnSqui5VZSv62HpbDljJ/0JYIwNdd+O/ETgA== Received: from CY1NAM02FT029.eop-nam02.prod.protection.outlook.com (10.152.74.57) by CY1NAM02HT241.eop-nam02.prod.protection.outlook.com (10.152.74.70) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3477.21; Tue, 20 Oct 2020 00:00:21 +0000 Received: from MWHPR07MB3440.namprd07.prod.outlook.com (2a01:111:e400:7e45::4e) by CY1NAM02FT029.mail.protection.outlook.com (2a01:111:e400:7e45::399) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3477.21 via Frontend Transport; Tue, 20 Oct 2020 00:00:21 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:DA619884C075225DA27879A2C768417FAD217B66BA501C04A80557AE2F658910;UpperCasedChecksum:6290131095B2E170F97BDBBE39121BBFF74E75D5A87A965653DA20ED9F3BBF17;SizeAsReceived:7676;Count:47 Received: from MWHPR07MB3440.namprd07.prod.outlook.com ([fe80::858f:bd50:1b65:e803]) by MWHPR07MB3440.namprd07.prod.outlook.com ([fe80::858f:bd50:1b65:e803%7]) with mapi id 15.20.3477.028; Tue, 20 Oct 2020 00:00:21 +0000 From: "Michael Kubacki" To: devel@edk2.groups.io CC: Liming Gao , Michael D Kinney , Guomin Jiang , Wei6 Xu Subject: [PATCH v6 5/6] FmpDevicePkg: Add Last Attempt Status support to dependency libs Date: Mon, 19 Oct 2020 16:59:38 -0700 Message-ID: X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20201019235939.2320-1-michael.kubacki@outlook.com> References: <20201019235939.2320-1-michael.kubacki@outlook.com> X-TMN: [3rVZtU4qoNWQf13zcXPVSyJTDn68wVPdJWyORrCulSOBMn1gqna3IUOATi6sNuwx] X-ClientProxiedBy: MWHPR14CA0067.namprd14.prod.outlook.com (2603:10b6:300:81::29) To MWHPR07MB3440.namprd07.prod.outlook.com (2603:10b6:301:69::28) Return-Path: michael.kubacki@outlook.com X-Microsoft-Original-Message-ID: <20201019235939.2320-6-michael.kubacki@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (2001:4898:80e8:2:819c:275:72be:ff50) by MWHPR14CA0067.namprd14.prod.outlook.com (2603:10b6:300:81::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3477.21 via Frontend Transport; Tue, 20 Oct 2020 00:00:17 +0000 X-MS-PublicTrafficType: Email X-IncomingHeaderCount: 47 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-Correlation-Id: b90682f3-9253-4d8a-4d88-08d8748b2119 X-MS-TrafficTypeDiagnostic: CY1NAM02HT241: X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: ZYZP/MUVl6NaMg42VAh8CpxRrFbTgo3d8JpRmZQILgFxnte6MY/g5NGxow5QfbuIOw4c+AayzUKKONZOPqcCF1LWl++9iBbvATZ6QHiZqyXjpQRI1GjinGW147zeRxjgYVsxbLCMNF6lM6X2EK1hbDpV/RSfa8fqZTFO9jpctsCSxGtwwMqV63sRyQAQwGf9ESMc9dfuiCrgpF8SMirxQg== X-MS-Exchange-AntiSpam-MessageData: lyB78mypCfaRQP5jkZiq/Bdi80LQO+wvNffRVUleEWUAjCbZyT2ywtFqwZ7yHp52kf7z5Kq9fmrqaaK+qB2qulC16zDY4g7MsF7vHkl5mEHpbDUYoorylY6VB+G0iBHxyZ4TmuyR06m50Iviq6nxPymD1sbZzg4QGdR6vQq1PWSwwxAWUY8Y17qbqXR0ko5VHiM/qUryEITqhChX+GmOtw== X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: b90682f3-9253-4d8a-4d88-08d8748b2119 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Oct 2020 00:00:18.0346 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-AuthSource: CY1NAM02FT029.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1NAM02HT241 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Michael Kubacki The FMP dependency libraries are leveraged during firmware update to check for dependencies required to update the image. This change adds granular Last Attempt Status code support to these services so failures can be more easily observed during the firmware update process via Last Attempt Status codes. Cc: Liming Gao Cc: Michael D Kinney Cc: Guomin Jiang Cc: Wei6 Xu Signed-off-by: Michael Kubacki Acked-by: Liming Gao Reviewed-by: Wei6 Xu --- FmpDevicePkg/FmpDxe/FmpDxe.c = | 31 ++++++- FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c = | 39 +++++--- FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c= | 14 ++- FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c = | 93 +++++++++++++++++--- FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnit= Test.c | 7 +- FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h = | 8 +- FmpDevicePkg/Include/Library/FmpDependencyLib.h = | 44 +++++---- 7 files changed, 189 insertions(+), 47 deletions(-) diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c index b7fd9c93aea0..de7f1fe53e32 100644 --- a/FmpDevicePkg/FmpDxe/FmpDxe.c +++ b/FmpDevicePkg/FmpDxe/FmpDxe.c @@ -730,6 +730,15 @@ GetAllHeaderSize ( LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE= _VALUE to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_C= ODE_VALUE. =20 + This function might also return error cod= es that occur within libraries + linked against this module that return la= st attempt error codes such as: + + LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MI= N_ERROR_CODE_VALUE to + LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MA= X_ERROR_CODE_VALUE + + LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_= LIB_MIN_ERROR_CODE_VALUE to + LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_= LIB_MAX_ERROR_CODE_VALUE + @retval EFI_SUCCESS The image was successfully checked. @retval EFI_ABORTED The operation is aborted. @retval EFI_INVALID_PARAMETER The Image was NULL. @@ -925,7 +934,16 @@ CheckTheImageInternal ( // // Get the dependency from Image. // - Dependencies =3D GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION = *)Image, ImageSize, &DependenciesSize); + Dependencies =3D GetImageDependency ( + (EFI_FIRMWARE_IMAGE_AUTHENTICATION *) Image, + ImageSize, + &DependenciesSize, + LastAttemptStatus + ); + if (*LastAttemptStatus !=3D LAST_ATTEMPT_STATUS_SUCCESS) { + Status =3D EFI_ABORTED; + goto cleanup; + } =20 // // Check the FmpPayloadHeader @@ -964,11 +982,18 @@ CheckTheImageInternal ( // // Evaluate dependency expression // - Private->DependenciesSatisfied =3D CheckFmpDependency (Private->Descript= or.ImageTypeId, Version, Dependencies, DependenciesSize); + Private->DependenciesSatisfied =3D CheckFmpDependency ( + Private->Descriptor.ImageTypeId, + Version, + Dependencies, + DependenciesSize, + &LocalLastAttemptStatus + ); if (!Private->DependenciesSatisfied) { DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check f= ailed.\n", mImageIdName)); *ImageUpdatable =3D IMAGE_UPDATABLE_INVALID; Status =3D EFI_SUCCESS; + *LastAttemptStatus =3D LocalLastAttemptStatus; goto cleanup; } =20 @@ -1181,7 +1206,7 @@ SetTheImage ( // // Get the dependency from Image. // - Dependencies =3D GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION = *)Image, ImageSize, &DependenciesSize); + Dependencies =3D GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION = *)Image, ImageSize, &DependenciesSize, &LastAttemptStatus); =20 // // No functional error in CheckTheImage. Attempt to get the Version to diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckL= ib.c b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c index 02ed600e0e95..cca83dbe4a14 100644 --- a/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c +++ b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include =20 /** Check dependency for firmware update. @@ -25,6 +28,10 @@ @param[in] Version New version. @param[in] Dependencies Fmp dependency. @param[in] DependenciesSize Size, in bytes, of the Fmp dependency. + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hold= s the + last attempt status to report back to the= caller. + This function will set the value to LAST_= ATTEMPT_STATUS_SUCCESS + if an error code is not set. =20 @retval TRUE Dependencies are satisfied. @retval FALSE Dependencies are unsatisfied or dependency check fails. @@ -36,7 +43,8 @@ CheckFmpDependency ( IN EFI_GUID ImageTypeId, IN UINT32 Version, IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL - IN UINT32 DependenciesSize + IN UINT32 DependenciesSize, + OUT UINT32 *LastAttemptStatus OPTIONAL ) { EFI_STATUS Status; @@ -44,6 +52,7 @@ CheckFmpDependency ( UINTN Index; EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; UINTN ImageInfoSize; + UINT32 LocalLastAttemptStatus; UINT32 *DescriptorVer; UINT8 FmpImageInfoCount; UINTN *DescriptorSize; @@ -55,14 +64,15 @@ CheckFmpDependency ( UINTN FmpVersionsCount; BOOLEAN IsSatisfied; =20 - FmpImageInfoBuf =3D NULL; - DescriptorVer =3D NULL; - DescriptorSize =3D NULL; - NumberOfFmpInstance =3D 0; - FmpVersions =3D NULL; - FmpVersionsCount =3D 0; - IsSatisfied =3D TRUE; - PackageVersionName =3D NULL; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; + FmpImageInfoBuf =3D NULL; + DescriptorVer =3D NULL; + DescriptorSize =3D NULL; + NumberOfFmpInstance =3D 0; + FmpVersions =3D NULL; + FmpVersionsCount =3D 0; + IsSatisfied =3D TRUE; + PackageVersionName =3D NULL; =20 // // Get ImageDescriptors of all FMP instances, and archive them for depen= dency evaluation. @@ -77,30 +87,35 @@ CheckFmpDependency ( if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "CheckFmpDependency: Get Firmware Management Prot= ocol failed. (%r)", Status)); IsSatisfied =3D FALSE; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ER= ROR_FMP_PROTOCOL_NOT_FOUND; goto cleanup; } =20 FmpImageInfoBuf =3D AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPT= OR *) * NumberOfFmpInstance); if (FmpImageInfoBuf =3D=3D NULL) { IsSatisfied =3D FALSE; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ER= ROR_MEM_ALLOC_FMP_INFO_BUFFER_FAILED; goto cleanup; } =20 DescriptorVer =3D AllocateZeroPool (sizeof(UINT32) * NumberOfFmpInstance= ); if (DescriptorVer =3D=3D NULL ) { IsSatisfied =3D FALSE; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ER= ROR_MEM_ALLOC_DESC_VER_BUFFER_FAILED; goto cleanup; } =20 DescriptorSize =3D AllocateZeroPool (sizeof(UINTN) * NumberOfFmpInstance= ); if (DescriptorSize =3D=3D NULL ) { IsSatisfied =3D FALSE; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ER= ROR_MEM_ALLOC_DESC_SIZE_BUFFER_FAILED; goto cleanup; } =20 FmpVersions =3D AllocateZeroPool (sizeof(FMP_DEPEX_CHECK_VERSION_DATA) *= NumberOfFmpInstance); if (FmpVersions =3D=3D NULL) { IsSatisfied =3D FALSE; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ER= ROR_MEM_ALLOC_FMP_VER_BUFFER_FAILED; goto cleanup; } =20 @@ -164,7 +179,7 @@ CheckFmpDependency ( // Evaluate firmware image's depex, against the version of other Fmp ins= tances. // if (Dependencies !=3D NULL) { - IsSatisfied =3D EvaluateDependency (Dependencies, DependenciesSize, Fm= pVersions, FmpVersionsCount); + IsSatisfied =3D EvaluateDependency (Dependencies, DependenciesSize, Fm= pVersions, FmpVersionsCount, &LocalLastAttemptStatus); } =20 if (!IsSatisfied) { @@ -194,5 +209,9 @@ CheckFmpDependency ( FreePool (FmpVersions); } =20 + if (LastAttemptStatus !=3D NULL) { + *LastAttemptStatus =3D LocalLastAttemptStatus; + } + return IsSatisfied; } diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCh= eckLibNull.c b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependency= CheckLibNull.c index 55e9af22909d..74247957ac4f 100644 --- a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibN= ull.c +++ b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibN= ull.c @@ -2,11 +2,13 @@ Null instance of FmpDependencyCheckLib. =20 Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ #include +#include #include =20 /** @@ -16,7 +18,10 @@ @param[in] Version New version. @param[in] Dependencies Fmp dependency. @param[in] DependenciesSize Size, in bytes, of the Fmp dependency. - + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hold= s the + last attempt status to report back to the= caller. + This function will set the value to LAST_= ATTEMPT_STATUS_SUCCESS + if an error code is not set. @retval TRUE Dependencies are satisfied. @retval FALSE Dependencies are unsatisfied or dependency check fails. =20 @@ -27,8 +32,13 @@ CheckFmpDependency ( IN EFI_GUID ImageTypeId, IN UINT32 Version, IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL - IN UINT32 DependenciesSize + IN UINT32 DependenciesSize, + OUT UINT32 *LastAttemptStatus OPTIONAL ) { + if (LastAttemptStatus !=3D NULL) { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; + } + return TRUE; } diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c b/Fmp= DevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c index 5ef25d2415cf..b222ace6d6ca 100644 --- a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c +++ b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include =20 // // Define the initial size of the dependency expression evaluation stack @@ -203,6 +206,10 @@ Pop ( parameter is optional and can be set to = NULL. @param[in] FmpVersionsCount Element count of the array. When FmpVers= ions is NULL, FmpVersionsCount must be 0. + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hol= ds the + last attempt status to report back to th= e caller. + This function will set the value to LAST= _ATTEMPT_STATUS_SUCCESS + if an error code is not set. =20 @retval TRUE Dependency expressions evaluate to TRUE. @retval FALSE Dependency expressions evaluate to FALSE. @@ -211,10 +218,11 @@ Pop ( BOOLEAN EFIAPI EvaluateDependency ( - IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, - IN UINTN DependenciesSize, - IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL, - IN UINTN FmpVersionsCount + IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, + IN UINTN DependenciesSize, + IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions, OPTIONAL + IN UINTN FmpVersionsCount, + OUT UINT32 *LastAttemptStatus OPTIONAL ) { EFI_STATUS Status; @@ -224,6 +232,9 @@ EvaluateDependency ( DEPEX_ELEMENT Element2; GUID ImageTypeId; UINT32 Version; + UINT32 LocalLastAttemptStatus; + + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; =20 // // Check if parameter is valid. @@ -249,6 +260,7 @@ EvaluateDependency ( case EFI_FMP_DEP_PUSH_GUID: if (Iterator + sizeof (EFI_GUID) >=3D (UINT8 *) Dependencies->Depend= encies + DependenciesSize) { DEBUG ((DEBUG_ERROR, "EvaluateDependency: GUID extends beyond end = of dependency expression!\n")); + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_GUID_BEYOND_DEPEX; goto Error; } =20 @@ -259,6 +271,7 @@ EvaluateDependency ( if(CompareGuid (&FmpVersions[Index].ImageTypeId, &ImageTypeId)){ Status =3D Push (FmpVersions[Index].Version, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_= ERROR_PUSH_FAILURE; goto Error; } break; @@ -266,18 +279,21 @@ EvaluateDependency ( } if (Index =3D=3D FmpVersionsCount) { DEBUG ((DEBUG_ERROR, "EvaluateDependency: %g is not found!\n", &Im= ageTypeId)); + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_FMP_NOT_FOUND; goto Error; } break; case EFI_FMP_DEP_PUSH_VERSION: if (Iterator + sizeof (UINT32) >=3D (UINT8 *) Dependencies->Dependen= cies + DependenciesSize ) { DEBUG ((DEBUG_ERROR, "EvaluateDependency: VERSION extends beyond e= nd of dependency expression!\n")); + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_VERSION_BEYOND_DEPEX; goto Error; } =20 Version =3D *(UINT32 *) (Iterator + 1); Status =3D Push (Version, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } Iterator =3D Iterator + sizeof (UINT32); @@ -286,154 +302,191 @@ EvaluateDependency ( Iterator +=3D AsciiStrnLenS ((CHAR8 *) Iterator, DependenciesSize - = (Iterator - Dependencies->Dependencies)); if (Iterator =3D=3D (UINT8 *) Dependencies->Dependencies + Dependenc= iesSize) { DEBUG ((DEBUG_ERROR, "EvaluateDependency: STRING extends beyond en= d of dependency expression!\n")); + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_VERSION_STR_BEYOND_DEPEX; goto Error; } break; case EFI_FMP_DEP_AND: Status =3D Pop (&Element1, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Pop (&Element2, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Push (Element1.Value.Boolean & Element2.Value.Boolean, Bo= oleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_OR: Status =3D Pop (&Element1, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Pop(&Element2, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Push (Element1.Value.Boolean | Element2.Value.Boolean, Bo= oleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_NOT: Status =3D Pop (&Element1, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Push (!(Element1.Value.Boolean), BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_TRUE: Status =3D Push (TRUE, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_FALSE: Status =3D Push (FALSE, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_EQ: Status =3D Pop (&Element1, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Pop (&Element2, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D (Element1.Value.Version =3D=3D Element2.Value.Version) ? = Push (TRUE, BooleanType) : Push (FALSE, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_GT: Status =3D Pop (&Element1, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Pop (&Element2, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D (Element1.Value.Version > Element2.Value.Version) ? Push= (TRUE, BooleanType) : Push (FALSE, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_GTE: Status =3D Pop (&Element1, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Pop (&Element2, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D (Element1.Value.Version >=3D Element2.Value.Version) ? Pu= sh (TRUE, BooleanType) : Push (FALSE, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_LT: Status =3D Pop (&Element1, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Pop (&Element2, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus=3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR= _POP_FAILURE; goto Error; } Status =3D (Element1.Value.Version < Element2.Value.Version) ? Push= (TRUE, BooleanType) : Push (FALSE, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_LTE: Status =3D Pop (&Element1, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D Pop (&Element2, VersionType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } Status =3D (Element1.Value.Version <=3D Element2.Value.Version) ? Pu= sh (TRUE, BooleanType) : Push (FALSE, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_PUSH_FAILURE; goto Error; } break; case EFI_FMP_DEP_END: Status =3D Pop (&Element1, BooleanType); if (EFI_ERROR (Status)) { + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERRO= R_POP_FAILURE; goto Error; } return Element1.Value.Boolean; default: DEBUG ((DEBUG_ERROR, "EvaluateDependency: Unknown Opcode - %02x!\n",= *Iterator)); + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_= UNKNOWN_OPCODE; goto Error; } Iterator++; } =20 DEBUG ((DEBUG_ERROR, "EvaluateDependency: No EFI_FMP_DEP_END Opcode in e= xpression!\n")); + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_E= ND_OPCODE; =20 Error: + if (LastAttemptStatus !=3D NULL) { + *LastAttemptStatus =3D LocalLastAttemptStatus; + } + return FALSE; } =20 /** Validate the dependency expression and output its size. =20 - @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP. - @param[in] MaxDepexSize Max size of the dependency. - @param[out] DepexSize Size of dependency. + @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP. + @param[in] MaxDepexSize Max size of the dependency. + @param[out] DepexSize Size of dependency. + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hol= ds the + last attempt status to report back to th= e caller. + If a last attempt status error code is n= ot returned, + this function will not modify the LastAt= temptStatus value. =20 @retval TRUE The dependency expression is valid. @retval FALSE The dependency expression is invalid. @@ -444,7 +497,8 @@ EFIAPI ValidateDependency ( IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, IN UINTN MaxDepexSize, - OUT UINT32 *DepexSize + OUT UINT32 *DepexSize, + OUT UINT32 *LastAttemptStatus OPTIONAL ) { UINT8 *Depex; @@ -493,16 +547,23 @@ ValidateDependency ( } } =20 + if (LastAttemptStatus !=3D NULL) { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END= _OPCODE; + } + return FALSE; } =20 /** Get dependency from firmware image. =20 - @param[in] Image Points to the firmware image. - @param[in] ImageSize Size, in bytes, of the firmware image. - @param[out] DepexSize Size, in bytes, of the dependency. - + @param[in] Image Points to the firmware image. + @param[in] ImageSize Size, in bytes, of the firmware image. + @param[out] DepexSize Size, in bytes, of the dependency. + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hol= ds the + last attempt status to report back to th= e caller. + If a last attempt status error code is n= ot returned, + this function will not modify the LastAt= temptStatus value. @retval The pointer to dependency. @retval Null =20 @@ -512,7 +573,8 @@ EFIAPI GetImageDependency ( IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image, IN UINTN ImageSize, - OUT UINT32 *DepexSize + OUT UINT32 *DepexSize, + OUT UINT32 *LastAttemptStatus OPTIONAL ) { EFI_FIRMWARE_IMAGE_DEP *Depex; @@ -530,6 +592,9 @@ GetImageDependency ( // // Pointer overflow. Invalid image. // + if (LastAttemptStatus !=3D NULL) { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GET_= DEPEX_FAILURE; + } return NULL; } =20 @@ -539,7 +604,7 @@ GetImageDependency ( // // Validate the dependency and get the size of dependency // - if (ValidateDependency (Depex, MaxDepexSize, DepexSize)) { + if (ValidateDependency (Depex, MaxDepexSize, DepexSize, LastAttemptStatu= s)) { return Depex; } =20 diff --git a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDe= pendencyUnitTest.c b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/Ev= aluateDependencyUnitTest.c index f8ccdd906f29..01ac19a7d5d7 100644 --- a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependenc= yUnitTest.c +++ b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependenc= yUnitTest.c @@ -2,6 +2,7 @@ Unit tests of EvaluateDependency API in FmpDependencyLib. =20 Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ @@ -162,6 +163,7 @@ EvaluateDependencyTest ( { BASIC_TEST_CONTEXT *TestContext; BOOLEAN EvaluationResult; + UINT32 LastAttemptStatus; =20 TestContext =3D (BASIC_TEST_CONTEXT *)Context; =20 @@ -169,8 +171,9 @@ EvaluateDependencyTest ( (EFI_FIRMWARE_IMAGE_DEP *)TestContext->Dependencies= , TestContext->DependenciesSize, mFmpVersions, - sizeof(mFmpVersions)/sizeof(FMP_DEPEX_CHECK_VERSION= _DATA) - ); + sizeof(mFmpVersions)/sizeof(FMP_DEPEX_CHECK_VERSION= _DATA), + &LastAttemptStatus + ); =20 UT_ASSERT_EQUAL (EvaluationResult, TestContext->ExpectedResult); =20 diff --git a/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h b/FmpDevi= cePkg/Include/Library/FmpDependencyCheckLib.h index ec380c4947bd..785bda9401e6 100644 --- a/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h +++ b/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h @@ -2,6 +2,7 @@ Fmp Capsule Dependency check functions for Firmware Management Protocol = based firmware updates. =20 + Copyright (c) Microsoft Corporation.
Copyright (c) 2020, Intel Corporation. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent @@ -21,6 +22,10 @@ @param[in] Version New version. @param[in] Dependencies Fmp dependency. @param[in] DependenciesSize Size, in bytes, of the Fmp dependency. + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hold= s the + last attempt status to report back to the= caller. + This function will set the value to LAST_= ATTEMPT_STATUS_SUCCESS + if an error code is not set. =20 @retval TRUE Dependencies are satisfied. @retval FALSE Dependencies are unsatisfied or dependency check fails. @@ -32,7 +37,8 @@ CheckFmpDependency ( IN EFI_GUID ImageTypeId, IN UINT32 Version, IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL - IN UINT32 DependenciesSize + IN UINT32 DependenciesSize, + OUT UINT32 *LastAttemptStatus OPTIONAL ); =20 #endif diff --git a/FmpDevicePkg/Include/Library/FmpDependencyLib.h b/FmpDevicePkg= /Include/Library/FmpDependencyLib.h index c732903425b4..f460f0f07882 100644 --- a/FmpDevicePkg/Include/Library/FmpDependencyLib.h +++ b/FmpDevicePkg/Include/Library/FmpDependencyLib.h @@ -26,9 +26,13 @@ typedef struct { /** Validate the dependency expression and output its size. =20 - @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP. - @param[in] MaxDepexSize Max size of the dependency. - @param[out] DepexSize Size of dependency. + @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP. + @param[in] MaxDepexSize Max size of the dependency. + @param[out] DepexSize Size of dependency. + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hol= ds the + last attempt status to report back to th= e caller. + If a last attempt status error code is n= ot returned, + this function will not modify the LastAt= temptStatus value. =20 @retval TRUE The dependency expression is valid. @retval FALSE The dependency expression is invalid. @@ -39,16 +43,20 @@ EFIAPI ValidateDependency ( IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, IN UINTN MaxDepexSize, - OUT UINT32 *DepexSize + OUT UINT32 *DepexSize, + OUT UINT32 *LastAttemptStatus OPTIONAL ); =20 /** Get dependency from firmware image. =20 - @param[in] Image Points to the firmware image. - @param[in] ImageSize Size, in bytes, of the firmware image. - @param[out] DepexSize Size, in bytes, of the dependency. - + @param[in] Image Points to the firmware image. + @param[in] ImageSize Size, in bytes, of the firmware image. + @param[out] DepexSize Size, in bytes, of the dependency. + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hol= ds the + last attempt status to report back to th= e caller. + If a last attempt status error code is n= ot returned, + this function will not modify the LastAt= temptStatus value. @retval The pointer to dependency. @retval Null =20 @@ -56,9 +64,10 @@ ValidateDependency ( EFI_FIRMWARE_IMAGE_DEP* EFIAPI GetImageDependency ( - IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image, - IN UINTN ImageSize, - OUT UINT32 *DepexSize + IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image, + IN UINTN ImageSize, + OUT UINT32 *DepexSize, + OUT UINT32 *LastAttemptStatus OPTIONAL ); =20 /** @@ -73,6 +82,10 @@ GetImageDependency ( parameter is optional and can be set to = NULL. @param[in] FmpVersionsCount Element count of the array. When FmpVers= ions is NULL, FmpVersionsCount must be 0. + @param[out] LastAttemptStatus An optional pointer to a UINT32 that hol= ds the + last attempt status to report back to th= e caller. + This function will set the value to LAST= _ATTEMPT_STATUS_SUCCESS + if an error code is not set. =20 @retval TRUE Dependency expressions evaluate to TRUE. @retval FALSE Dependency expressions evaluate to FALSE. @@ -81,10 +94,11 @@ GetImageDependency ( BOOLEAN EFIAPI EvaluateDependency ( - IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, - IN UINTN DependenciesSize, - IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL, - IN UINTN FmpVersionsCount + IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, + IN UINTN DependenciesSize, + IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions, OPTIONAL + IN UINTN FmpVersionsCount, + OUT UINT32 *LastAttemptStatus OPTIONAL ); =20 #endif --=20 2.28.0.windows.1