* [PATCH v6 1/6] MdePkg/SystemResourceTable.h: Add vendor range values
[not found] <20201019235939.2320-1-michael.kubacki@outlook.com>
@ 2020-10-19 23:59 ` Michael Kubacki
2020-10-19 23:59 ` [PATCH v6 2/6] FmpDevicePkg: Add Last Attempt Status header files Michael Kubacki
` (4 subsequent siblings)
5 siblings, 0 replies; 6+ messages in thread
From: Michael Kubacki @ 2020-10-19 23:59 UTC (permalink / raw)
To: devel; +Cc: Liming Gao, Michael D Kinney, Guomin Jiang, Wei6 Xu, Zhiguang Liu
From: Michael Kubacki <michael.kubacki@microsoft.com>
Adds the following macros to define the unsuccessful vendor range
min and max (defined in UEFI Specification 2.8):
1. LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MIN
2. LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Wei6 Xu <wei6.xu@intel.com>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
Reviewed-by: Wei6 Xu <wei6.xu@intel.com>
---
MdePkg/Include/Guid/SystemResourceTable.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/MdePkg/Include/Guid/SystemResourceTable.h b/MdePkg/Include/Guid/SystemResourceTable.h
index 418b8c8d055a..c330fd80a693 100644
--- a/MdePkg/Include/Guid/SystemResourceTable.h
+++ b/MdePkg/Include/Guid/SystemResourceTable.h
@@ -2,6 +2,7 @@
Guid & data structure used for EFI System Resource Table (ESRT)
Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
@@ -44,6 +45,18 @@
#define LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT 0x00000007
#define LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES 0x00000008
+///
+/// LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX is defined as
+/// 0x4000 as of UEFI Specification 2.8B. This will be modified in the
+/// future to the correct value 0x3FFF. To ensure correct implementation,
+/// this change is preemptively made in the value defined below.
+///
+/// When the UEFI Specification is updated, this comment block can be
+/// removed.
+///
+#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MIN 0x00001000
+#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX 0x00003FFF
+
typedef struct {
///
/// The firmware class field contains a GUID that identifies a firmware component
--
2.28.0.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 2/6] FmpDevicePkg: Add Last Attempt Status header files
[not found] <20201019235939.2320-1-michael.kubacki@outlook.com>
2020-10-19 23:59 ` [PATCH v6 1/6] MdePkg/SystemResourceTable.h: Add vendor range values Michael Kubacki
@ 2020-10-19 23:59 ` Michael Kubacki
2020-10-19 23:59 ` [PATCH v6 3/6] FmpDevicePkg/FmpDxe: Add check image path Last Attempt Status capability Michael Kubacki
` (3 subsequent siblings)
5 siblings, 0 replies; 6+ messages in thread
From: Michael Kubacki @ 2020-10-19 23:59 UTC (permalink / raw)
To: devel; +Cc: Liming Gao, Michael D Kinney, Guomin Jiang, Wei6 Xu
From: Michael Kubacki <michael.kubacki@microsoft.com>
Introduces a public and a private header file to define more
granular usage of the UEFI Specification defined unsuccessful
vendor range for Last Attempt Status codes. The unsuccessful
vendor range is described in UEFI Specification 2.8A section 23.4.
The public header file Include/LastAttemptStatus.h defines ranges
within the unsuccessful vendor range. At a high-level, the two
main ranges are defined are the FMP Reserved range and the Device
Library Reserved range.
The FMP Reserved range is reserved for usage of components within
FmpDevicePkg. PrivateInclude/FmpLastAttemptStatus.h contains
usage details and specific Last Attempt Status code definitions.
The Device Library Reserved range is reserved for usage by
FmpDeviceLib instances. Each library may define custom Last
Attempt Status codes within the bounds defined in
Include/LastAttemptStatus.h:
[LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE,
LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Wei6 Xu <wei6.xu@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
Reviewed-by: Wei6 Xu <wei6.xu@intel.com>
---
FmpDevicePkg/Include/LastAttemptStatus.h | 81 ++++++++++++++++++++
FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h | 81 ++++++++++++++++++++
2 files changed, 162 insertions(+)
diff --git a/FmpDevicePkg/Include/LastAttemptStatus.h b/FmpDevicePkg/Include/LastAttemptStatus.h
new file mode 100644
index 000000000000..0dcd1ef71621
--- /dev/null
+++ b/FmpDevicePkg/Include/LastAttemptStatus.h
@@ -0,0 +1,81 @@
+/** @file
+ Defines last attempt status code ranges within the UEFI Specification
+ defined unsuccessful vendor range.
+
+ Copyright (c) Microsoft Corporation.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __LAST_ATTEMPT_STATUS_H__
+#define __LAST_ATTEMPT_STATUS_H__
+
+///
+/// Last Attempt Status Unsuccessful Vendor Range Map
+///
+/// Update this map any time new ranges are added. Pre-existing range definitions cannot be modified
+/// to keep status code definitions consistent over time.
+///
+/// START | END | Usage
+/// ------------------------------------------------------------------|
+/// 0x1000 | 0x17FF | FmpDevicePkg |
+/// 0x1000 | 0x107F | FmpDxe driver |
+/// 0x1080 | 0x109F | FmpDependencyLib |
+/// 0x10A0 | 0x10BF | FmpDependencyCheckLib |
+/// 0x10C0 | 0x17FF | Unused. Available for future expansion. |
+/// 0x1800 | 0x1FFF | FmpDeviceLib instances implementation |
+/// 0x2000 | 0x3FFF | Unused. Available for future expansion. |
+///
+
+///
+/// The minimum value of the FMP reserved range.
+///
+#define LAST_ATTEMPT_STATUS_FMP_RESERVED_MIN_ERROR_CODE_VALUE 0x1000
+
+///
+/// The maximum value of the FMP reserved range.
+///
+#define LAST_ATTEMPT_STATUS_FMP_RESERVED_MAX_ERROR_CODE_VALUE 0x1FFF
+
+///
+/// The minimum value allowed for FmpDxe driver-specific errors.
+///
+#define LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE 0x1000
+
+///
+/// The maximum value allowed for FmpDxe driver-specific errors.
+///
+#define LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE 0x107F
+
+///
+/// The minimum value allowed for FmpDependencyLib related errors.
+///
+#define LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE 0x1080
+
+///
+/// The maximum value allowed for FmpDependencyLib related errors.
+///
+#define LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MAX_ERROR_CODE_VALUE 0x109F
+
+///
+/// The minimum value allowed for FmpDependencyCheckLib related errors.
+///
+#define LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE 0x10A0
+
+///
+/// The maximum value allowed for FmpDependencyCheckLib related errors.
+///
+#define LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MAX_ERROR_CODE_VALUE 0x10BF
+
+///
+/// The minimum value allowed for FMP device library errors.
+///
+#define LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE 0x1800
+
+///
+/// The maximum value allowed for FMP device library errors.
+///
+#define LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE 0x1FFF
+
+#endif
diff --git a/FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h b/FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h
new file mode 100644
index 000000000000..de865a2e3d26
--- /dev/null
+++ b/FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h
@@ -0,0 +1,81 @@
+/** @file
+ Defines private last attempt status codes used in FmpDevicePkg.
+
+ Copyright (c) Microsoft Corporation.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __FMP_LAST_ATTEMPT_STATUS_H__
+#define __FMP_LAST_ATTEMPT_STATUS_H__
+
+///
+/// Last attempt status codes defined for additional granularity in FmpDevicePkg components.
+///
+/// These codes are defined within the last attempt status FMP reserved range which extends from
+/// LAST_ATTEMPT_STATUS_FMP_RESERVED_MIN_ERROR_CODE_VALUE to LAST_ATTEMPT_STATUS_FMP_RESERVED_MAX_ERROR_CODE_VALUE.
+///
+/// The following last attempt status code ranges are currently defined for the corresponding component:
+/// * LAST_ATTEMPT_STATUS_DRIVER - FMP driver
+/// * LAST_ATTEMPT_STATUS_DEPENDENCY - FMP dependency functionality
+///
+/// Future last attempt status code additions in FmpDevicePkg should be added as follows:
+/// * FmpDxe driver: Onto the end of the LAST_ATTEMPT_STATUS_DRIVER_ERROR range
+/// * FMP dependency functionality: Onto the end of the LAST_ATTEMPT_STATUS_DEPENDENCY_ERROR range
+/// * Other components: Add a new range onto the end of the last existing range in the enum within the limits of
+/// [LAST_ATTEMPT_STATUS_FMP_RESERVED_MIN_ERROR_CODE_VALUE,LAST_ATTEMPT_STATUS_FMP_RESERVED_MAX_ERROR_CODE_VALUE]
+///
+/// The value of pre-existing last attempt status codes should never be modified to ensure the values remain
+/// consistent over time.
+///
+enum LAST_ATTEMPT_STATUS_EXPANDED_ERROR_LIST
+{
+ ///
+ /// Last attempt status codes used in FmpDxe
+ ///
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER = LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING ,
+
+ ///
+ /// Last attempt status codes used in FmpDependencyLib
+ ///
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GET_DEPEX_FAILURE = LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_UNKNOWN_OPCODE ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GUID_BEYOND_DEPEX ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_BEYOND_DEPEX ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_STR_BEYOND_DEPEX ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_FMP_NOT_FOUND ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE ,
+
+ ///
+ /// Last attempt status codes used in FmpDependencyCheckLib
+ ///
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_FMP_PROTOCOL_NOT_FOUND = LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_INFO_BUFFER_FAILED ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_VER_BUFFER_FAILED ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_SIZE_BUFFER_FAILED ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_VER_BUFFER_FAILED
+};
+
+#endif
--
2.28.0.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 3/6] FmpDevicePkg/FmpDxe: Add check image path Last Attempt Status capability
[not found] <20201019235939.2320-1-michael.kubacki@outlook.com>
2020-10-19 23:59 ` [PATCH v6 1/6] MdePkg/SystemResourceTable.h: Add vendor range values Michael Kubacki
2020-10-19 23:59 ` [PATCH v6 2/6] FmpDevicePkg: Add Last Attempt Status header files Michael Kubacki
@ 2020-10-19 23:59 ` Michael Kubacki
2020-10-19 23:59 ` [PATCH v6 4/6] FmpDevicePkg/FmpDxe: Improve set image path Last Attempt Status granularity Michael Kubacki
` (2 subsequent siblings)
5 siblings, 0 replies; 6+ messages in thread
From: Michael Kubacki @ 2020-10-19 23:59 UTC (permalink / raw)
To: devel; +Cc: Liming Gao, Michael D Kinney, Guomin Jiang, Wei6 Xu
From: Michael Kubacki <michael.kubacki@microsoft.com>
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 <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Wei6 Xu <wei6.xu@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
Reviewed-by: Wei6 Xu <wei6.xu@intel.com>
---
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 update. It also provides,
if available, additional information if the 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 that occur within this function
+ implementation within a driver range of last attempt error codes from
+ LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE
+ to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE.
@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;
- Status = EFI_SUCCESS;
- RawSize = 0;
- FmpPayloadHeader = NULL;
- FmpPayloadSize = 0;
- Version = 0;
- FmpHeaderSize = 0;
- AllHeaderSize = 0;
- Dependencies = NULL;
- DependenciesSize = 0;
+ Status = EFI_SUCCESS;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ RawSize = 0;
+ FmpPayloadHeader = NULL;
+ FmpPayloadSize = 0;
+ Version = 0;
+ FmpHeaderSize = 0;
+ AllHeaderSize = 0;
+ Dependencies = NULL;
+ DependenciesSize = 0;
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
return EFI_UNSUPPORTED;
}
+ if (LastAttemptStatus == NULL) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImageInternal() - LastAttemptStatus is NULL.\n", mImageIdName));
+ Status = EFI_INVALID_PARAMETER;
+ goto cleanup;
+ }
+
+ //
+ // A last attempt status error code will always override the success
+ // value before returning from the function
+ //
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
if (This == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - This is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;
goto cleanup;
}
@@ -789,6 +813,7 @@ CheckTheImage (
if (ImageUpdatable == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE;
goto cleanup;
}
@@ -808,6 +833,7 @@ CheckTheImage (
// not sure if this is needed
//
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED;
return EFI_INVALID_PARAMETER;
}
@@ -817,6 +843,7 @@ CheckTheImage (
if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));
Status = EFI_ABORTED;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE;
} 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 = EFI_ABORTED;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE;
break;
}
//
@@ -855,6 +883,7 @@ CheckTheImage (
//
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));
Status = EFI_ABORTED;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH;
break;
}
PublicKeyData = PublicKeyDataXdr;
@@ -874,6 +903,11 @@ CheckTheImage (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));
+ if (LocalLastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
+ *LastAttemptStatus = LocalLastAttemptStatus;
+ } else {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE;
+ }
goto cleanup;
}
@@ -884,6 +918,7 @@ CheckTheImage (
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;
Status = EFI_INVALID_PARAMETER;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX;
goto cleanup;
}
@@ -899,6 +934,7 @@ CheckTheImage (
if (FmpPayloadHeader == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
Status = EFI_ABORTED;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;
goto cleanup;
}
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
@@ -906,6 +942,7 @@ CheckTheImage (
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
Status = EFI_SUCCESS;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION;
goto cleanup;
}
@@ -920,6 +957,7 @@ CheckTheImage (
);
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;
Status = EFI_SUCCESS;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW;
goto cleanup;
}
@@ -942,6 +980,7 @@ CheckTheImage (
DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
Status = EFI_SUCCESS;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;
goto cleanup;
}
@@ -953,6 +992,7 @@ CheckTheImage (
if (AllHeaderSize == 0) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
Status = EFI_ABORTED;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;
goto cleanup;
}
RawSize = ImageSize - AllHeaderSize;
@@ -969,6 +1009,42 @@ CheckTheImage (
return Status;
}
+/**
+ Checks if the firmware image is valid for the device.
+
+ This function allows firmware update application to validate the firmware 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 DescriptorCount.
+ @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 update. It also provides,
+ if available, additional information if the 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, ImageUpdatable, &LastAttemptStatus);
+}
+
/**
Updates the firmware image of the device.
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 specific
information provided through PCDs and libraries.
- Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -36,6 +36,8 @@
#include <Protocol/VariableLock.h>
#include <Guid/SystemResourceTable.h>
#include <Guid/EventGroup.h>
+#include <LastAttemptStatus.h>
+#include <FmpLastAttemptStatus.h>
#define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED"
#define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE"
--
2.28.0.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 4/6] FmpDevicePkg/FmpDxe: Improve set image path Last Attempt Status granularity
[not found] <20201019235939.2320-1-michael.kubacki@outlook.com>
` (2 preceding siblings ...)
2020-10-19 23:59 ` [PATCH v6 3/6] FmpDevicePkg/FmpDxe: Add check image path Last Attempt Status capability Michael Kubacki
@ 2020-10-19 23:59 ` Michael Kubacki
2020-10-19 23:59 ` [PATCH v6 5/6] FmpDevicePkg: Add Last Attempt Status support to dependency libs Michael Kubacki
2020-10-19 23:59 ` [PATCH v6 6/6] FmpDevicePkg/FmpDeviceLib: Add Last Attempt Status to Check/Set API Michael Kubacki
5 siblings, 0 replies; 6+ messages in thread
From: Michael Kubacki @ 2020-10-19 23:59 UTC (permalink / raw)
To: devel; +Cc: Liming Gao, Michael D Kinney, Guomin Jiang, Wei6 Xu
From: Michael Kubacki <michael.kubacki@microsoft.com>
Increases the level of granularity for Last Attempt Status codes
returned from SetTheImage() in FmpDxe. This allows better
identification of the error that occurred in the set image
operation using Last Attempt Status codes.
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Wei6 Xu <wei6.xu@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
Reviewed-by: Wei6 Xu <wei6.xu@intel.com>
---
FmpDevicePkg/FmpDxe/FmpDxe.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c
index bc11faa2bfaa..b7fd9c93aea0 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.c
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.c
@@ -1138,6 +1138,7 @@ SetTheImage (
if (This == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - This is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;
goto cleanup;
}
@@ -1163,6 +1164,7 @@ SetTheImage (
//
if (Private->FmpDeviceLocked) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED;
Status = EFI_UNSUPPORTED;
goto cleanup;
}
@@ -1170,12 +1172,9 @@ SetTheImage (
//
// Call check image to verify the image
//
- Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable);
+ Status = CheckTheImageInternal (This, ImageIndex, Image, ImageSize, &Updateable, &LastAttemptStatus);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));
- if (Status == EFI_SECURITY_VIOLATION) {
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
- }
goto cleanup;
}
@@ -1191,6 +1190,7 @@ SetTheImage (
FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );
if (FmpHeader == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;
Status = EFI_ABORTED;
goto cleanup;
}
@@ -1218,6 +1218,7 @@ SetTheImage (
if (Progress == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR;
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
@@ -1238,6 +1239,7 @@ SetTheImage (
Status = CheckSystemPower (&BooleanValue);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API;
goto cleanup;
}
if (!BooleanValue) {
@@ -1258,10 +1260,12 @@ SetTheImage (
Status = CheckSystemThermal (&BooleanValue);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API;
goto cleanup;
}
if (!BooleanValue) {
Status = EFI_ABORTED;
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL;
DEBUG (
(DEBUG_ERROR,
"FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)
@@ -1277,10 +1281,12 @@ SetTheImage (
Status = CheckSystemEnvironment (&BooleanValue);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API;
goto cleanup;
}
if (!BooleanValue) {
Status = EFI_ABORTED;
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV;
DEBUG (
(DEBUG_ERROR,
"FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)
@@ -1302,12 +1308,14 @@ SetTheImage (
Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;
goto cleanup;
}
AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
if (AllHeaderSize == 0) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;
Status = EFI_ABORTED;
goto cleanup;
}
@@ -1372,6 +1380,7 @@ SetTheImage (
mProgressFunc = NULL;
if (Private != NULL) {
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName, LastAttemptStatus));
SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
}
--
2.28.0.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 5/6] FmpDevicePkg: Add Last Attempt Status support to dependency libs
[not found] <20201019235939.2320-1-michael.kubacki@outlook.com>
` (3 preceding siblings ...)
2020-10-19 23:59 ` [PATCH v6 4/6] FmpDevicePkg/FmpDxe: Improve set image path Last Attempt Status granularity Michael Kubacki
@ 2020-10-19 23:59 ` Michael Kubacki
2020-10-19 23:59 ` [PATCH v6 6/6] FmpDevicePkg/FmpDeviceLib: Add Last Attempt Status to Check/Set API Michael Kubacki
5 siblings, 0 replies; 6+ messages in thread
From: Michael Kubacki @ 2020-10-19 23:59 UTC (permalink / raw)
To: devel; +Cc: Liming Gao, Michael D Kinney, Guomin Jiang, Wei6 Xu
From: Michael Kubacki <michael.kubacki@microsoft.com>
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 <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Wei6 Xu <wei6.xu@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
Reviewed-by: Wei6 Xu <wei6.xu@intel.com>
---
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/EvaluateDependencyUnitTest.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_CODE_VALUE.
+ This function might also return error codes that occur within libraries
+ linked against this module that return last attempt error codes such as:
+
+ LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MAX_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 = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
+ Dependencies = GetImageDependency (
+ (EFI_FIRMWARE_IMAGE_AUTHENTICATION *) Image,
+ ImageSize,
+ &DependenciesSize,
+ LastAttemptStatus
+ );
+ if (*LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
+ Status = EFI_ABORTED;
+ goto cleanup;
+ }
//
// Check the FmpPayloadHeader
@@ -964,11 +982,18 @@ CheckTheImageInternal (
//
// Evaluate dependency expression
//
- Private->DependenciesSatisfied = CheckFmpDependency (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize);
+ Private->DependenciesSatisfied = CheckFmpDependency (
+ Private->Descriptor.ImageTypeId,
+ Version,
+ Dependencies,
+ DependenciesSize,
+ &LocalLastAttemptStatus
+ );
if (!Private->DependenciesSatisfied) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
Status = EFI_SUCCESS;
+ *LastAttemptStatus = LocalLastAttemptStatus;
goto cleanup;
}
@@ -1181,7 +1206,7 @@ SetTheImage (
//
// Get the dependency from Image.
//
- Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
+ Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize, &LastAttemptStatus);
//
// No functional error in CheckTheImage. Attempt to get the Version to
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.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 <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Guid/SystemResourceTable.h>
+#include <LastAttemptStatus.h>
+#include <FmpLastAttemptStatus.h>
/**
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 holds 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.
@@ -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;
- FmpImageInfoBuf = NULL;
- DescriptorVer = NULL;
- DescriptorSize = NULL;
- NumberOfFmpInstance = 0;
- FmpVersions = NULL;
- FmpVersionsCount = 0;
- IsSatisfied = TRUE;
- PackageVersionName = NULL;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ FmpImageInfoBuf = NULL;
+ DescriptorVer = NULL;
+ DescriptorSize = NULL;
+ NumberOfFmpInstance = 0;
+ FmpVersions = NULL;
+ FmpVersionsCount = 0;
+ IsSatisfied = TRUE;
+ PackageVersionName = NULL;
//
// Get ImageDescriptors of all FMP instances, and archive them for dependency evaluation.
@@ -77,30 +87,35 @@ CheckFmpDependency (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "CheckFmpDependency: Get Firmware Management Protocol failed. (%r)", Status));
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_FMP_PROTOCOL_NOT_FOUND;
goto cleanup;
}
FmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfFmpInstance);
if (FmpImageInfoBuf == NULL) {
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_INFO_BUFFER_FAILED;
goto cleanup;
}
DescriptorVer = AllocateZeroPool (sizeof(UINT32) * NumberOfFmpInstance);
if (DescriptorVer == NULL ) {
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_VER_BUFFER_FAILED;
goto cleanup;
}
DescriptorSize = AllocateZeroPool (sizeof(UINTN) * NumberOfFmpInstance);
if (DescriptorSize == NULL ) {
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_SIZE_BUFFER_FAILED;
goto cleanup;
}
FmpVersions = AllocateZeroPool (sizeof(FMP_DEPEX_CHECK_VERSION_DATA) * NumberOfFmpInstance);
if (FmpVersions == NULL) {
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_VER_BUFFER_FAILED;
goto cleanup;
}
@@ -164,7 +179,7 @@ CheckFmpDependency (
// Evaluate firmware image's depex, against the version of other Fmp instances.
//
if (Dependencies != NULL) {
- IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount);
+ IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount, &LocalLastAttemptStatus);
}
if (!IsSatisfied) {
@@ -194,5 +209,9 @@ CheckFmpDependency (
FreePool (FmpVersions);
}
+ if (LastAttemptStatus != NULL) {
+ *LastAttemptStatus = LocalLastAttemptStatus;
+ }
+
return IsSatisfied;
}
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
index 55e9af22909d..74247957ac4f 100644
--- a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
@@ -2,11 +2,13 @@
Null instance of FmpDependencyCheckLib.
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiDxe.h>
+#include <Guid/SystemResourceTable.h>
#include <Library/FmpDependencyCheckLib.h>
/**
@@ -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 holds 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.
@@ -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 != NULL) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ }
+
return TRUE;
}
diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c b/FmpDevicePkg/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 <Library/DebugLib.h>
#include <Library/FmpDependencyLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Guid/SystemResourceTable.h>
+#include <LastAttemptStatus.h>
+#include <FmpLastAttemptStatus.h>
//
// 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 FmpVersions
is NULL, FmpVersionsCount must be 0.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds 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 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 = LAST_ATTEMPT_STATUS_SUCCESS;
//
// Check if parameter is valid.
@@ -249,6 +260,7 @@ EvaluateDependency (
case EFI_FMP_DEP_PUSH_GUID:
if (Iterator + sizeof (EFI_GUID) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize) {
DEBUG ((DEBUG_ERROR, "EvaluateDependency: GUID extends beyond end of dependency expression!\n"));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GUID_BEYOND_DEPEX;
goto Error;
}
@@ -259,6 +271,7 @@ EvaluateDependency (
if(CompareGuid (&FmpVersions[Index].ImageTypeId, &ImageTypeId)){
Status = Push (FmpVersions[Index].Version, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
@@ -266,18 +279,21 @@ EvaluateDependency (
}
if (Index == FmpVersionsCount) {
DEBUG ((DEBUG_ERROR, "EvaluateDependency: %g is not found!\n", &ImageTypeId));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_FMP_NOT_FOUND;
goto Error;
}
break;
case EFI_FMP_DEP_PUSH_VERSION:
if (Iterator + sizeof (UINT32) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize ) {
DEBUG ((DEBUG_ERROR, "EvaluateDependency: VERSION extends beyond end of dependency expression!\n"));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_BEYOND_DEPEX;
goto Error;
}
Version = *(UINT32 *) (Iterator + 1);
Status = Push (Version, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
Iterator = Iterator + sizeof (UINT32);
@@ -286,154 +302,191 @@ EvaluateDependency (
Iterator += AsciiStrnLenS ((CHAR8 *) Iterator, DependenciesSize - (Iterator - Dependencies->Dependencies));
if (Iterator == (UINT8 *) Dependencies->Dependencies + DependenciesSize) {
DEBUG ((DEBUG_ERROR, "EvaluateDependency: STRING extends beyond end of dependency expression!\n"));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_STR_BEYOND_DEPEX;
goto Error;
}
break;
case EFI_FMP_DEP_AND:
Status = Pop (&Element1, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Push (Element1.Value.Boolean & Element2.Value.Boolean, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_OR:
Status = Pop (&Element1, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop(&Element2, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Push (Element1.Value.Boolean | Element2.Value.Boolean, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_NOT:
Status = Pop (&Element1, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Push (!(Element1.Value.Boolean), BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_TRUE:
Status = Push (TRUE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_FALSE:
Status = Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_EQ:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version == Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_GT:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version > Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_GTE:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version >= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_LT:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus= LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version < Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_LTE:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version <= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_END:
Status = Pop (&Element1, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
return Element1.Value.Boolean;
default:
DEBUG ((DEBUG_ERROR, "EvaluateDependency: Unknown Opcode - %02x!\n", *Iterator));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_UNKNOWN_OPCODE;
goto Error;
}
Iterator++;
}
DEBUG ((DEBUG_ERROR, "EvaluateDependency: No EFI_FMP_DEP_END Opcode in expression!\n"));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE;
Error:
+ if (LastAttemptStatus != NULL) {
+ *LastAttemptStatus = LocalLastAttemptStatus;
+ }
+
return FALSE;
}
/**
Validate the dependency expression and output its size.
- @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 holds the
+ last attempt status to report back to the caller.
+ If a last attempt status error code is not returned,
+ this function will not modify the LastAttemptStatus value.
@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 (
}
}
+ if (LastAttemptStatus != NULL) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE;
+ }
+
return FALSE;
}
/**
Get dependency from firmware image.
- @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 holds the
+ last attempt status to report back to the caller.
+ If a last attempt status error code is not returned,
+ this function will not modify the LastAttemptStatus value.
@retval The pointer to dependency.
@retval Null
@@ -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 != NULL) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GET_DEPEX_FAILURE;
+ }
return NULL;
}
@@ -539,7 +604,7 @@ GetImageDependency (
//
// Validate the dependency and get the size of dependency
//
- if (ValidateDependency (Depex, MaxDepexSize, DepexSize)) {
+ if (ValidateDependency (Depex, MaxDepexSize, DepexSize, LastAttemptStatus)) {
return Depex;
}
diff --git a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
index f8ccdd906f29..01ac19a7d5d7 100644
--- a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
+++ b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
@@ -2,6 +2,7 @@
Unit tests of EvaluateDependency API in FmpDependencyLib.
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -162,6 +163,7 @@ EvaluateDependencyTest (
{
BASIC_TEST_CONTEXT *TestContext;
BOOLEAN EvaluationResult;
+ UINT32 LastAttemptStatus;
TestContext = (BASIC_TEST_CONTEXT *)Context;
@@ -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
+ );
UT_ASSERT_EQUAL (EvaluationResult, TestContext->ExpectedResult);
diff --git a/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h b/FmpDevicePkg/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.
+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
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 holds 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.
@@ -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
);
#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.
- @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 holds the
+ last attempt status to report back to the caller.
+ If a last attempt status error code is not returned,
+ this function will not modify the LastAttemptStatus value.
@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
);
/**
Get dependency from firmware image.
- @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 holds the
+ last attempt status to report back to the caller.
+ If a last attempt status error code is not returned,
+ this function will not modify the LastAttemptStatus value.
@retval The pointer to dependency.
@retval Null
@@ -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
);
/**
@@ -73,6 +82,10 @@ GetImageDependency (
parameter is optional and can be set to NULL.
@param[in] FmpVersionsCount Element count of the array. When FmpVersions
is NULL, FmpVersionsCount must be 0.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds 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 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
);
#endif
--
2.28.0.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 6/6] FmpDevicePkg/FmpDeviceLib: Add Last Attempt Status to Check/Set API
[not found] <20201019235939.2320-1-michael.kubacki@outlook.com>
` (4 preceding siblings ...)
2020-10-19 23:59 ` [PATCH v6 5/6] FmpDevicePkg: Add Last Attempt Status support to dependency libs Michael Kubacki
@ 2020-10-19 23:59 ` Michael Kubacki
5 siblings, 0 replies; 6+ messages in thread
From: Michael Kubacki @ 2020-10-19 23:59 UTC (permalink / raw)
To: devel; +Cc: Liming Gao, Michael D Kinney, Guomin Jiang, Wei6 Xu
From: Michael Kubacki <michael.kubacki@microsoft.com>
Provides the ability for a given FMP device library instance to
return a Last Attempt Status code during check image and set image
operations with FmpDeviceCheckImageEx() and FmpDeviceSetImageEx().
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Wei6 Xu <wei6.xu@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
Reviewed-by: Wei6 Xu <wei6.xu@intel.com>
---
FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c | 144 +++++++++++++++++++-
FmpDevicePkg/Include/Library/FmpDeviceLib.h | 121 +++++++++++++++-
2 files changed, 263 insertions(+), 2 deletions(-)
diff --git a/FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c b/FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c
index 316de12e910c..f4f57b29bdb1 100644
--- a/FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c
+++ b/FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c
@@ -2,7 +2,7 @@
Provides firmware device specific services to support updates of a firmware
image stored in a firmware device.
- Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -10,6 +10,7 @@
**/
#include <PiDxe.h>
+#include <Guid/SystemResourceTable.h>
#include <Library/FmpDeviceLib.h>
/**
@@ -407,6 +408,57 @@ FmpDeviceCheckImage (
OUT UINT32 *ImageUpdatable
)
{
+ UINT32 LastAttemptStatus;
+
+ return FmpDeviceCheckImageWithStatus (Image, ImageSize, ImageUpdatable, &LastAttemptStatus);
+}
+
+/**
+ Checks if a new firmware image is valid for the firmware device. This
+ function allows firmware update operation to validate the firmware image
+ before FmpDeviceSetImage() is called.
+
+ @param[in] Image Points to a new firmware image.
+ @param[in] ImageSize Size, in bytes, of a new firmware image.
+ @param[out] ImageUpdatable Indicates if a new firmware image is valid for
+ a firmware update to the firmware device. The
+ following values from the Firmware Management
+ Protocol are supported:
+ IMAGE_UPDATABLE_VALID
+ IMAGE_UPDATABLE_INVALID
+ IMAGE_UPDATABLE_INVALID_TYPE
+ IMAGE_UPDATABLE_INVALID_OLD
+ IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE
+ @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. This value will only be checked when this
+ function returns an error.
+
+ The return status code must fall in the range of
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
+
+ If the value falls outside this range, it will be converted
+ to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
+
+ @retval EFI_SUCCESS The image was successfully checked. Additional
+ status information is returned in
+ ImageUpdatable.
+ @retval EFI_INVALID_PARAMETER Image is NULL.
+ @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDeviceCheckImageWithStatus (
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *ImageUpdatable,
+ OUT UINT32 *LastAttemptStatus
+ )
+{
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
return EFI_SUCCESS;
}
@@ -473,6 +525,96 @@ FmpDeviceSetImage (
OUT CHAR16 **AbortReason
)
{
+ UINT32 LastAttemptStatus;
+
+ return FmpDeviceSetImageWithStatus (
+ Image,
+ ImageSize,
+ VendorCode,
+ Progress,
+ CapsuleFwVersion,
+ AbortReason,
+ &LastAttemptStatus
+ );
+}
+
+/**
+ Updates a firmware device with a new firmware image. This function returns
+ EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image
+ is updatable, the function should perform the following minimal validations
+ before proceeding to do the firmware image update.
+ - Validate that the image is a supported image for this firmware device.
+ Return EFI_ABORTED if the image is not supported. Additional details
+ on why the image is not a supported image may be returned in AbortReason.
+ - Validate the data from VendorCode if is not NULL. Firmware image
+ validation must be performed before VendorCode data validation.
+ VendorCode data is ignored or considered invalid if image validation
+ fails. Return EFI_ABORTED if the VendorCode data is invalid.
+
+ VendorCode enables vendor to implement vendor-specific firmware image update
+ policy. Null if the caller did not specify the policy or use the default
+ policy. As an example, vendor can implement a policy to allow an option to
+ force a firmware image update when the abort reason is due to the new firmware
+ image version is older than the current firmware image version or bad image
+ checksum. Sensitive operations such as those wiping the entire firmware image
+ and render the device to be non-functional should be encoded in the image
+ itself rather than passed with the VendorCode. AbortReason enables vendor to
+ have the option to provide a more detailed description of the abort reason to
+ the caller.
+
+ @param[in] Image Points to the new firmware image.
+ @param[in] ImageSize Size, in bytes, of the new firmware image.
+ @param[in] VendorCode This enables vendor to implement vendor-specific
+ firmware image update policy. NULL indicates
+ the caller did not specify the policy or use the
+ default policy.
+ @param[in] Progress A function used to report the progress of
+ updating the firmware device with the new
+ firmware image.
+ @param[in] CapsuleFwVersion The version of the new firmware image from the
+ update capsule that provided the new firmware
+ image.
+ @param[out] AbortReason A pointer to a pointer to a Null-terminated
+ Unicode string providing more details on an
+ aborted operation. The buffer is allocated by
+ this function with
+ EFI_BOOT_SERVICES.AllocatePool(). It is the
+ caller's responsibility to free this buffer with
+ EFI_BOOT_SERVICES.FreePool().
+ @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. This value will only be checked when this
+ function returns an error.
+
+ The return status code must fall in the range of
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
+
+ If the value falls outside this range, it will be converted
+ to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
+
+ @retval EFI_SUCCESS The firmware device was successfully updated
+ with the new firmware image.
+ @retval EFI_ABORTED The operation is aborted. Additional details
+ are provided in AbortReason.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDeviceSetImageWithStatus (
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode, OPTIONAL
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
+ IN UINT32 CapsuleFwVersion,
+ OUT CHAR16 **AbortReason,
+ OUT UINT32 *LastAttemptStatus
+ )
+{
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
return EFI_UNSUPPORTED;
}
diff --git a/FmpDevicePkg/Include/Library/FmpDeviceLib.h b/FmpDevicePkg/Include/Library/FmpDeviceLib.h
index 9a89f5c2eec5..6abd99fa1f47 100644
--- a/FmpDevicePkg/Include/Library/FmpDeviceLib.h
+++ b/FmpDevicePkg/Include/Library/FmpDeviceLib.h
@@ -2,7 +2,7 @@
Provides firmware device specific services to support updates of a firmware
image stored in a firmware device.
- Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -403,6 +403,50 @@ FmpDeviceCheckImage (
OUT UINT32 *ImageUpdatable
);
+/**
+ Checks if a new firmware image is valid for the firmware device. This
+ function allows firmware update operation to validate the firmware image
+ before FmpDeviceSetImage() is called.
+
+ @param[in] Image Points to a new firmware image.
+ @param[in] ImageSize Size, in bytes, of a new firmware image.
+ @param[out] ImageUpdatable Indicates if a new firmware image is valid for
+ a firmware update to the firmware device. The
+ following values from the Firmware Management
+ Protocol are supported:
+ IMAGE_UPDATABLE_VALID
+ IMAGE_UPDATABLE_INVALID
+ IMAGE_UPDATABLE_INVALID_TYPE
+ IMAGE_UPDATABLE_INVALID_OLD
+ IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE
+ @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. This value will only be checked when this
+ function returns an error.
+
+ The return status code must fall in the range of
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
+
+ If the value falls outside this range, it will be converted
+ to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
+
+ @retval EFI_SUCCESS The image was successfully checked. Additional
+ status information is returned in
+ ImageUpdatable.
+ @retval EFI_INVALID_PARAMETER Image is NULL.
+ @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDeviceCheckImageWithStatus (
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *ImageUpdatable,
+ OUT UINT32 *LastAttemptStatus
+ );
+
/**
Updates a firmware device with a new firmware image. This function returns
EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image
@@ -466,6 +510,81 @@ FmpDeviceSetImage (
OUT CHAR16 **AbortReason
);
+/**
+ Updates a firmware device with a new firmware image. This function returns
+ EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image
+ is updatable, the function should perform the following minimal validations
+ before proceeding to do the firmware image update.
+ - Validate that the image is a supported image for this firmware device.
+ Return EFI_ABORTED if the image is not supported. Additional details
+ on why the image is not a supported image may be returned in AbortReason.
+ - Validate the data from VendorCode if is not NULL. Firmware image
+ validation must be performed before VendorCode data validation.
+ VendorCode data is ignored or considered invalid if image validation
+ fails. Return EFI_ABORTED if the VendorCode data is invalid.
+
+ VendorCode enables vendor to implement vendor-specific firmware image update
+ policy. Null if the caller did not specify the policy or use the default
+ policy. As an example, vendor can implement a policy to allow an option to
+ force a firmware image update when the abort reason is due to the new firmware
+ image version is older than the current firmware image version or bad image
+ checksum. Sensitive operations such as those wiping the entire firmware image
+ and render the device to be non-functional should be encoded in the image
+ itself rather than passed with the VendorCode. AbortReason enables vendor to
+ have the option to provide a more detailed description of the abort reason to
+ the caller.
+
+ @param[in] Image Points to the new firmware image.
+ @param[in] ImageSize Size, in bytes, of the new firmware image.
+ @param[in] VendorCode This enables vendor to implement vendor-specific
+ firmware image update policy. NULL indicates
+ the caller did not specify the policy or use the
+ default policy.
+ @param[in] Progress A function used to report the progress of
+ updating the firmware device with the new
+ firmware image.
+ @param[in] CapsuleFwVersion The version of the new firmware image from the
+ update capsule that provided the new firmware
+ image.
+ @param[out] AbortReason A pointer to a pointer to a Null-terminated
+ Unicode string providing more details on an
+ aborted operation. The buffer is allocated by
+ this function with
+ EFI_BOOT_SERVICES.AllocatePool(). It is the
+ caller's responsibility to free this buffer with
+ EFI_BOOT_SERVICES.FreePool().
+ @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. This value will only be checked when this
+ function returns an error.
+
+ The return status code must fall in the range of
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
+
+ If the value falls outside this range, it will be converted
+ to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
+
+ @retval EFI_SUCCESS The firmware device was successfully updated
+ with the new firmware image.
+ @retval EFI_ABORTED The operation is aborted. Additional details
+ are provided in AbortReason.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDeviceSetImageWithStatus (
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode, OPTIONAL
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
+ IN UINT32 CapsuleFwVersion,
+ OUT CHAR16 **AbortReason,
+ OUT UINT32 *LastAttemptStatus
+ );
+
/**
Lock the firmware device that contains a firmware image. Once a firmware
device is locked, any attempts to modify the firmware image contents in the
--
2.28.0.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread