From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM04-DM6-obe.outbound.protection.outlook.com (NAM04-DM6-obe.outbound.protection.outlook.com [40.92.45.19]) by mx.groups.io with SMTP id smtpd.web12.495.1602796329907079406 for ; Thu, 15 Oct 2020 14:12:10 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@outlook.com header.s=selector1 header.b=U3/PHAGE; spf=pass (domain: outlook.com, ip: 40.92.45.19, mailfrom: michael.kubacki@outlook.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=I8j55Y2ZRSIwUMpgUsNpWqxofgYTnDZyPGg2n5rq6uSe+O2mLRNu7Eyek/M0aBhM8bsR19QZENvoiJC3XuYRTiJOr0E4UjTUNvgsq8ltdbshFvSeP9T48xzRsIprCyrVIDJE6DMNtioxt4N/RhmL3UBG7s8ZoVmxcv9Cm0uPfTI2qmgrKojs1GUhUkl9u0uZPy238A2NV5pKor4pL/iWeYrTGgBMhsR4Nl4tirBp2oKS+r3IK1JBFN4ImWZy+PNjjHHgnDg9YfkGzsIgfJxWq0S9WTCYWixv4ErSBJFv420vq4sokPqSBh5OkeAaN0BNlntvl50AwDRcvLNl6SWXIw== 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=HEO0msK4s3t9qwTqb5akoDIahdQNtzXbFj17Pk75uF0=; b=J2n13DcsrCB9RdKlhRuDnn7qFtflN6i1G8CIh6HuOH0x/Xuh3FUF7f6hHF+xaWoWbCnmoRK+l1vqzFx0n6HZVaRiufINbwnQ8aWpGw6uZJELMFiX4w3TXG3vTqBDZ1okWxRoLwzyIbkMcjHyXV4BFoaw0k60j6wwMVmxNFALIr5OaY8Y1FfaRlPlboBHoHyTA3yPqhCc7csZwjINCuyiegrF5171JgN1pXFmUeUcbX/Old7Gvzo1IQF99vIC6KdAl3ciK7FRhHtquet+zQSW0YgYVNakkvE4YFk6RA6ydMtrvdGpXFFkNdPXcFi/lu4uA2eo+sUTlEUApk/+OGT4Xg== 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=HEO0msK4s3t9qwTqb5akoDIahdQNtzXbFj17Pk75uF0=; b=U3/PHAGE2TDfukNLIYztpDvRz/ZdBxqMjReu2T74FWvyH3sZiIGMQ9FBJCXzKNLuhdBA6Q+FOfXEIJF2B9Y7ncI+tzGm6ODUu6rPT6y4H3fAPD9yeUm9N1JyJBF8gD5Upp/9Hrw3d3HRnErfqy0mP74ekYstBQbSDTlVeZUBUh92bAOGz47fpQ3AGeJjIsfkANFHRPWM0z9OBohx1Rt4DVcle6x0C0Ya/9orcLiFWSRoqePJ2nABG4qzZjB33WZ/W8qbQ0pIP9Z6H/2aae6T/U7QX9LZRrIJXEBVoBbz/MbLDTRVUf82VxTFh7Dsa5ldYxPg80X2VuBsZhvqpbw6vA== Received: from DM6NAM04FT027.eop-NAM04.prod.protection.outlook.com (2a01:111:e400:7ea3::43) by DM6NAM04HT201.eop-NAM04.prod.protection.outlook.com (2a01:111:e400:7ea3::112) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3455.27; Thu, 15 Oct 2020 21:12:08 +0000 Received: from MWHPR07MB3440.namprd07.prod.outlook.com (2a01:111:e400:7ea3::53) by DM6NAM04FT027.mail.protection.outlook.com (2a01:111:e400:7ea3::334) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3455.27 via Frontend Transport; Thu, 15 Oct 2020 21:12:08 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:B5310A73BB160D89700F036C0C34398DC0F385B54E27FB909B5FBB4FF1E6C9FD;UpperCasedChecksum:F3D73F778BF37F0BF71DF7877C10CA04E1A2D13659D103EFAD85AEC35B6190CD;SizeAsReceived:7688;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.3455.031; Thu, 15 Oct 2020 21:12:08 +0000 From: "Michael Kubacki" To: devel@edk2.groups.io CC: Liming Gao , Michael D Kinney , Guomin Jiang , Wei6 Xu Subject: [PATCH v5 3/6] FmpDevicePkg/FmpDxe: Add check image path Last Attempt Status capability Date: Thu, 15 Oct 2020 14:11:18 -0700 Message-ID: X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20201015211121.1927-1-michael.kubacki@outlook.com> References: <20201015211121.1927-1-michael.kubacki@outlook.com> X-TMN: [U39LB0ijfZm8fm4Ro6J3WFF4dGLbk9TbJBT9FGF4ErsaDMHR5+QHwHAEn9ZLaQ+D] X-ClientProxiedBy: MWHPR22CA0029.namprd22.prod.outlook.com (2603:10b6:300:69::15) To MWHPR07MB3440.namprd07.prod.outlook.com (2603:10b6:301:69::28) Return-Path: michael.kubacki@outlook.com X-Microsoft-Original-Message-ID: <20201015211121.1927-4-michael.kubacki@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (2001:4898:80e8:8:d168:ab8a:5f17:7fc6) by MWHPR22CA0029.namprd22.prod.outlook.com (2603:10b6:300:69::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3477.20 via Frontend Transport; Thu, 15 Oct 2020 21:12:08 +0000 X-MS-PublicTrafficType: Email X-IncomingHeaderCount: 47 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-Correlation-Id: 9d06d46b-bf3f-44bf-2b72-08d8714ef9d6 X-MS-TrafficTypeDiagnostic: DM6NAM04HT201: X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: dejC7J2VpqU+fK3t9RvYAMwwkdsIMLedvmtqUYv4/qkDv+E3V80wmhwD8man55BE0KktH4iehQOKqIynAFGnOG/er4TZTBcXiUjJQZjBF9gKzhTJZe01S2s2SgRuh95PTOTtXkLM506fX2eu+WCBc3BLcW79cust0DIQzVox9MNxjOQUlEAf8yB+jnfc4+cUxo89kdy1WB1H1xolyt3MNQ== X-MS-Exchange-AntiSpam-MessageData: cM0uSmyvn2JDHBTWruAh6kgk3ExlD6CnIrAj79ikJGZ5665exP3nQ1bhYYi8h/AF7QioZz9ARbQpdfufZyiJPmnveT6Nonnb2PX0GX8cL/Wj0J+PbGUGQs2nIo9VRVjUf3GGcsVlPmpD06prAWGP57X+6sT5rKlfKLIu2U5XwQo4VrcIXwZ+UoMl7hO2qK3T/NOGd39DF2cYe6grOT2yNQ== X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 9d06d46b-bf3f-44bf-2b72-08d8714ef9d6 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2020 21:12:08.8214 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-AuthSource: DM6NAM04FT027.eop-NAM04.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: DM6NAM04HT201 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Michael Kubacki CheckTheImage() is currently used to provide the CheckImage() implementation for the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance produced by FmpDxe in addition to being called internally in the SetImage() path. Since CheckTheImage() plays a major role in determining the validity of a given firmware image, an internal version of the function is introduced - CheckTheImageInternal() that is capable of returning a Last Attempt Status code to internal callers such as SetTheImage(). The CheckImage() API as defined in the UEFI Specification for EFI_FIRMWARE_MANAGEMENT_PROTOCOL is not impacted by this change. CheckTheImageInternal() contains unique Last Attempt Status codes during error paths in the function so it is easier to identify the issue with a particular image through the Last Attempt Status code value. Cc: Liming Gao Cc: Michael D Kinney Cc: Guomin Jiang Cc: Wei6 Xu Signed-off-by: Michael Kubacki --- FmpDevicePkg/FmpDxe/FmpDxe.c | 98 +++++++++++++++++--- FmpDevicePkg/FmpDxe/FmpDxe.h | 4 +- 2 files changed, 90 insertions(+), 12 deletions(-) diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c index 427b215ddc5f..bc11faa2bfaa 100644 --- a/FmpDevicePkg/FmpDxe/FmpDxe.c +++ b/FmpDevicePkg/FmpDxe/FmpDxe.c @@ -721,6 +721,14 @@ GetAllHeaderSize ( @param[in] ImageSize Size of the new image in bytes. @param[out] ImageUpdatable Indicates if the new image is valid for u= pdate. It also provides, if available, additional information if t= he image is invalid. + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last= attempt status to report + back to the ESRT table in case of error. = If an error does not occur, + this function will set the value to LAST_= ATTEMPT_STATUS_SUCCESS. + + This function will return error codes tha= t occur within this function + implementation within a driver range of l= ast attempt error codes from + LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE= _VALUE + to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_C= ODE_VALUE. =20 @retval EFI_SUCCESS The image was successfully checked. @retval EFI_ABORTED The operation is aborted. @@ -731,15 +739,17 @@ GetAllHeaderSize ( **/ EFI_STATUS EFIAPI -CheckTheImage ( +CheckTheImageInternal ( IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, IN UINT8 ImageIndex, IN CONST VOID *Image, IN UINTN ImageSize, - OUT UINT32 *ImageUpdatable + OUT UINT32 *ImageUpdatable, + OUT UINT32 *LastAttemptStatus ) { EFI_STATUS Status; + UINT32 LocalLastAttemptStatus; FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private; UINTN RawSize; VOID *FmpPayloadHeader; @@ -755,23 +765,37 @@ CheckTheImage ( EFI_FIRMWARE_IMAGE_DEP *Dependencies; UINT32 DependenciesSize; =20 - Status =3D EFI_SUCCESS; - RawSize =3D 0; - FmpPayloadHeader =3D NULL; - FmpPayloadSize =3D 0; - Version =3D 0; - FmpHeaderSize =3D 0; - AllHeaderSize =3D 0; - Dependencies =3D NULL; - DependenciesSize =3D 0; + Status =3D EFI_SUCCESS; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; + RawSize =3D 0; + FmpPayloadHeader =3D NULL; + FmpPayloadSize =3D 0; + Version =3D 0; + FmpHeaderSize =3D 0; + AllHeaderSize =3D 0; + Dependencies =3D NULL; + DependenciesSize =3D 0; =20 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) { return EFI_UNSUPPORTED; } =20 + if (LastAttemptStatus =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImageInternal() - LastAttemp= tStatus is NULL.\n", mImageIdName)); + Status =3D EFI_INVALID_PARAMETER; + goto cleanup; + } + + // + // A last attempt status error code will always override the success + // value before returning from the function + // + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; + if (This =3D=3D NULL) { DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - This is NULL.\n", mIm= ageIdName)); Status =3D EFI_INVALID_PARAMETER; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_M= ISSING; goto cleanup; } =20 @@ -789,6 +813,7 @@ CheckTheImage ( if (ImageUpdatable =3D=3D NULL) { DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointe= r Parameter is NULL.\n", mImageIdName)); Status =3D EFI_INVALID_PARAMETER; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDA= TABLE; goto cleanup; } =20 @@ -808,6 +833,7 @@ CheckTheImage ( // not sure if this is needed // *ImageUpdatable =3D IMAGE_UPDATABLE_INVALID; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROV= IDED; return EFI_INVALID_PARAMETER; } =20 @@ -817,6 +843,7 @@ CheckTheImage ( if (PublicKeyDataXdr =3D=3D NULL || (PublicKeyDataXdr =3D=3D PublicKeyDa= taXdrEnd)) { DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n"= , mImageIdName)); Status =3D EFI_ABORTED; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CE= RTIFICATE; } else { // // Try each key from PcdFmpDevicePkcs7CertBufferXdr @@ -839,6 +866,7 @@ CheckTheImage ( // DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond = end of PCD, skipping it.\n", mImageIdName)); Status =3D EFI_ABORTED; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALI= D_KEY_LENGTH_VALUE; break; } // @@ -855,6 +883,7 @@ CheckTheImage ( // DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end o= f PCD, skipping it.\n", mImageIdName)); Status =3D EFI_ABORTED; + LocalLastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALI= D_KEY_LENGTH; break; } PublicKeyData =3D PublicKeyDataXdr; @@ -874,6 +903,11 @@ CheckTheImage ( =20 if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Fai= led %r.\n", mImageIdName, Status)); + if (LocalLastAttemptStatus !=3D LAST_ATTEMPT_STATUS_SUCCESS) { + *LastAttemptStatus =3D LocalLastAttemptStatus; + } else { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_F= AILURE; + } goto cleanup; } =20 @@ -884,6 +918,7 @@ CheckTheImage ( DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\= n", mImageIdName)); *ImageUpdatable =3D IMAGE_UPDATABLE_INVALID_TYPE; Status =3D EFI_INVALID_PARAMETER; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_= INDEX; goto cleanup; } =20 @@ -899,6 +934,7 @@ CheckTheImage ( if (FmpPayloadHeader =3D=3D NULL) { DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader faile= d.\n", mImageIdName)); Status =3D EFI_ABORTED; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER= ; goto cleanup; } Status =3D GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize,= &Version); @@ -906,6 +942,7 @@ CheckTheImage ( DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeade= rVersion failed %r.\n", mImageIdName, Status)); *ImageUpdatable =3D IMAGE_UPDATABLE_INVALID; Status =3D EFI_SUCCESS; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER= _VERSION; goto cleanup; } =20 @@ -920,6 +957,7 @@ CheckTheImage ( ); *ImageUpdatable =3D IMAGE_UPDATABLE_INVALID_OLD; Status =3D EFI_SUCCESS; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LO= W; goto cleanup; } =20 @@ -942,6 +980,7 @@ CheckTheImage ( DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSiz= e failed %r.\n", Status)); *ImageUpdatable =3D IMAGE_UPDATABLE_INVALID; Status =3D EFI_SUCCESS; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER= _SIZE; goto cleanup; } =20 @@ -953,6 +992,7 @@ CheckTheImage ( if (AllHeaderSize =3D=3D 0) { DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize f= ailed.\n", mImageIdName)); Status =3D EFI_ABORTED; + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER= _SIZE; goto cleanup; } RawSize =3D ImageSize - AllHeaderSize; @@ -969,6 +1009,42 @@ CheckTheImage ( return Status; } =20 +/** + Checks if the firmware image is valid for the device. + + This function allows firmware update application to validate the firmwar= e image without + invoking the SetImage() first. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware = image(s) within the device. + The number is between 1 and DescriptorCou= nt. + @param[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[out] ImageUpdatable Indicates if the new image is valid for u= pdate. It also provides, + if available, additional information if t= he image is invalid. + + @retval EFI_SUCCESS The image was successfully checked. + @retval EFI_ABORTED The operation is aborted. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +CheckTheImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable + ) +{ + UINT32 LastAttemptStatus; + + return CheckTheImageInternal (This, ImageIndex, Image, ImageSize, ImageU= pdatable, &LastAttemptStatus); +} + /** Updates the firmware image of the device. =20 diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.h b/FmpDevicePkg/FmpDxe/FmpDxe.h index 30754dea495e..1177b1828e9a 100644 --- a/FmpDevicePkg/FmpDxe/FmpDxe.h +++ b/FmpDevicePkg/FmpDxe/FmpDxe.h @@ -3,7 +3,7 @@ image stored in a firmware device with platform and firmware device spec= ific information provided through PCDs and libraries. =20 - Copyright (c) 2016, Microsoft Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation.
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent @@ -36,6 +36,8 @@ #include #include #include +#include +#include =20 #define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED" #define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE" --=20 2.28.0.windows.1