// Protocol instance\r
//\r
const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate = {\r
- FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE, // Signature\r
- NULL, // Handle\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE, // Signature\r
+ NULL, // Handle\r
{ // Fmp\r
GetTheImageInfo,\r
GetTheImage,\r
GetPackageInfo,\r
SetPackageInfo\r
},\r
- FALSE, // DescriptorPopulated\r
- { // Desc\r
- 1, // ImageIndex\r
+ FALSE, // DescriptorPopulated\r
+ { // Desc\r
+ 1, // ImageIndex\r
//\r
// ImageTypeId\r
//\r
- { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },\r
+ { 0x00000000, 0x0000,0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }\r
+ },\r
1, // ImageId\r
NULL, // ImageIdName\r
0, // Version\r
0, // LastAttemptStatus\r
0 // HardwareInstance\r
},\r
- NULL, // ImageIdName\r
- NULL, // VersionName\r
- TRUE, // RuntimeVersionSupported\r
- NULL, // FmpDeviceLockEvent\r
- FALSE, // FmpDeviceLocked\r
- NULL, // FmpDeviceContext\r
- NULL, // VersionVariableName\r
- NULL, // LsvVariableName\r
- NULL, // LastAttemptStatusVariableName\r
- NULL, // LastAttemptVersionVariableName\r
- NULL, // FmpStateVariableName\r
- TRUE // DependenciesSatisfied\r
+ NULL, // ImageIdName\r
+ NULL, // VersionName\r
+ TRUE, // RuntimeVersionSupported\r
+ NULL, // FmpDeviceLockEvent\r
+ FALSE, // FmpDeviceLocked\r
+ NULL, // FmpDeviceContext\r
+ NULL, // VersionVariableName\r
+ NULL, // LsvVariableName\r
+ NULL, // LastAttemptStatusVariableName\r
+ NULL, // LastAttemptVersionVariableName\r
+ NULL, // FmpStateVariableName\r
+ TRUE // DependenciesSatisfied\r
};\r
\r
///\r
IN UINTN Completion\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
Status = EFI_UNSUPPORTED;\r
\r
UINTN ImageTypeIdGuidSize;\r
\r
FmpDeviceLibGuid = NULL;\r
- Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);\r
+ Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);\r
if (EFI_ERROR (Status)) {\r
if (Status != EFI_UNSUPPORTED) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName, Status));\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName));\r
Status = EFI_NOT_FOUND;\r
}\r
+\r
if (EFI_ERROR (Status)) {\r
ImageTypeIdGuidSize = PcdGetSize (PcdFmpDeviceImageTypeIdGuid);\r
if (ImageTypeIdGuidSize == sizeof (EFI_GUID)) {\r
FmpDeviceLibGuid = &gEfiCallerIdGuid;\r
}\r
}\r
+\r
return FmpDeviceLibGuid;\r
}\r
\r
// Check the FmpDeviceLib\r
//\r
DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
- Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);\r
+ Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);\r
if (EFI_ERROR (Status)) {\r
DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
}\r
}\r
\r
Private->Descriptor.ImageIndex = 1;\r
- CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid());\r
+ CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid ());\r
Private->Descriptor.ImageId = Private->Descriptor.ImageIndex;\r
- Private->Descriptor.ImageIdName = GetImageTypeNameString();\r
+ Private->Descriptor.ImageIdName = GetImageTypeNameString ();\r
\r
//\r
// Get the hardware instance from FmpDeviceLib\r
Status = FmpDeviceGetVersion (&Private->Descriptor.Version);\r
if (Status == EFI_UNSUPPORTED) {\r
Private->RuntimeVersionSupported = FALSE;\r
- Private->Descriptor.Version = GetVersionFromVariable (Private);\r
+ Private->Descriptor.Version = GetVersionFromVariable (Private);\r
} else if (EFI_ERROR (Status)) {\r
//\r
// Unexpected error. Use default version.\r
//\r
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString(), Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString (), Status));\r
Private->Descriptor.Version = DEFAULT_VERSION;\r
}\r
\r
//\r
// Confirm that buffer isn't null\r
//\r
- if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)\r
- || (PackageVersion == NULL)) {\r
+ if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)\r
+ || (PackageVersion == NULL))\r
+ {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
CopyMem (ImageInfo, &Private->Descriptor, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));\r
\r
*DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;\r
- *DescriptorCount = 1;\r
- *DescriptorSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
+ *DescriptorCount = 1;\r
+ *DescriptorSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
//\r
// means unsupported\r
//\r
if (EFI_ERROR (Status)) {\r
Size = 0;\r
}\r
+\r
if (*ImageSize < Size) {\r
*ImageSize = Size;\r
DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));\r
//\r
// Check to make sure that operation can be safely performed.\r
//\r
- if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize < (UINTN)Image || \\r
- ((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize >= (UINTN)Image + ImageSize) {\r
+ if ((((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize < (UINTN)Image) || \\r
+ (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize >= (UINTN)Image + ImageSize))\r
+ {\r
//\r
// Pointer overflow. Invalid image.\r
//\r
//\r
// Check to make sure that operation can be safely performed.\r
//\r
- if (CalculatedSize < sizeof (Image->MonotonicCount) ||\r
- CalculatedSize < AdditionalHeaderSize ||\r
- CalculatedSize < Image->AuthInfo.Hdr.dwLength ) {\r
+ if ((CalculatedSize < sizeof (Image->MonotonicCount)) ||\r
+ (CalculatedSize < AdditionalHeaderSize) ||\r
+ (CalculatedSize < Image->AuthInfo.Hdr.dwLength))\r
+ {\r
//\r
// Integer overflow. Invalid image.\r
//\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
+ @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
+ This function might also return error codes that occur within libraries\r
+ linked against this module that return last attempt error codes such as:\r
+\r
+ LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE to\r
+ LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MAX_ERROR_CODE_VALUE\r
+\r
+ LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE to\r
+ LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_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
+ Status = EFI_INVALID_PARAMETER;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;\r
goto cleanup;\r
}\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
+ Status = EFI_INVALID_PARAMETER;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE;\r
goto cleanup;\r
}\r
\r
//\r
- //Set to valid and then if any tests fail it will update this flag.\r
+ // Set to valid and then if any tests fail it will update this flag.\r
//\r
*ImageUpdatable = IMAGE_UPDATABLE_VALID;\r
\r
//\r
// not sure if this is needed\r
//\r
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);\r
PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);\r
\r
- if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {\r
+ if ((PublicKeyDataXdr == NULL) || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));\r
- Status = EFI_ABORTED;\r
+ Status = EFI_ABORTED;\r
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE;\r
} else {\r
//\r
// Try each key from PcdFmpDevicePkcs7CertBufferXdr\r
Index++;\r
DEBUG (\r
(DEBUG_INFO,\r
- "FmpDxe(%s): Certificate #%d [%p..%p].\n",\r
- mImageIdName,\r
- Index,\r
- PublicKeyDataXdr,\r
- PublicKeyDataXdrEnd\r
+ "FmpDxe(%s): Certificate #%d [%p..%p].\n",\r
+ mImageIdName,\r
+ Index,\r
+ PublicKeyDataXdr,\r
+ PublicKeyDataXdrEnd\r
)\r
);\r
\r
// Key data extends beyond end of PCD\r
//\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));\r
- Status = EFI_ABORTED;\r
+ Status = EFI_ABORTED;\r
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE;\r
break;\r
}\r
+\r
//\r
// Read key length stored in big-endian format\r
//\r
// Key data extends beyond end of PCD\r
//\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));\r
- Status = EFI_ABORTED;\r
+ Status = EFI_ABORTED;\r
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH;\r
break;\r
}\r
+\r
PublicKeyData = PublicKeyDataXdr;\r
- Status = AuthenticateFmpImage (\r
- (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,\r
- ImageSize,\r
- PublicKeyData,\r
- PublicKeyDataLength\r
- );\r
+ Status = AuthenticateFmpImage (\r
+ (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,\r
+ ImageSize,\r
+ PublicKeyData,\r
+ PublicKeyDataLength\r
+ );\r
if (!EFI_ERROR (Status)) {\r
break;\r
}\r
+\r
PublicKeyDataXdr += PublicKeyDataLength;\r
- PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));\r
+ PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));\r
}\r
}\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
+\r
goto cleanup;\r
}\r
\r
//\r
if (ImageIndex != 1) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));\r
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;\r
- Status = EFI_INVALID_PARAMETER;\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
//\r
// Get the dependency from Image.\r
//\r
- Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);\r
+ Dependencies = GetImageDependency (\r
+ (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,\r
+ ImageSize,\r
+ &DependenciesSize,\r
+ LastAttemptStatus\r
+ );\r
+ if (*LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {\r
+ Status = EFI_ABORTED;\r
+ goto cleanup;\r
+ }\r
\r
//\r
// Check the FmpPayloadHeader\r
//\r
- FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );\r
+ FmpPayloadHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);\r
if (FmpPayloadHeader == NULL) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
- Status = EFI_ABORTED;\r
+ Status = EFI_ABORTED;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;\r
goto cleanup;\r
}\r
+\r
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));\r
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
- Status = EFI_SUCCESS;\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
if (Version < Private->Descriptor.LowestSupportedImageVersion) {\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",\r
- mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)\r
+ "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",\r
+ mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)\r
);\r
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;\r
- Status = EFI_SUCCESS;\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
//\r
// Evaluate dependency expression\r
//\r
- Private->DependenciesSatisfied = CheckFmpDependency (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize);\r
+ Private->DependenciesSatisfied = CheckFmpDependency (\r
+ Private->Descriptor.ImageTypeId,\r
+ Version,\r
+ Dependencies,\r
+ DependenciesSize,\r
+ &LocalLastAttemptStatus\r
+ );\r
if (!Private->DependenciesSatisfied) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));\r
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
- Status = EFI_SUCCESS;\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+ Status = EFI_SUCCESS;\r
+ *LastAttemptStatus = LocalLastAttemptStatus;\r
goto cleanup;\r
}\r
\r
Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));\r
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
- Status = EFI_SUCCESS;\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
// Call FmpDevice Lib Check Image on the\r
// Raw payload. So all headers need stripped off\r
//\r
- AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
+ AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
if (AllHeaderSize == 0) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
- Status = EFI_ABORTED;\r
+ Status = EFI_ABORTED;\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;\r
goto cleanup;\r
}\r
+\r
RawSize = ImageSize - AllHeaderSize;\r
\r
//\r
// FmpDeviceLib CheckImage function to do any specific checks\r
//\r
- Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable);\r
+ Status = FmpDeviceCheckImageWithStatus ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable, LastAttemptStatus);\r
if (EFI_ERROR (Status)) {\r
+ // The image cannot be valid if an error occurred checking the image\r
+ if (*ImageUpdatable == IMAGE_UPDATABLE_VALID) {\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+ }\r
+\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));\r
}\r
\r
+ //\r
+ // Only validate the library last attempt status code if the image is not updatable.\r
+ // This specifically avoids converting LAST_ATTEMPT_STATUS_SUCCESS if it set for an updatable image.\r
+ //\r
+ if (*ImageUpdatable != IMAGE_UPDATABLE_VALID) {\r
+ //\r
+ // LastAttemptStatus returned from the device library should fall within the designated error range\r
+ // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]\r
+ //\r
+ if ((*LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||\r
+ (*LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))\r
+ {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "FmpDxe(%s): CheckTheImage() - LastAttemptStatus %d from FmpDeviceCheckImageWithStatus() is invalid.\n",\r
+ mImageIdName,\r
+ *LastAttemptStatus\r
+ ));\r
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
+ }\r
+ }\r
+\r
cleanup:\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
EFI_FIRMWARE_IMAGE_DEP *Dependencies;\r
UINT32 DependenciesSize;\r
\r
- Status = EFI_SUCCESS;\r
- Private = NULL;\r
- Updateable = 0;\r
- BooleanValue = FALSE;\r
- FmpHeaderSize = 0;\r
- FmpHeader = NULL;\r
- FmpPayloadSize = 0;\r
- AllHeaderSize = 0;\r
- IncomingFwVersion = 0;\r
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
- Dependencies = NULL;\r
- DependenciesSize = 0;\r
+ Status = EFI_SUCCESS;\r
+ Private = NULL;\r
+ Updateable = 0;\r
+ BooleanValue = FALSE;\r
+ FmpHeaderSize = 0;\r
+ FmpHeader = NULL;\r
+ FmpPayloadSize = 0;\r
+ AllHeaderSize = 0;\r
+ IncomingFwVersion = 0;\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
+ Dependencies = NULL;\r
+ DependenciesSize = 0;\r
\r
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
return EFI_UNSUPPORTED;\r
\r
if (This == NULL) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - This is NULL.\n", mImageIdName));\r
- Status = EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;\r
goto cleanup;\r
}\r
\r
//\r
if (Private->FmpDeviceLocked) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));\r
- Status = EFI_UNSUPPORTED;\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED;\r
+ Status = EFI_UNSUPPORTED;\r
goto cleanup;\r
}\r
\r
//\r
// Call check image to verify the image\r
//\r
- Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable);\r
+ Status = CheckTheImageInternal (This, ImageIndex, Image, ImageSize, &Updateable, &LastAttemptStatus);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));\r
- if (Status == EFI_SECURITY_VIOLATION) {\r
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;\r
- }\r
goto cleanup;\r
}\r
\r
//\r
// Get the dependency from Image.\r
//\r
- Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);\r
+ Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize, &LastAttemptStatus);\r
\r
//\r
// No functional error in CheckTheImage. Attempt to get the Version to\r
// support better error reporting.\r
//\r
- FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );\r
+ FmpHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);\r
if (FmpHeader == NULL) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
- Status = EFI_ABORTED;\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;\r
+ Status = EFI_ABORTED;\r
goto cleanup;\r
}\r
+\r
Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);\r
if (!EFI_ERROR (Status)) {\r
//\r
SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
}\r
\r
-\r
if (Updateable != IMAGE_UPDATABLE_VALID) {\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",\r
- mImageIdName, Updateable)\r
+ "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",\r
+ mImageIdName, Updateable)\r
);\r
if (Private->DependenciesSatisfied == FALSE) {\r
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;\r
}\r
+\r
Status = EFI_ABORTED;\r
goto cleanup;\r
}\r
\r
if (Progress == NULL) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));\r
- Status = EFI_INVALID_PARAMETER;\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
}\r
\r
}\r
\r
//\r
- //Check System Power\r
+ // Check System Power\r
//\r
Status = CheckSystemPower (&BooleanValue);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API;\r
goto cleanup;\r
}\r
+\r
if (!BooleanValue) {\r
Status = EFI_ABORTED;\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName)\r
+ "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName)\r
);\r
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;\r
goto cleanup;\r
Progress (2);\r
\r
//\r
- //Check System Thermal\r
+ // Check System Thermal\r
//\r
Status = CheckSystemThermal (&BooleanValue);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API;\r
goto cleanup;\r
}\r
+\r
if (!BooleanValue) {\r
- Status = EFI_ABORTED;\r
+ Status = EFI_ABORTED;\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL;\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)\r
+ "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)\r
);\r
goto cleanup;\r
}\r
Progress (3);\r
\r
//\r
- //Check System Environment\r
+ // Check System Environment\r
//\r
Status = CheckSystemEnvironment (&BooleanValue);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API;\r
goto cleanup;\r
}\r
+\r
if (!BooleanValue) {\r
- Status = EFI_ABORTED;\r
+ Status = EFI_ABORTED;\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV;\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)\r
+ "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)\r
);\r
goto cleanup;\r
}\r
Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;\r
goto cleanup;\r
}\r
\r
AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
if (AllHeaderSize == 0) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
- Status = EFI_ABORTED;\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;\r
+ Status = EFI_ABORTED;\r
goto cleanup;\r
}\r
\r
Progress (5);\r
\r
//\r
- //Copy the requested image to the firmware using the FmpDeviceLib\r
+ // Copy the requested image to the firmware using the FmpDeviceLib\r
//\r
- Status = FmpDeviceSetImage (\r
+ Status = FmpDeviceSetImageWithStatus (\r
(((UINT8 *)Image) + AllHeaderSize),\r
ImageSize - AllHeaderSize,\r
VendorCode,\r
FmpDxeProgress,\r
IncomingFwVersion,\r
- AbortReason\r
+ AbortReason,\r
+ &LastAttemptStatus\r
);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status));\r
+\r
+ //\r
+ // LastAttemptStatus returned from the device library should fall within the designated error range\r
+ // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]\r
+ //\r
+ if ((LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||\r
+ (LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))\r
+ {\r
+ DEBUG (\r
+ (DEBUG_ERROR,\r
+ "FmpDxe(%s): SetTheImage() - LastAttemptStatus %d from FmpDeviceSetImageWithStatus() is invalid.\n",\r
+ mImageIdName,\r
+ LastAttemptStatus)\r
+ );\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
+ }\r
+\r
goto cleanup;\r
}\r
\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName, Status));\r
}\r
+\r
Status = EFI_SUCCESS;\r
}\r
\r
mProgressFunc = NULL;\r
\r
if (Private != NULL) {\r
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName, LastAttemptStatus));\r
SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
}\r
\r
// Lock the firmware device\r
//\r
FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
- Status = FmpDeviceLock();\r
+ Status = FmpDeviceLock ();\r
if (EFI_ERROR (Status)) {\r
if (Status != EFI_UNSUPPORTED) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));\r
DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));\r
}\r
}\r
+\r
Private->FmpDeviceLocked = TRUE;\r
}\r
}\r
//\r
// Initialize private context data structure\r
//\r
- Private->Handle = Handle;\r
+ Private->Handle = Handle;\r
Private->FmpDeviceContext = NULL;\r
- Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+ Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
if (Status == EFI_UNSUPPORTED) {\r
Private->FmpDeviceContext = NULL;\r
} else if (EFI_ERROR (Status)) {\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName, Status));\r
}\r
+\r
ASSERT_EFI_ERROR (Status);\r
} else {\r
DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));\r
//\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&Private->Handle,\r
- &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,\r
- &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ &Private->Fmp,\r
+ &gEdkiiFirmwareManagementProgressProtocolGuid,\r
+ &mFmpProgress,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
if (Private->FmpDeviceLockEvent != NULL) {\r
gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
}\r
+\r
if (Private->Descriptor.VersionName != NULL) {\r
FreePool (Private->Descriptor.VersionName);\r
}\r
+\r
if (Private->FmpDeviceContext != NULL) {\r
FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
}\r
+\r
if (Private->VersionVariableName != NULL) {\r
FreePool (Private->VersionVariableName);\r
}\r
+\r
if (Private->LsvVariableName != NULL) {\r
FreePool (Private->LsvVariableName);\r
}\r
+\r
if (Private->LastAttemptStatusVariableName != NULL) {\r
FreePool (Private->LastAttemptStatusVariableName);\r
}\r
+\r
if (Private->LastAttemptVersionVariableName != NULL) {\r
FreePool (Private->LastAttemptVersionVariableName);\r
}\r
+\r
if (Private->FmpStateVariableName != NULL) {\r
FreePool (Private->FmpStateVariableName);\r
}\r
+\r
FreePool (Private);\r
}\r
}\r
\r
Status = gBS->UninstallMultipleProtocolInterfaces (\r
Private->Handle,\r
- &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,\r
- &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ &Private->Fmp,\r
+ &gEdkiiFirmwareManagementProgressProtocolGuid,\r
+ &mFmpProgress,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
if (Private->Descriptor.VersionName != NULL) {\r
FreePool (Private->Descriptor.VersionName);\r
}\r
+\r
if (Private->FmpDeviceContext != NULL) {\r
FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
}\r
+\r
if (Private->VersionVariableName != NULL) {\r
FreePool (Private->VersionVariableName);\r
}\r
+\r
if (Private->LsvVariableName != NULL) {\r
FreePool (Private->LsvVariableName);\r
}\r
+\r
if (Private->LastAttemptStatusVariableName != NULL) {\r
FreePool (Private->LastAttemptStatusVariableName);\r
}\r
+\r
if (Private->LastAttemptVersionVariableName != NULL) {\r
FreePool (Private->LastAttemptVersionVariableName);\r
}\r
+\r
if (Private->FmpStateVariableName != NULL) {\r
FreePool (Private->FmpStateVariableName);\r
}\r
+\r
FreePool (Private);\r
\r
return EFI_SUCCESS;\r
if (mFmpSingleInstance) {\r
return UninstallFmpInstance (ImageHandle);\r
}\r
+\r
return EFI_SUCCESS;\r
}\r
\r
//\r
// Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.\r
//\r
- mImageIdName = (CHAR16 *) PcdGetPtr (PcdFmpDeviceImageIdName);\r
- if (PcdGetSize (PcdFmpDeviceImageIdName) <= 2 || mImageIdName[0] == 0) {\r
+ mImageIdName = (CHAR16 *)PcdGetPtr (PcdFmpDeviceImageIdName);\r
+ if ((PcdGetSize (PcdFmpDeviceImageIdName) <= 2) || (mImageIdName[0] == 0)) {\r
//\r
// PcdFmpDeviceImageIdName must be set to a non-empty Unicode string\r
//\r
if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {\r
mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);\r
}\r
+\r
DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));\r
\r
//\r