2 Produces a Firmware Management Protocol that supports updates to a firmware
3 image stored in a firmware device with platform and firmware device specific
4 information provided through PCDs and libraries.
6 Copyright (c) Microsoft Corporation.<BR>
7 Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include "VariableSupport.h"
17 /// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
18 /// FILE_GUID must always be overridden in the <Defines> section to provide
19 /// the ESRT GUID value associated with the updatable firmware image. A
20 /// check is made in this module's driver entry point to verify that a
21 /// new FILE_GUID value has been defined.
23 const EFI_GUID mDefaultModuleFileGuid
= {
24 0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }
28 /// TRUE if FmpDeviceLib manages a single firmware storage device.
30 BOOLEAN mFmpSingleInstance
= FALSE
;
33 /// Firmware Management Protocol instance that is initialized in the entry
34 /// point from PCD settings.
36 EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL mFmpProgress
;
39 // Template of the private context structure for the Firmware Management
42 const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate
= {
43 FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE
, // Signature
53 FALSE
, // DescriptorPopulated
59 { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
65 0, // AttributesSupported
66 0, // AttributesSetting
68 0, // LowestSupportedImageVersion
69 0, // LastAttemptVersion
70 0, // LastAttemptStatus
75 TRUE
, // RuntimeVersionSupported
76 NULL
, // FmpDeviceLockEvent
77 FALSE
, // FmpDeviceLocked
78 NULL
, // FmpDeviceContext
79 NULL
, // VersionVariableName
80 NULL
, // LsvVariableName
81 NULL
, // LastAttemptStatusVariableName
82 NULL
, // LastAttemptVersionVariableName
83 NULL
, // FmpStateVariableName
84 TRUE
// DependenciesSatisfied
88 /// GUID that is used to create event used to lock the firmware storage device.
90 EFI_GUID
*mLockGuid
= NULL
;
93 /// Progress() function pointer passed into SetTheImage()
95 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc
= NULL
;
98 /// Null-terminated Unicode string retrieved from PcdFmpDeviceImageIdName.
100 CHAR16
*mImageIdName
= NULL
;
103 Callback function to report the process of the firmware updating.
105 Wrap the caller's version in this so that progress from the device lib is
106 within the expected range. Convert device lib 0% - 100% to 6% - 98%.
108 FmpDxe 1% - 5% for validation
109 FmpDeviceLib 6% - 98% for flashing/update
110 FmpDxe 99% - 100% finish
112 @param[in] Completion A value between 1 and 100 indicating the current
113 completion progress of the firmware update. Completion
114 progress is reported as from 1 to 100 percent. A value
115 of 0 is used by the driver to indicate that progress
116 reporting is not supported.
118 @retval EFI_SUCCESS The progress was updated.
119 @retval EFI_UNSUPPORTED Updating progress is not supported.
130 Status
= EFI_UNSUPPORTED
;
132 if (mProgressFunc
== NULL
) {
137 // Reserve 6% - 98% for the FmpDeviceLib. Call the real progress function.
139 Status
= mProgressFunc (((Completion
* 92) / 100) + 6);
141 if (Status
== EFI_UNSUPPORTED
) {
142 mProgressFunc
= NULL
;
149 Returns a pointer to the ImageTypeId GUID value. An attempt is made to get
150 the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide
151 a GUID value, then PcdFmpDeviceImageTypeIdGuid is used. If the size of
152 PcdFmpDeviceImageTypeIdGuid is not the size of EFI_GUID, then gEfiCallerIdGuid
155 @retval The ImageTypeId GUID
164 EFI_GUID
*FmpDeviceLibGuid
;
165 UINTN ImageTypeIdGuidSize
;
167 FmpDeviceLibGuid
= NULL
;
168 Status
= FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid
);
169 if (EFI_ERROR (Status
)) {
170 if (Status
!= EFI_UNSUPPORTED
) {
171 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName
, Status
));
173 } else if (FmpDeviceLibGuid
== NULL
) {
174 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName
));
175 Status
= EFI_NOT_FOUND
;
177 if (EFI_ERROR (Status
)) {
178 ImageTypeIdGuidSize
= PcdGetSize (PcdFmpDeviceImageTypeIdGuid
);
179 if (ImageTypeIdGuidSize
== sizeof (EFI_GUID
)) {
180 FmpDeviceLibGuid
= (EFI_GUID
*)PcdGetPtr (PcdFmpDeviceImageTypeIdGuid
);
182 DEBUG ((DEBUG_WARN
, "FmpDxe(%s): Fall back to ImageTypeIdGuid of gEfiCallerIdGuid\n", mImageIdName
));
183 FmpDeviceLibGuid
= &gEfiCallerIdGuid
;
186 return FmpDeviceLibGuid
;
190 Returns a pointer to the Null-terminated Unicode ImageIdName string.
192 @retval Null-terminated Unicode ImageIdName string.
196 GetImageTypeNameString (
204 Lowest supported version is a combo of three parts.
205 1. Check if the device lib has a lowest supported version
206 2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)
207 3. Check Fixed at build PCD
209 @param[in] Private Pointer to the private context structure for the
210 Firmware Management Protocol instance.
212 @retval The largest value
216 GetLowestSupportedVersion (
217 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
221 UINT32 DeviceLibLowestSupportedVersion
;
222 UINT32 VariableLowestSupportedVersion
;
226 // Get the LowestSupportedVersion.
229 if (!IsLowestSupportedVersionCheckRequired ()) {
231 // Any Version can pass the 0 LowestSupportedVersion check.
236 ReturnLsv
= PcdGet32 (PcdFmpDeviceBuildTimeLowestSupportedVersion
);
239 // Check the FmpDeviceLib
241 DeviceLibLowestSupportedVersion
= DEFAULT_LOWESTSUPPORTEDVERSION
;
242 Status
= FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion
);
243 if (EFI_ERROR (Status
)) {
244 DeviceLibLowestSupportedVersion
= DEFAULT_LOWESTSUPPORTEDVERSION
;
247 if (DeviceLibLowestSupportedVersion
> ReturnLsv
) {
248 ReturnLsv
= DeviceLibLowestSupportedVersion
;
252 // Check the lowest supported version UEFI variable for this device
254 VariableLowestSupportedVersion
= GetLowestSupportedVersionFromVariable (Private
);
255 if (VariableLowestSupportedVersion
> ReturnLsv
) {
256 ReturnLsv
= VariableLowestSupportedVersion
;
260 // Return the largest value
266 Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the private
269 @param[in] Private Pointer to the private context structure for the
270 Firmware Management Protocol instance.
275 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
279 UINT32 DependenciesSize
;
281 if (Private
== NULL
) {
282 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): PopulateDescriptor() - Private is NULL.\n", mImageIdName
));
286 if (Private
->DescriptorPopulated
) {
290 Private
->Descriptor
.ImageIndex
= 1;
291 CopyGuid (&Private
->Descriptor
.ImageTypeId
, GetImageTypeIdGuid());
292 Private
->Descriptor
.ImageId
= Private
->Descriptor
.ImageIndex
;
293 Private
->Descriptor
.ImageIdName
= GetImageTypeNameString();
296 // Get the hardware instance from FmpDeviceLib
298 Status
= FmpDeviceGetHardwareInstance (&Private
->Descriptor
.HardwareInstance
);
299 if (Status
== EFI_UNSUPPORTED
) {
300 Private
->Descriptor
.HardwareInstance
= 0;
304 // Generate UEFI Variable names used to store status information for this
307 GenerateFmpVariableNames (Private
);
310 // Get the version. Some devices don't support getting the firmware version
311 // at runtime. If FmpDeviceLib does not support returning a version, then
312 // it is stored in a UEFI variable.
314 Status
= FmpDeviceGetVersion (&Private
->Descriptor
.Version
);
315 if (Status
== EFI_UNSUPPORTED
) {
316 Private
->RuntimeVersionSupported
= FALSE
;
317 Private
->Descriptor
.Version
= GetVersionFromVariable (Private
);
318 } else if (EFI_ERROR (Status
)) {
320 // Unexpected error. Use default version.
322 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName
, GetImageTypeNameString(), Status
));
323 Private
->Descriptor
.Version
= DEFAULT_VERSION
;
327 // Free the current version name. Shouldn't really happen but this populate
328 // function could be called multiple times (to refresh).
330 if (Private
->Descriptor
.VersionName
!= NULL
) {
331 FreePool (Private
->Descriptor
.VersionName
);
332 Private
->Descriptor
.VersionName
= NULL
;
336 // Attempt to get the version string from the FmpDeviceLib
338 Status
= FmpDeviceGetVersionString (&Private
->Descriptor
.VersionName
);
339 if (Status
== EFI_UNSUPPORTED
) {
340 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName
));
341 Private
->Descriptor
.VersionName
= AllocateCopyPool (
342 sizeof (VERSION_STRING_NOT_SUPPORTED
),
343 VERSION_STRING_NOT_SUPPORTED
345 } else if (EFI_ERROR (Status
)) {
346 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName
));
347 Private
->Descriptor
.VersionName
= AllocateCopyPool (
348 sizeof (VERSION_STRING_NOT_AVAILABLE
),
349 VERSION_STRING_NOT_AVAILABLE
353 Private
->Descriptor
.LowestSupportedImageVersion
= GetLowestSupportedVersion (Private
);
356 // Get attributes from the FmpDeviceLib
358 FmpDeviceGetAttributes (
359 &Private
->Descriptor
.AttributesSupported
,
360 &Private
->Descriptor
.AttributesSetting
364 // Force set the updatable bits in the attributes;
366 Private
->Descriptor
.AttributesSupported
|= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE
;
367 Private
->Descriptor
.AttributesSetting
|= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE
;
370 // Force set the authentication bits in the attributes;
372 Private
->Descriptor
.AttributesSupported
|= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED
);
373 Private
->Descriptor
.AttributesSetting
|= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED
);
375 Private
->Descriptor
.Compatibilities
= 0;
378 // Get the size of the firmware image from the FmpDeviceLib
380 Status
= FmpDeviceGetSize (&Private
->Descriptor
.Size
);
381 if (EFI_ERROR (Status
)) {
382 Private
->Descriptor
.Size
= 0;
385 Private
->Descriptor
.LastAttemptVersion
= GetLastAttemptVersionFromVariable (Private
);
386 Private
->Descriptor
.LastAttemptStatus
= GetLastAttemptStatusFromVariable (Private
);
389 // Get the dependency from the FmpDependencyDeviceLib.
391 Private
->Descriptor
.Dependencies
= NULL
;
394 // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
396 if (Private
->Descriptor
.AttributesSetting
& IMAGE_ATTRIBUTE_DEPENDENCY
) {
397 Private
->Descriptor
.Dependencies
= GetFmpDependency (&DependenciesSize
);
400 Private
->DescriptorPopulated
= TRUE
;
404 Returns information about the current firmware image(s) of the device.
406 This function allows a copy of the current firmware image to be created and saved.
407 The saved copy could later been used, for example, in firmware image recovery or rollback.
409 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
410 @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
411 On input, this is the size of the buffer allocated by the caller.
412 On output, it is the size of the buffer returned by the firmware
413 if the buffer was large enough, or the size of the buffer needed
414 to contain the image(s) information if the buffer was too small.
415 @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
416 information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
417 @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
418 associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
419 @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
420 descriptors or firmware images within this device.
421 @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
422 of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
423 @param[out] PackageVersion A version number that represents all the firmware images in the device.
424 The format is vendor specific and new version must have a greater value
425 than the old version. If PackageVersion is not supported, the value is
426 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
427 is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
428 that package version update is in progress.
429 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
430 package version name. The buffer is allocated by this function with
431 AllocatePool(), and it is the caller's responsibility to free it with a call
434 @retval EFI_SUCCESS The device was successfully updated with the new image.
435 @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
436 needed to hold the image(s) information is returned in ImageInfoSize.
437 @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
438 @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
444 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
445 IN OUT UINTN
*ImageInfoSize
,
446 IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
447 OUT UINT32
*DescriptorVersion
,
448 OUT UINT8
*DescriptorCount
,
449 OUT UINTN
*DescriptorSize
,
450 OUT UINT32
*PackageVersion
,
451 OUT CHAR16
**PackageVersionName
455 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
457 Status
= EFI_SUCCESS
;
460 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImageInfo() - This is NULL.\n", mImageIdName
));
461 Status
= EFI_INVALID_PARAMETER
;
466 // Retrieve the private context structure
468 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This
);
469 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
472 // Check for valid pointer
474 if (ImageInfoSize
== NULL
) {
475 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName
));
476 Status
= EFI_INVALID_PARAMETER
;
481 // Check the buffer size
482 // NOTE: Check this first so caller can get the necessary memory size it must allocate.
484 if (*ImageInfoSize
< (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
))) {
485 *ImageInfoSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
486 DEBUG ((DEBUG_VERBOSE
, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName
));
487 Status
= EFI_BUFFER_TOO_SMALL
;
492 // Confirm that buffer isn't null
494 if ( (ImageInfo
== NULL
) || (DescriptorVersion
== NULL
) || (DescriptorCount
== NULL
) || (DescriptorSize
== NULL
)
495 || (PackageVersion
== NULL
)) {
496 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName
));
497 Status
= EFI_INVALID_PARAMETER
;
502 // Set the size to whatever we need
504 *ImageInfoSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
507 // Make sure the descriptor has already been loaded or refreshed
509 PopulateDescriptor (Private
);
512 // Copy the image descriptor
514 CopyMem (ImageInfo
, &Private
->Descriptor
, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
));
516 *DescriptorVersion
= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
;
517 *DescriptorCount
= 1;
518 *DescriptorSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
522 *PackageVersion
= 0xFFFFFFFF;
525 // Do not update PackageVersionName since it is not supported in this instance.
534 Retrieves a copy of the current firmware image of the device.
536 This function allows a copy of the current firmware image to be created and saved.
537 The saved copy could later been used, for example, in firmware image recovery or rollback.
539 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
540 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
541 The number is between 1 and DescriptorCount.
542 @param[in, out] Image Points to the buffer where the current image is copied to.
543 @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
544 On return, points to the length of the image, in bytes.
546 @retval EFI_SUCCESS The device was successfully updated with the new image.
547 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
548 image. The current buffer size needed to hold the image is returned
550 @retval EFI_INVALID_PARAMETER The Image was NULL.
551 @retval EFI_NOT_FOUND The current image is not copied to the buffer.
552 @retval EFI_UNSUPPORTED The operation is not supported.
553 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
559 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
562 IN OUT UINTN
*ImageSize
566 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
569 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable
)) {
570 return EFI_UNSUPPORTED
;
573 Status
= EFI_SUCCESS
;
576 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImage() - This is NULL.\n", mImageIdName
));
577 Status
= EFI_INVALID_PARAMETER
;
582 // Retrieve the private context structure
584 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This
);
585 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
588 // Check to make sure index is 1 (only 1 image for this device)
590 if (ImageIndex
!= 1) {
591 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName
));
592 Status
= EFI_INVALID_PARAMETER
;
596 if (ImageSize
== NULL
) {
597 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName
));
598 Status
= EFI_INVALID_PARAMETER
;
603 // Check the buffer size
605 Status
= FmpDeviceGetSize (&Size
);
606 if (EFI_ERROR (Status
)) {
609 if (*ImageSize
< Size
) {
611 DEBUG ((DEBUG_VERBOSE
, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName
));
612 Status
= EFI_BUFFER_TOO_SMALL
;
617 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName
));
618 Status
= EFI_INVALID_PARAMETER
;
622 Status
= FmpDeviceGetImage (Image
, ImageSize
);
629 Helper function to safely retrieve the FMP header from
630 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
632 @param[in] Image Pointer to the image.
633 @param[in] ImageSize Size of the image.
634 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
635 @param[out] PayloadSize An optional pointer to a UINTN that holds the size of the payload
636 (image size minus headers)
638 @retval !NULL Valid pointer to the header.
639 @retval NULL Structure is bad and pointer cannot be found.
644 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION
*Image
,
645 IN CONST UINTN ImageSize
,
646 IN CONST UINTN AdditionalHeaderSize
,
647 OUT UINTN
*PayloadSize OPTIONAL
651 // Check to make sure that operation can be safely performed.
653 if (((UINTN
)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
) + AdditionalHeaderSize
< (UINTN
)Image
|| \
654 ((UINTN
)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
) + AdditionalHeaderSize
>= (UINTN
)Image
+ ImageSize
) {
656 // Pointer overflow. Invalid image.
661 if (PayloadSize
!= NULL
) {
662 *PayloadSize
= ImageSize
- (sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
+ AdditionalHeaderSize
);
665 return (VOID
*)((UINT8
*)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
+ AdditionalHeaderSize
);
669 Helper function to safely calculate the size of all headers
670 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
672 @param[in] Image Pointer to the image.
673 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
675 @retval UINT32>0 Valid size of all the headers.
676 @retval 0 Structure is bad and size cannot be found.
681 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION
*Image
,
682 IN UINT32 AdditionalHeaderSize
685 UINT32 CalculatedSize
;
688 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetAllHeaderSize() - Image is NULL.\n", mImageIdName
));
692 CalculatedSize
= sizeof (Image
->MonotonicCount
) +
693 AdditionalHeaderSize
+
694 Image
->AuthInfo
.Hdr
.dwLength
;
697 // Check to make sure that operation can be safely performed.
699 if (CalculatedSize
< sizeof (Image
->MonotonicCount
) ||
700 CalculatedSize
< AdditionalHeaderSize
||
701 CalculatedSize
< Image
->AuthInfo
.Hdr
.dwLength
) {
703 // Integer overflow. Invalid image.
708 return CalculatedSize
;
712 Checks if the firmware image is valid for the device.
714 This function allows firmware update application to validate the firmware image without
715 invoking the SetImage() first.
717 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
718 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
719 The number is between 1 and DescriptorCount.
720 @param[in] Image Points to the new image.
721 @param[in] ImageSize Size of the new image in bytes.
722 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
723 if available, additional information if the image is invalid.
724 @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt status to report
725 back to the ESRT table in case of error. If an error does not occur,
726 this function will set the value to LAST_ATTEMPT_STATUS_SUCCESS.
728 This function will return error codes that occur within this function
729 implementation within a driver range of last attempt error codes from
730 LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE
731 to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE.
733 This function might also return error codes that occur within libraries
734 linked against this module that return last attempt error codes such as:
736 LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE to
737 LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MAX_ERROR_CODE_VALUE
739 LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE to
740 LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MAX_ERROR_CODE_VALUE
742 @retval EFI_SUCCESS The image was successfully checked.
743 @retval EFI_ABORTED The operation is aborted.
744 @retval EFI_INVALID_PARAMETER The Image was NULL.
745 @retval EFI_UNSUPPORTED The operation is not supported.
746 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
751 CheckTheImageInternal (
752 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
754 IN CONST VOID
*Image
,
756 OUT UINT32
*ImageUpdatable
,
757 OUT UINT32
*LastAttemptStatus
761 UINT32 LocalLastAttemptStatus
;
762 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
764 VOID
*FmpPayloadHeader
;
765 UINTN FmpPayloadSize
;
767 UINT32 FmpHeaderSize
;
771 UINTN PublicKeyDataLength
;
772 UINT8
*PublicKeyDataXdr
;
773 UINT8
*PublicKeyDataXdrEnd
;
774 EFI_FIRMWARE_IMAGE_DEP
*Dependencies
;
775 UINT32 DependenciesSize
;
777 Status
= EFI_SUCCESS
;
778 LocalLastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
780 FmpPayloadHeader
= NULL
;
786 DependenciesSize
= 0;
788 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable
)) {
789 return EFI_UNSUPPORTED
;
792 if (LastAttemptStatus
== NULL
) {
793 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImageInternal() - LastAttemptStatus is NULL.\n", mImageIdName
));
794 Status
= EFI_INVALID_PARAMETER
;
799 // A last attempt status error code will always override the success
800 // value before returning from the function
802 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
805 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckImage() - This is NULL.\n", mImageIdName
));
806 Status
= EFI_INVALID_PARAMETER
;
807 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING
;
812 // Retrieve the private context structure
814 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This
);
815 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
818 // Make sure the descriptor has already been loaded or refreshed
820 PopulateDescriptor (Private
);
822 if (ImageUpdatable
== NULL
) {
823 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName
));
824 Status
= EFI_INVALID_PARAMETER
;
825 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE
;
830 //Set to valid and then if any tests fail it will update this flag.
832 *ImageUpdatable
= IMAGE_UPDATABLE_VALID
;
835 // Set to satisfied and then if dependency evaluates to false it will update this flag.
837 Private
->DependenciesSatisfied
= TRUE
;
840 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName
));
842 // not sure if this is needed
844 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
845 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED
;
846 return EFI_INVALID_PARAMETER
;
849 PublicKeyDataXdr
= PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr
);
850 PublicKeyDataXdrEnd
= PublicKeyDataXdr
+ PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr
);
852 if (PublicKeyDataXdr
== NULL
|| (PublicKeyDataXdr
== PublicKeyDataXdrEnd
)) {
853 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName
));
854 Status
= EFI_ABORTED
;
855 LocalLastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE
;
858 // Try each key from PcdFmpDevicePkcs7CertBufferXdr
860 for (Index
= 1; PublicKeyDataXdr
< PublicKeyDataXdrEnd
; Index
++) {
864 "FmpDxe(%s): Certificate #%d [%p..%p].\n",
872 if ((PublicKeyDataXdr
+ sizeof (UINT32
)) > PublicKeyDataXdrEnd
) {
874 // Key data extends beyond end of PCD
876 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName
));
877 Status
= EFI_ABORTED
;
878 LocalLastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE
;
882 // Read key length stored in big-endian format
884 PublicKeyDataLength
= SwapBytes32 (*(UINT32
*)(PublicKeyDataXdr
));
886 // Point to the start of the key data
888 PublicKeyDataXdr
+= sizeof (UINT32
);
889 if (PublicKeyDataXdr
+ PublicKeyDataLength
> PublicKeyDataXdrEnd
) {
891 // Key data extends beyond end of PCD
893 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName
));
894 Status
= EFI_ABORTED
;
895 LocalLastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH
;
898 PublicKeyData
= PublicKeyDataXdr
;
899 Status
= AuthenticateFmpImage (
900 (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
,
905 if (!EFI_ERROR (Status
)) {
908 PublicKeyDataXdr
+= PublicKeyDataLength
;
909 PublicKeyDataXdr
= (UINT8
*)ALIGN_POINTER (PublicKeyDataXdr
, sizeof (UINT32
));
913 if (EFI_ERROR (Status
)) {
914 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName
, Status
));
915 if (LocalLastAttemptStatus
!= LAST_ATTEMPT_STATUS_SUCCESS
) {
916 *LastAttemptStatus
= LocalLastAttemptStatus
;
918 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE
;
924 // Check to make sure index is 1
926 if (ImageIndex
!= 1) {
927 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName
));
928 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID_TYPE
;
929 Status
= EFI_INVALID_PARAMETER
;
930 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX
;
935 // Get the dependency from Image.
937 Dependencies
= GetImageDependency (
938 (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*) Image
,
943 if (*LastAttemptStatus
!= LAST_ATTEMPT_STATUS_SUCCESS
) {
944 Status
= EFI_ABORTED
;
949 // Check the FmpPayloadHeader
951 FmpPayloadHeader
= GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, DependenciesSize
, &FmpPayloadSize
);
952 if (FmpPayloadHeader
== NULL
) {
953 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName
));
954 Status
= EFI_ABORTED
;
955 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER
;
958 Status
= GetFmpPayloadHeaderVersion (FmpPayloadHeader
, FmpPayloadSize
, &Version
);
959 if (EFI_ERROR (Status
)) {
960 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName
, Status
));
961 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
962 Status
= EFI_SUCCESS
;
963 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION
;
968 // Check the lowest supported version
970 if (Version
< Private
->Descriptor
.LowestSupportedImageVersion
) {
973 "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
974 mImageIdName
, Version
, Private
->Descriptor
.LowestSupportedImageVersion
)
976 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID_OLD
;
977 Status
= EFI_SUCCESS
;
978 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW
;
983 // Evaluate dependency expression
985 Private
->DependenciesSatisfied
= CheckFmpDependency (
986 Private
->Descriptor
.ImageTypeId
,
990 &LocalLastAttemptStatus
992 if (!Private
->DependenciesSatisfied
) {
993 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName
));
994 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
995 Status
= EFI_SUCCESS
;
996 *LastAttemptStatus
= LocalLastAttemptStatus
;
1001 // Get the FmpHeaderSize so we can determine the real payload size
1003 Status
= GetFmpPayloadHeaderSize (FmpPayloadHeader
, FmpPayloadSize
, &FmpHeaderSize
);
1004 if (EFI_ERROR (Status
)) {
1005 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status
));
1006 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
1007 Status
= EFI_SUCCESS
;
1008 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE
;
1013 // Call FmpDevice Lib Check Image on the
1014 // Raw payload. So all headers need stripped off
1016 AllHeaderSize
= GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, FmpHeaderSize
+ DependenciesSize
);
1017 if (AllHeaderSize
== 0) {
1018 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName
));
1019 Status
= EFI_ABORTED
;
1020 *LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE
;
1023 RawSize
= ImageSize
- AllHeaderSize
;
1026 // FmpDeviceLib CheckImage function to do any specific checks
1028 Status
= FmpDeviceCheckImage ((((UINT8
*)Image
) + AllHeaderSize
), RawSize
, ImageUpdatable
);
1029 if (EFI_ERROR (Status
)) {
1030 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName
, Status
));
1038 Checks if the firmware image is valid for the device.
1040 This function allows firmware update application to validate the firmware image without
1041 invoking the SetImage() first.
1043 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1044 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
1045 The number is between 1 and DescriptorCount.
1046 @param[in] Image Points to the new image.
1047 @param[in] ImageSize Size of the new image in bytes.
1048 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
1049 if available, additional information if the image is invalid.
1051 @retval EFI_SUCCESS The image was successfully checked.
1052 @retval EFI_ABORTED The operation is aborted.
1053 @retval EFI_INVALID_PARAMETER The Image was NULL.
1054 @retval EFI_UNSUPPORTED The operation is not supported.
1055 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1061 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
1062 IN UINT8 ImageIndex
,
1063 IN CONST VOID
*Image
,
1065 OUT UINT32
*ImageUpdatable
1068 UINT32 LastAttemptStatus
;
1070 return CheckTheImageInternal (This
, ImageIndex
, Image
, ImageSize
, ImageUpdatable
, &LastAttemptStatus
);
1074 Updates the firmware image of the device.
1076 This function updates the hardware with the new firmware image.
1077 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
1078 If the firmware image is updatable, the function should perform the following minimal validations
1079 before proceeding to do the firmware image update.
1080 - Validate the image authentication if image has attribute
1081 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
1082 EFI_SECURITY_VIOLATION if the validation fails.
1083 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
1084 the image is unsupported. The function can optionally provide more detailed information on
1085 why the image is not a supported image.
1086 - Validate the data from VendorCode if not null. Image validation must be performed before
1087 VendorCode data validation. VendorCode data is ignored or considered invalid if image
1088 validation failed. The function returns EFI_ABORTED if the data is invalid.
1090 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
1091 the caller did not specify the policy or use the default policy. As an example, vendor can implement
1092 a policy to allow an option to force a firmware image update when the abort reason is due to the new
1093 firmware image version is older than the current firmware image version or bad image checksum.
1094 Sensitive operations such as those wiping the entire firmware image and render the device to be
1095 non-functional should be encoded in the image itself rather than passed with the VendorCode.
1096 AbortReason enables vendor to have the option to provide a more detailed description of the abort
1097 reason to the caller.
1099 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1100 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
1101 The number is between 1 and DescriptorCount.
1102 @param[in] Image Points to the new image.
1103 @param[in] ImageSize Size of the new image in bytes.
1104 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
1105 Null indicates the caller did not specify the policy or use the default policy.
1106 @param[in] Progress A function used by the driver to report the progress of the firmware update.
1107 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
1108 details for the aborted operation. The buffer is allocated by this function
1109 with AllocatePool(), and it is the caller's responsibility to free it with a
1112 @retval EFI_SUCCESS The device was successfully updated with the new image.
1113 @retval EFI_ABORTED The operation is aborted.
1114 @retval EFI_INVALID_PARAMETER The Image was NULL.
1115 @retval EFI_UNSUPPORTED The operation is not supported.
1116 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1122 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
1123 IN UINT8 ImageIndex
,
1124 IN CONST VOID
*Image
,
1126 IN CONST VOID
*VendorCode
,
1127 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress
,
1128 OUT CHAR16
**AbortReason
1132 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
1134 BOOLEAN BooleanValue
;
1135 UINT32 FmpHeaderSize
;
1137 UINTN FmpPayloadSize
;
1138 UINT32 AllHeaderSize
;
1139 UINT32 IncomingFwVersion
;
1140 UINT32 LastAttemptStatus
;
1142 UINT32 LowestSupportedVersion
;
1143 EFI_FIRMWARE_IMAGE_DEP
*Dependencies
;
1144 UINT32 DependenciesSize
;
1146 Status
= EFI_SUCCESS
;
1149 BooleanValue
= FALSE
;
1154 IncomingFwVersion
= 0;
1155 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1156 Dependencies
= NULL
;
1157 DependenciesSize
= 0;
1159 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable
)) {
1160 return EFI_UNSUPPORTED
;
1164 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - This is NULL.\n", mImageIdName
));
1165 Status
= EFI_INVALID_PARAMETER
;
1166 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING
;
1171 // Retrieve the private context structure
1173 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This
);
1174 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
1177 // Make sure the descriptor has already been loaded or refreshed
1179 PopulateDescriptor (Private
);
1182 // Set to 0 to clear any previous results.
1184 SetLastAttemptVersionInVariable (Private
, IncomingFwVersion
);
1187 // if we have locked the device, then skip the set operation.
1188 // it should be blocked by hardware too but we can catch here even faster
1190 if (Private
->FmpDeviceLocked
) {
1191 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName
));
1192 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED
;
1193 Status
= EFI_UNSUPPORTED
;
1198 // Call check image to verify the image
1200 Status
= CheckTheImageInternal (This
, ImageIndex
, Image
, ImageSize
, &Updateable
, &LastAttemptStatus
);
1201 if (EFI_ERROR (Status
)) {
1202 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName
, Status
));
1207 // Get the dependency from Image.
1209 Dependencies
= GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, &DependenciesSize
, &LastAttemptStatus
);
1212 // No functional error in CheckTheImage. Attempt to get the Version to
1213 // support better error reporting.
1215 FmpHeader
= GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, DependenciesSize
, &FmpPayloadSize
);
1216 if (FmpHeader
== NULL
) {
1217 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName
));
1218 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER
;
1219 Status
= EFI_ABORTED
;
1222 Status
= GetFmpPayloadHeaderVersion (FmpHeader
, FmpPayloadSize
, &IncomingFwVersion
);
1223 if (!EFI_ERROR (Status
)) {
1225 // Set to actual value
1227 SetLastAttemptVersionInVariable (Private
, IncomingFwVersion
);
1231 if (Updateable
!= IMAGE_UPDATABLE_VALID
) {
1234 "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
1235 mImageIdName
, Updateable
)
1237 if (Private
->DependenciesSatisfied
== FALSE
) {
1238 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES
;
1240 Status
= EFI_ABORTED
;
1244 if (Progress
== NULL
) {
1245 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName
));
1246 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR
;
1247 Status
= EFI_INVALID_PARAMETER
;
1251 mProgressFunc
= Progress
;
1254 // Checking the image is at least 1%
1256 Status
= Progress (1);
1257 if (EFI_ERROR (Status
)) {
1258 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName
, Status
));
1262 //Check System Power
1264 Status
= CheckSystemPower (&BooleanValue
);
1265 if (EFI_ERROR (Status
)) {
1266 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName
, Status
));
1267 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API
;
1270 if (!BooleanValue
) {
1271 Status
= EFI_ABORTED
;
1274 "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName
)
1276 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT
;
1283 //Check System Thermal
1285 Status
= CheckSystemThermal (&BooleanValue
);
1286 if (EFI_ERROR (Status
)) {
1287 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName
, Status
));
1288 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API
;
1291 if (!BooleanValue
) {
1292 Status
= EFI_ABORTED
;
1293 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL
;
1296 "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName
)
1304 //Check System Environment
1306 Status
= CheckSystemEnvironment (&BooleanValue
);
1307 if (EFI_ERROR (Status
)) {
1308 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName
, Status
));
1309 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API
;
1312 if (!BooleanValue
) {
1313 Status
= EFI_ABORTED
;
1314 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV
;
1317 "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName
)
1325 // Save LastAttemptStatus as error so that if SetImage never returns the error
1326 // state is recorded.
1328 SetLastAttemptStatusInVariable (Private
, LastAttemptStatus
);
1331 // Strip off all the headers so the device can process its firmware
1333 Status
= GetFmpPayloadHeaderSize (FmpHeader
, FmpPayloadSize
, &FmpHeaderSize
);
1334 if (EFI_ERROR (Status
)) {
1335 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName
, Status
));
1336 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE
;
1340 AllHeaderSize
= GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, FmpHeaderSize
+ DependenciesSize
);
1341 if (AllHeaderSize
== 0) {
1342 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName
));
1343 LastAttemptStatus
= LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE
;
1344 Status
= EFI_ABORTED
;
1349 // Indicate that control is handed off to FmpDeviceLib
1354 //Copy the requested image to the firmware using the FmpDeviceLib
1356 Status
= FmpDeviceSetImage (
1357 (((UINT8
*)Image
) + AllHeaderSize
),
1358 ImageSize
- AllHeaderSize
,
1364 if (EFI_ERROR (Status
)) {
1365 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName
, Status
));
1370 // Store the dependency
1372 if (Private
->Descriptor
.AttributesSetting
& IMAGE_ATTRIBUTE_DEPENDENCY
) {
1373 Status
= SaveFmpDependency (Dependencies
, DependenciesSize
);
1374 if (EFI_ERROR (Status
)) {
1375 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName
, Status
));
1377 Status
= EFI_SUCCESS
;
1381 // Finished the update without error
1382 // Indicate that control has been returned from FmpDeviceLib
1387 // Update the version stored in variable
1389 if (!Private
->RuntimeVersionSupported
) {
1390 Version
= DEFAULT_VERSION
;
1391 GetFmpPayloadHeaderVersion (FmpHeader
, FmpPayloadSize
, &Version
);
1392 SetVersionInVariable (Private
, Version
);
1396 // Update lowest supported variable
1398 LowestSupportedVersion
= DEFAULT_LOWESTSUPPORTEDVERSION
;
1399 GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader
, FmpPayloadSize
, &LowestSupportedVersion
);
1400 SetLowestSupportedVersionInVariable (Private
, LowestSupportedVersion
);
1402 LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1405 mProgressFunc
= NULL
;
1407 if (Private
!= NULL
) {
1408 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName
, LastAttemptStatus
));
1409 SetLastAttemptStatusInVariable (Private
, LastAttemptStatus
);
1412 if (Progress
!= NULL
) {
1414 // Set progress to 100 after everything is done including recording Status.
1420 // Need repopulate after SetImage is called to
1421 // update LastAttemptVersion and LastAttemptStatus.
1423 if (Private
!= NULL
) {
1424 Private
->DescriptorPopulated
= FALSE
;
1431 Returns information about the firmware package.
1433 This function returns package information.
1435 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1436 @param[out] PackageVersion A version number that represents all the firmware images in the device.
1437 The format is vendor specific and new version must have a greater value
1438 than the old version. If PackageVersion is not supported, the value is
1439 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
1440 comparison is to be performed using PackageVersionName. A value of
1441 0xFFFFFFFD indicates that package version update is in progress.
1442 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
1443 the package version name. The buffer is allocated by this function with
1444 AllocatePool(), and it is the caller's responsibility to free it with a
1446 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
1447 package version name. A value of 0 indicates the device does not support
1448 update of package version name. Length is the number of Unicode characters,
1449 including the terminating null character.
1450 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
1451 Definitions' for possible returned values of this parameter. A value of 1
1452 indicates the attribute is supported and the current setting value is
1453 indicated in AttributesSetting. A value of 0 indicates the attribute is not
1454 supported and the current setting value in AttributesSetting is meaningless.
1455 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
1456 values of this parameter
1458 @retval EFI_SUCCESS The package information was successfully returned.
1459 @retval EFI_UNSUPPORTED The operation is not supported.
1465 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
1466 OUT UINT32
*PackageVersion
,
1467 OUT CHAR16
**PackageVersionName
,
1468 OUT UINT32
*PackageVersionNameMaxLen
,
1469 OUT UINT64
*AttributesSupported
,
1470 OUT UINT64
*AttributesSetting
1473 return EFI_UNSUPPORTED
;
1477 Updates information about the firmware package.
1479 This function updates package information.
1480 This function returns EFI_UNSUPPORTED if the package information is not updatable.
1481 VendorCode enables vendor to implement vendor-specific package information update policy.
1482 Null if the caller did not specify this policy or use the default policy.
1484 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1485 @param[in] Image Points to the authentication image.
1486 Null if authentication is not required.
1487 @param[in] ImageSize Size of the authentication image in bytes.
1488 0 if authentication is not required.
1489 @param[in] VendorCode This enables vendor to implement vendor-specific firmware
1490 image update policy.
1491 Null indicates the caller did not specify this policy or use
1493 @param[in] PackageVersion The new package version.
1494 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
1495 the package version name.
1496 The string length is equal to or less than the value returned in
1497 PackageVersionNameMaxLen.
1499 @retval EFI_SUCCESS The device was successfully updated with the new package
1501 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
1502 returned in PackageVersionNameMaxLen.
1503 @retval EFI_UNSUPPORTED The operation is not supported.
1504 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1510 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
1511 IN CONST VOID
*Image
,
1513 IN CONST VOID
*VendorCode
,
1514 IN UINT32 PackageVersion
,
1515 IN CONST CHAR16
*PackageVersionName
1518 return EFI_UNSUPPORTED
;
1522 Event notification function that is invoked when the event GUID specified by
1523 PcdFmpDeviceLockEventGuid is signaled.
1525 @param[in] Event Event whose notification function is being invoked.
1526 @param[in] Context The pointer to the notification function's context,
1527 which is implementation-dependent.
1531 FmpDxeLockEventNotify (
1537 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
1539 if (Context
== NULL
) {
1540 ASSERT (Context
!= NULL
);
1544 Private
= (FIRMWARE_MANAGEMENT_PRIVATE_DATA
*)Context
;
1546 if (!Private
->FmpDeviceLocked
) {
1548 // Lock the firmware device
1550 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
1551 Status
= FmpDeviceLock();
1552 if (EFI_ERROR (Status
)) {
1553 if (Status
!= EFI_UNSUPPORTED
) {
1554 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName
, Status
));
1556 DEBUG ((DEBUG_WARN
, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName
, Status
));
1559 Private
->FmpDeviceLocked
= TRUE
;
1564 Function to install FMP instance.
1566 @param[in] Handle The device handle to install a FMP instance on.
1568 @retval EFI_SUCCESS FMP Installed
1569 @retval EFI_INVALID_PARAMETER Handle was invalid
1570 @retval other Error installing FMP
1575 InstallFmpInstance (
1576 IN EFI_HANDLE Handle
1580 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1581 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
1584 // Only allow a single FMP Protocol instance to be installed
1586 Status
= gBS
->OpenProtocol (
1588 &gEfiFirmwareManagementProtocolGuid
,
1592 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1594 if (!EFI_ERROR (Status
)) {
1595 return EFI_ALREADY_STARTED
;
1599 // Allocate FMP Protocol instance
1601 Private
= AllocateCopyPool (
1602 sizeof (mFirmwareManagementPrivateDataTemplate
),
1603 &mFirmwareManagementPrivateDataTemplate
1605 if (Private
== NULL
) {
1606 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName
));
1607 Status
= EFI_OUT_OF_RESOURCES
;
1612 // Initialize private context data structure
1614 Private
->Handle
= Handle
;
1615 Private
->FmpDeviceContext
= NULL
;
1616 Status
= FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
1617 if (Status
== EFI_UNSUPPORTED
) {
1618 Private
->FmpDeviceContext
= NULL
;
1619 } else if (EFI_ERROR (Status
)) {
1624 // Make sure the descriptor has already been loaded or refreshed
1626 PopulateDescriptor (Private
);
1628 if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
1630 // Register all UEFI Variables used by this module to be locked.
1632 Status
= LockAllFmpVariables (Private
);
1633 if (EFI_ERROR (Status
)) {
1634 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName
, Status
));
1636 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): All variables registered to lock\n", mImageIdName
));
1640 // Create and register notify function to lock the FMP device.
1642 Status
= gBS
->CreateEventEx (
1645 FmpDxeLockEventNotify
,
1648 &Private
->FmpDeviceLockEvent
1650 if (EFI_ERROR (Status
)) {
1651 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName
, Status
));
1653 ASSERT_EFI_ERROR (Status
);
1655 DEBUG ((DEBUG_VERBOSE
, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName
));
1659 // Install FMP Protocol and FMP Progress Protocol
1661 Status
= gBS
->InstallMultipleProtocolInterfaces (
1663 &gEfiFirmwareManagementProtocolGuid
, &Private
->Fmp
,
1664 &gEdkiiFirmwareManagementProgressProtocolGuid
, &mFmpProgress
,
1667 if (EFI_ERROR (Status
)) {
1668 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName
, Status
));
1674 if (EFI_ERROR (Status
)) {
1675 if (Private
!= NULL
) {
1676 if (Private
->FmpDeviceLockEvent
!= NULL
) {
1677 gBS
->CloseEvent (Private
->FmpDeviceLockEvent
);
1679 if (Private
->Descriptor
.VersionName
!= NULL
) {
1680 FreePool (Private
->Descriptor
.VersionName
);
1682 if (Private
->FmpDeviceContext
!= NULL
) {
1683 FmpDeviceSetContext (NULL
, &Private
->FmpDeviceContext
);
1685 if (Private
->VersionVariableName
!= NULL
) {
1686 FreePool (Private
->VersionVariableName
);
1688 if (Private
->LsvVariableName
!= NULL
) {
1689 FreePool (Private
->LsvVariableName
);
1691 if (Private
->LastAttemptStatusVariableName
!= NULL
) {
1692 FreePool (Private
->LastAttemptStatusVariableName
);
1694 if (Private
->LastAttemptVersionVariableName
!= NULL
) {
1695 FreePool (Private
->LastAttemptVersionVariableName
);
1697 if (Private
->FmpStateVariableName
!= NULL
) {
1698 FreePool (Private
->FmpStateVariableName
);
1708 Function to uninstall FMP instance.
1710 @param[in] Handle The device handle to install a FMP instance on.
1712 @retval EFI_SUCCESS FMP Installed
1713 @retval EFI_INVALID_PARAMETER Handle was invalid
1714 @retval other Error installing FMP
1719 UninstallFmpInstance (
1720 IN EFI_HANDLE Handle
1724 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1725 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
1727 Status
= gBS
->OpenProtocol (
1729 &gEfiFirmwareManagementProtocolGuid
,
1733 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1735 if (EFI_ERROR (Status
)) {
1736 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName
, Status
));
1740 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp
);
1741 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
1743 if (Private
->FmpDeviceLockEvent
!= NULL
) {
1744 gBS
->CloseEvent (Private
->FmpDeviceLockEvent
);
1747 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1749 &gEfiFirmwareManagementProtocolGuid
, &Private
->Fmp
,
1750 &gEdkiiFirmwareManagementProgressProtocolGuid
, &mFmpProgress
,
1753 if (EFI_ERROR (Status
)) {
1754 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName
, Status
));
1758 if (Private
->Descriptor
.VersionName
!= NULL
) {
1759 FreePool (Private
->Descriptor
.VersionName
);
1761 if (Private
->FmpDeviceContext
!= NULL
) {
1762 FmpDeviceSetContext (NULL
, &Private
->FmpDeviceContext
);
1764 if (Private
->VersionVariableName
!= NULL
) {
1765 FreePool (Private
->VersionVariableName
);
1767 if (Private
->LsvVariableName
!= NULL
) {
1768 FreePool (Private
->LsvVariableName
);
1770 if (Private
->LastAttemptStatusVariableName
!= NULL
) {
1771 FreePool (Private
->LastAttemptStatusVariableName
);
1773 if (Private
->LastAttemptVersionVariableName
!= NULL
) {
1774 FreePool (Private
->LastAttemptVersionVariableName
);
1776 if (Private
->FmpStateVariableName
!= NULL
) {
1777 FreePool (Private
->FmpStateVariableName
);
1785 Unloads the application and its installed protocol.
1787 @param ImageHandle Handle that identifies the image to be unloaded.
1788 @param SystemTable The system table.
1790 @retval EFI_SUCCESS The image has been unloaded.
1795 FmpDxeLibDestructor (
1796 IN EFI_HANDLE ImageHandle
,
1797 IN EFI_SYSTEM_TABLE
*SystemTable
1800 if (mFmpSingleInstance
) {
1801 return UninstallFmpInstance (ImageHandle
);
1807 Main entry for this driver/library.
1809 @param[in] ImageHandle Image handle this driver.
1810 @param[in] SystemTable Pointer to SystemTable.
1816 IN EFI_HANDLE ImageHandle
,
1817 IN EFI_SYSTEM_TABLE
*SystemTable
1823 // Verify that a new FILE_GUID value has been provided in the <Defines>
1824 // section of this module. The FILE_GUID is the ESRT GUID that must be
1825 // unique for each updatable firmware image.
1827 if (CompareGuid (&mDefaultModuleFileGuid
, &gEfiCallerIdGuid
)) {
1828 DEBUG ((DEBUG_ERROR
, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));
1830 return EFI_UNSUPPORTED
;
1834 // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.
1836 mImageIdName
= (CHAR16
*) PcdGetPtr (PcdFmpDeviceImageIdName
);
1837 if (PcdGetSize (PcdFmpDeviceImageIdName
) <= 2 || mImageIdName
[0] == 0) {
1839 // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
1841 DEBUG ((DEBUG_ERROR
, "FmpDxe(%g): PcdFmpDeviceImageIdName is an empty string.\n", &gEfiCallerIdGuid
));
1843 return EFI_UNSUPPORTED
;
1847 // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
1852 // Fill in FMP Progress Protocol fields for Version 1
1854 mFmpProgress
.Version
= 1;
1855 mFmpProgress
.ProgressBarForegroundColor
.Raw
= PcdGet32 (PcdFmpDeviceProgressColor
);
1856 mFmpProgress
.WatchdogSeconds
= PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds
);
1858 // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
1859 // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
1860 // gEfiEndOfDxeEventGroupGuid is used.
1862 mLockGuid
= &gEfiEndOfDxeEventGroupGuid
;
1863 if (PcdGetSize (PcdFmpDeviceLockEventGuid
) == sizeof (EFI_GUID
)) {
1864 mLockGuid
= (EFI_GUID
*)PcdGetPtr (PcdFmpDeviceLockEventGuid
);
1866 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName
, mLockGuid
));
1869 // Register with library the install function so if the library uses
1870 // UEFI driver model/driver binding protocol it can install FMP on its device handle
1871 // If library is simple lib that does not use driver binding then it should return
1872 // unsupported and this will install the FMP instance on the ImageHandle
1874 Status
= RegisterFmpInstaller (InstallFmpInstance
);
1875 if (Status
== EFI_UNSUPPORTED
) {
1876 mFmpSingleInstance
= TRUE
;
1877 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName
));
1878 Status
= RegisterFmpUninstaller (UninstallFmpInstance
);
1879 if (Status
== EFI_UNSUPPORTED
) {
1880 Status
= InstallFmpInstance (ImageHandle
);
1882 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName
));
1883 Status
= EFI_UNSUPPORTED
;
1885 } else if (EFI_ERROR (Status
)) {
1886 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName
, Status
));
1890 "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n",
1893 Status
= RegisterFmpUninstaller (UninstallFmpInstance
);
1894 if (EFI_ERROR (Status
)) {
1895 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName
));