@param[in] ImageSize Size of the new image in bytes.\r
@param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,\r
if available, additional information if the image is invalid.\r
+ @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt status to report\r
+ back to the ESRT table in case of error. If an error does not occur,\r
+ this function will set the value to LAST_ATTEMPT_STATUS_SUCCESS.\r
+\r
+ This function will return error codes that occur within this function\r
+ implementation within a driver range of last attempt error codes from\r
+ LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE\r
+ to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE.\r
\r
@retval EFI_SUCCESS The image was successfully checked.\r
@retval EFI_ABORTED The operation is aborted.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-CheckTheImage (\r
+CheckTheImageInternal (\r
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
IN UINT8 ImageIndex,\r
IN CONST VOID *Image,\r
IN UINTN ImageSize,\r
- OUT UINT32 *ImageUpdatable\r
+ OUT UINT32 *ImageUpdatable,\r
+ OUT UINT32 *LastAttemptStatus\r
)\r
{\r
EFI_STATUS Status;\r
+ UINT32 LocalLastAttemptStatus;\r
FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
UINTN RawSize;\r
VOID *FmpPayloadHeader;\r
EFI_FIRMWARE_IMAGE_DEP *Dependencies;\r
UINT32 DependenciesSize;\r
\r
- Status = EFI_SUCCESS;\r
- RawSize = 0;\r
- FmpPayloadHeader = NULL;\r
- FmpPayloadSize = 0;\r
- Version = 0;\r
- FmpHeaderSize = 0;\r
- AllHeaderSize = 0;\r
- Dependencies = NULL;\r
- DependenciesSize = 0;\r
+ Status = EFI_SUCCESS;\r
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
+ RawSize = 0;\r
+ FmpPayloadHeader = NULL;\r
+ FmpPayloadSize = 0;\r
+ Version = 0;\r
+ FmpHeaderSize = 0;\r
+ AllHeaderSize = 0;\r
+ Dependencies = NULL;\r
+ DependenciesSize = 0;\r
\r
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ if (LastAttemptStatus == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImageInternal() - LastAttemptStatus is NULL.\n", mImageIdName));\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto cleanup;\r
+ }\r
+\r
+ //\r
+ // A last attempt status error code will always override the success\r
+ // value before returning from the function\r
+ //\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
+\r
if (This == NULL) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - This is NULL.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;\r
goto cleanup;\r
}\r
\r
if (ImageUpdatable == NULL) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE;\r
goto cleanup;\r
}\r
\r
// not sure if this is needed\r
//\r
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE;\r
} else {\r
//\r
// Try each key from PcdFmpDevicePkcs7CertBufferXdr\r
//\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE;\r
break;\r
}\r
//\r
//\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH;\r
break;\r
}\r
PublicKeyData = PublicKeyDataXdr;\r
\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));\r
+ if (LocalLastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {\r
+ *LastAttemptStatus = LocalLastAttemptStatus;\r
+ } else {\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE;\r
+ }\r
goto cleanup;\r
}\r
\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));\r
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;\r
Status = EFI_INVALID_PARAMETER;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX;\r
goto cleanup;\r
}\r
\r
if (FmpPayloadHeader == NULL) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;\r
goto cleanup;\r
}\r
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));\r
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
Status = EFI_SUCCESS;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION;\r
goto cleanup;\r
}\r
\r
);\r
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;\r
Status = EFI_SUCCESS;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW;\r
goto cleanup;\r
}\r
\r
DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));\r
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
Status = EFI_SUCCESS;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;\r
goto cleanup;\r
}\r
\r
if (AllHeaderSize == 0) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;\r
goto cleanup;\r
}\r
RawSize = ImageSize - AllHeaderSize;\r
return Status;\r
}\r
\r
+/**\r
+ Checks if the firmware image is valid for the device.\r
+\r
+ This function allows firmware update application to validate the firmware image without\r
+ invoking the SetImage() first.\r
+\r
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
+ The number is between 1 and DescriptorCount.\r
+ @param[in] Image Points to the new image.\r
+ @param[in] ImageSize Size of the new image in bytes.\r
+ @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,\r
+ if available, additional information if the image is invalid.\r
+\r
+ @retval EFI_SUCCESS The image was successfully checked.\r
+ @retval EFI_ABORTED The operation is aborted.\r
+ @retval EFI_INVALID_PARAMETER The Image was NULL.\r
+ @retval EFI_UNSUPPORTED The operation is not supported.\r
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CheckTheImage (\r
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
+ IN UINT8 ImageIndex,\r
+ IN CONST VOID *Image,\r
+ IN UINTN ImageSize,\r
+ OUT UINT32 *ImageUpdatable\r
+ )\r
+{\r
+ UINT32 LastAttemptStatus;\r
+\r
+ return CheckTheImageInternal (This, ImageIndex, Image, ImageSize, ImageUpdatable, &LastAttemptStatus);\r
+}\r
+\r
/**\r
Updates the firmware image of the device.\r
\r