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) 2016, Microsoft Corporation. All rights reserved.<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_INFO
, "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
->DescriptorPopulated
) {
285 Private
->Descriptor
.ImageIndex
= 1;
286 CopyGuid (&Private
->Descriptor
.ImageTypeId
, GetImageTypeIdGuid());
287 Private
->Descriptor
.ImageId
= Private
->Descriptor
.ImageIndex
;
288 Private
->Descriptor
.ImageIdName
= GetImageTypeNameString();
291 // Get the hardware instance from FmpDeviceLib
293 Status
= FmpDeviceGetHardwareInstance (&Private
->Descriptor
.HardwareInstance
);
294 if (Status
== EFI_UNSUPPORTED
) {
295 Private
->Descriptor
.HardwareInstance
= 0;
299 // Generate UEFI Variable names used to store status information for this
302 GenerateFmpVariableNames (Private
);
305 // Get the version. Some devices don't support getting the firmware version
306 // at runtime. If FmpDeviceLib does not support returning a version, then
307 // it is stored in a UEFI variable.
309 Status
= FmpDeviceGetVersion (&Private
->Descriptor
.Version
);
310 if (Status
== EFI_UNSUPPORTED
) {
311 Private
->RuntimeVersionSupported
= FALSE
;
312 Private
->Descriptor
.Version
= GetVersionFromVariable (Private
);
313 } else if (EFI_ERROR (Status
)) {
315 // Unexpected error. Use default version.
317 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName
, GetImageTypeNameString(), Status
));
318 Private
->Descriptor
.Version
= DEFAULT_VERSION
;
322 // Free the current version name. Shouldn't really happen but this populate
323 // function could be called multiple times (to refresh).
325 if (Private
->Descriptor
.VersionName
!= NULL
) {
326 FreePool (Private
->Descriptor
.VersionName
);
327 Private
->Descriptor
.VersionName
= NULL
;
331 // Attempt to get the version string from the FmpDeviceLib
333 Status
= FmpDeviceGetVersionString (&Private
->Descriptor
.VersionName
);
334 if (Status
== EFI_UNSUPPORTED
) {
335 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName
));
336 Private
->Descriptor
.VersionName
= AllocateCopyPool (
337 sizeof (VERSION_STRING_NOT_SUPPORTED
),
338 VERSION_STRING_NOT_SUPPORTED
340 } else if (EFI_ERROR (Status
)) {
341 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName
));
342 Private
->Descriptor
.VersionName
= AllocateCopyPool (
343 sizeof (VERSION_STRING_NOT_AVAILABLE
),
344 VERSION_STRING_NOT_AVAILABLE
348 Private
->Descriptor
.LowestSupportedImageVersion
= GetLowestSupportedVersion (Private
);
351 // Get attributes from the FmpDeviceLib
353 FmpDeviceGetAttributes (
354 &Private
->Descriptor
.AttributesSupported
,
355 &Private
->Descriptor
.AttributesSetting
359 // Force set the updatable bits in the attributes;
361 Private
->Descriptor
.AttributesSupported
|= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE
;
362 Private
->Descriptor
.AttributesSetting
|= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE
;
365 // Force set the authentication bits in the attributes;
367 Private
->Descriptor
.AttributesSupported
|= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED
);
368 Private
->Descriptor
.AttributesSetting
|= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED
);
370 Private
->Descriptor
.Compatibilities
= 0;
373 // Get the size of the firmware image from the FmpDeviceLib
375 Status
= FmpDeviceGetSize (&Private
->Descriptor
.Size
);
376 if (EFI_ERROR (Status
)) {
377 Private
->Descriptor
.Size
= 0;
380 Private
->Descriptor
.LastAttemptVersion
= GetLastAttemptVersionFromVariable (Private
);
381 Private
->Descriptor
.LastAttemptStatus
= GetLastAttemptStatusFromVariable (Private
);
384 // Get the dependency from the FmpDependencyDeviceLib.
386 Private
->Descriptor
.Dependencies
= NULL
;
389 // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
391 if (Private
->Descriptor
.AttributesSetting
& IMAGE_ATTRIBUTE_DEPENDENCY
) {
392 Private
->Descriptor
.Dependencies
= GetFmpDependency (&DependenciesSize
);
395 Private
->DescriptorPopulated
= TRUE
;
399 Returns information about the current firmware image(s) of the device.
401 This function allows a copy of the current firmware image to be created and saved.
402 The saved copy could later been used, for example, in firmware image recovery or rollback.
404 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
405 @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
406 On input, this is the size of the buffer allocated by the caller.
407 On output, it is the size of the buffer returned by the firmware
408 if the buffer was large enough, or the size of the buffer needed
409 to contain the image(s) information if the buffer was too small.
410 @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
411 information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
412 @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
413 associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
414 @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
415 descriptors or firmware images within this device.
416 @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
417 of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
418 @param[out] PackageVersion A version number that represents all the firmware images in the device.
419 The format is vendor specific and new version must have a greater value
420 than the old version. If PackageVersion is not supported, the value is
421 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
422 is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
423 that package version update is in progress.
424 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
425 package version name. The buffer is allocated by this function with
426 AllocatePool(), and it is the caller's responsibility to free it with a call
429 @retval EFI_SUCCESS The device was successfully updated with the new image.
430 @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
431 needed to hold the image(s) information is returned in ImageInfoSize.
432 @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
433 @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
439 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
440 IN OUT UINTN
*ImageInfoSize
,
441 IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
442 OUT UINT32
*DescriptorVersion
,
443 OUT UINT8
*DescriptorCount
,
444 OUT UINTN
*DescriptorSize
,
445 OUT UINT32
*PackageVersion
,
446 OUT CHAR16
**PackageVersionName
450 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
452 Status
= EFI_SUCCESS
;
455 // Retrieve the private context structure
457 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This
);
458 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
461 // Check for valid pointer
463 if (ImageInfoSize
== NULL
) {
464 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName
));
465 Status
= EFI_INVALID_PARAMETER
;
470 // Check the buffer size
471 // NOTE: Check this first so caller can get the necessary memory size it must allocate.
473 if (*ImageInfoSize
< (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
))) {
474 *ImageInfoSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
475 DEBUG ((DEBUG_VERBOSE
, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName
));
476 Status
= EFI_BUFFER_TOO_SMALL
;
481 // Confirm that buffer isn't null
483 if ( (ImageInfo
== NULL
) || (DescriptorVersion
== NULL
) || (DescriptorCount
== NULL
) || (DescriptorSize
== NULL
)
484 || (PackageVersion
== NULL
)) {
485 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName
));
486 Status
= EFI_INVALID_PARAMETER
;
491 // Set the size to whatever we need
493 *ImageInfoSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
496 // Make sure the descriptor has already been loaded or refreshed
498 PopulateDescriptor (Private
);
501 // Copy the image descriptor
503 CopyMem (ImageInfo
, &Private
->Descriptor
, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
));
505 *DescriptorVersion
= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
;
506 *DescriptorCount
= 1;
507 *DescriptorSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
511 *PackageVersion
= 0xFFFFFFFF;
514 // Do not update PackageVersionName since it is not supported in this instance.
523 Retrieves a copy of the current firmware image of the device.
525 This function allows a copy of the current firmware image to be created and saved.
526 The saved copy could later been used, for example, in firmware image recovery or rollback.
528 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
529 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
530 The number is between 1 and DescriptorCount.
531 @param[in, out] Image Points to the buffer where the current image is copied to.
532 @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
533 On return, points to the length of the image, in bytes.
535 @retval EFI_SUCCESS The device was successfully updated with the new image.
536 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
537 image. The current buffer size needed to hold the image is returned
539 @retval EFI_INVALID_PARAMETER The Image was NULL.
540 @retval EFI_NOT_FOUND The current image is not copied to the buffer.
541 @retval EFI_UNSUPPORTED The operation is not supported.
542 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
548 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
551 IN OUT UINTN
*ImageSize
555 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
558 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable
)) {
559 return EFI_UNSUPPORTED
;
562 Status
= EFI_SUCCESS
;
565 // Retrieve the private context structure
567 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This
);
568 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
571 // Check to make sure index is 1 (only 1 image for this device)
573 if (ImageIndex
!= 1) {
574 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName
));
575 Status
= EFI_INVALID_PARAMETER
;
579 if (ImageSize
== NULL
) {
580 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName
));
581 Status
= EFI_INVALID_PARAMETER
;
586 // Check the buffer size
588 Status
= FmpDeviceGetSize (&Size
);
589 if (EFI_ERROR (Status
)) {
592 if (*ImageSize
< Size
) {
594 DEBUG ((DEBUG_VERBOSE
, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName
));
595 Status
= EFI_BUFFER_TOO_SMALL
;
600 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName
));
601 Status
= EFI_INVALID_PARAMETER
;
605 Status
= FmpDeviceGetImage (Image
, ImageSize
);
612 Helper function to safely retrieve the FMP header from
613 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
615 @param[in] Image Pointer to the image.
616 @param[in] ImageSize Size of the image.
617 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
618 @param[out] PayloadSize
620 @retval !NULL Valid pointer to the header.
621 @retval NULL Structure is bad and pointer cannot be found.
626 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION
*Image
,
627 IN CONST UINTN ImageSize
,
628 IN CONST UINTN AdditionalHeaderSize
,
629 OUT UINTN
*PayloadSize
633 // Check to make sure that operation can be safely performed.
635 if (((UINTN
)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
) + AdditionalHeaderSize
< (UINTN
)Image
|| \
636 ((UINTN
)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
) + AdditionalHeaderSize
>= (UINTN
)Image
+ ImageSize
) {
638 // Pointer overflow. Invalid image.
643 *PayloadSize
= ImageSize
- (sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
+ AdditionalHeaderSize
);
644 return (VOID
*)((UINT8
*)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
+ AdditionalHeaderSize
);
648 Helper function to safely calculate the size of all headers
649 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
651 @param[in] Image Pointer to the image.
652 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
654 @retval UINT32>0 Valid size of all the headers.
655 @retval 0 Structure is bad and size cannot be found.
660 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION
*Image
,
661 IN UINT32 AdditionalHeaderSize
664 UINT32 CalculatedSize
;
666 CalculatedSize
= sizeof (Image
->MonotonicCount
) +
667 AdditionalHeaderSize
+
668 Image
->AuthInfo
.Hdr
.dwLength
;
671 // Check to make sure that operation can be safely performed.
673 if (CalculatedSize
< sizeof (Image
->MonotonicCount
) ||
674 CalculatedSize
< AdditionalHeaderSize
||
675 CalculatedSize
< Image
->AuthInfo
.Hdr
.dwLength
) {
677 // Integer overflow. Invalid image.
682 return CalculatedSize
;
686 Checks if the firmware image is valid for the device.
688 This function allows firmware update application to validate the firmware image without
689 invoking the SetImage() first.
691 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
692 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
693 The number is between 1 and DescriptorCount.
694 @param[in] Image Points to the new image.
695 @param[in] ImageSize Size of the new image in bytes.
696 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
697 if available, additional information if the image is invalid.
699 @retval EFI_SUCCESS The image was successfully checked.
700 @retval EFI_ABORTED The operation is aborted.
701 @retval EFI_INVALID_PARAMETER The Image was NULL.
702 @retval EFI_UNSUPPORTED The operation is not supported.
703 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
709 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
711 IN CONST VOID
*Image
,
713 OUT UINT32
*ImageUpdatable
717 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
719 VOID
*FmpPayloadHeader
;
720 UINTN FmpPayloadSize
;
722 UINT32 FmpHeaderSize
;
726 UINTN PublicKeyDataLength
;
727 UINT8
*PublicKeyDataXdr
;
728 UINT8
*PublicKeyDataXdrEnd
;
729 EFI_FIRMWARE_IMAGE_DEP
*Dependencies
;
730 UINT32 DependenciesSize
;
732 Status
= EFI_SUCCESS
;
734 FmpPayloadHeader
= NULL
;
740 DependenciesSize
= 0;
742 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable
)) {
743 return EFI_UNSUPPORTED
;
747 // Retrieve the private context structure
749 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This
);
750 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
753 // Make sure the descriptor has already been loaded or refreshed
755 PopulateDescriptor (Private
);
757 if (ImageUpdatable
== NULL
) {
758 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName
));
759 Status
= EFI_INVALID_PARAMETER
;
764 //Set to valid and then if any tests fail it will update this flag.
766 *ImageUpdatable
= IMAGE_UPDATABLE_VALID
;
769 // Set to satisfied and then if dependency evaluates to false it will update this flag.
771 Private
->DependenciesSatisfied
= TRUE
;
774 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName
));
776 // not sure if this is needed
778 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
779 return EFI_INVALID_PARAMETER
;
782 PublicKeyDataXdr
= PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr
);
783 PublicKeyDataXdrEnd
= PublicKeyDataXdr
+ PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr
);
785 if (PublicKeyDataXdr
== NULL
|| (PublicKeyDataXdr
== PublicKeyDataXdrEnd
)) {
786 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName
));
787 Status
= EFI_ABORTED
;
790 // Try each key from PcdFmpDevicePkcs7CertBufferXdr
792 for (Index
= 1; PublicKeyDataXdr
< PublicKeyDataXdrEnd
; Index
++) {
796 "FmpDxe(%s): Certificate #%d [%p..%p].\n",
804 if ((PublicKeyDataXdr
+ sizeof (UINT32
)) > PublicKeyDataXdrEnd
) {
806 // Key data extends beyond end of PCD
808 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName
));
809 Status
= EFI_ABORTED
;
813 // Read key length stored in big-endian format
815 PublicKeyDataLength
= SwapBytes32 (*(UINT32
*)(PublicKeyDataXdr
));
817 // Point to the start of the key data
819 PublicKeyDataXdr
+= sizeof (UINT32
);
820 if (PublicKeyDataXdr
+ PublicKeyDataLength
> PublicKeyDataXdrEnd
) {
822 // Key data extends beyond end of PCD
824 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName
));
825 Status
= EFI_ABORTED
;
828 PublicKeyData
= PublicKeyDataXdr
;
829 Status
= AuthenticateFmpImage (
830 (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
,
835 if (!EFI_ERROR (Status
)) {
838 PublicKeyDataXdr
+= PublicKeyDataLength
;
839 PublicKeyDataXdr
= (UINT8
*)ALIGN_POINTER (PublicKeyDataXdr
, sizeof (UINT32
));
843 if (EFI_ERROR (Status
)) {
844 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName
, Status
));
849 // Check to make sure index is 1
851 if (ImageIndex
!= 1) {
852 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName
));
853 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID_TYPE
;
854 Status
= EFI_SUCCESS
;
859 // Get the dependency from Image.
861 Dependencies
= GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, &DependenciesSize
);
864 // Check the FmpPayloadHeader
866 FmpPayloadHeader
= GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, DependenciesSize
, &FmpPayloadSize
);
867 if (FmpPayloadHeader
== NULL
) {
868 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName
));
869 Status
= EFI_ABORTED
;
872 Status
= GetFmpPayloadHeaderVersion (FmpPayloadHeader
, FmpPayloadSize
, &Version
);
873 if (EFI_ERROR (Status
)) {
874 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName
, Status
));
875 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
876 Status
= EFI_SUCCESS
;
881 // Check the lowest supported version
883 if (Version
< Private
->Descriptor
.LowestSupportedImageVersion
) {
886 "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
887 mImageIdName
, Version
, Private
->Descriptor
.LowestSupportedImageVersion
)
889 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID_OLD
;
890 Status
= EFI_SUCCESS
;
895 // Evaluate dependency expression
897 Private
->DependenciesSatisfied
= CheckFmpDependency (Private
->Descriptor
.ImageTypeId
, Version
, Dependencies
, DependenciesSize
);
898 if (!Private
->DependenciesSatisfied
) {
899 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName
));
900 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
901 Status
= EFI_SUCCESS
;
906 // Get the FmpHeaderSize so we can determine the real payload size
908 Status
= GetFmpPayloadHeaderSize (FmpPayloadHeader
, FmpPayloadSize
, &FmpHeaderSize
);
909 if (EFI_ERROR (Status
)) {
910 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status
));
911 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
912 Status
= EFI_SUCCESS
;
917 // Call FmpDevice Lib Check Image on the
918 // Raw payload. So all headers need stripped off
920 AllHeaderSize
= GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, FmpHeaderSize
+ DependenciesSize
);
921 if (AllHeaderSize
== 0) {
922 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName
));
923 Status
= EFI_ABORTED
;
926 RawSize
= ImageSize
- AllHeaderSize
;
929 // FmpDeviceLib CheckImage function to do any specific checks
931 Status
= FmpDeviceCheckImage ((((UINT8
*)Image
) + AllHeaderSize
), RawSize
, ImageUpdatable
);
932 if (EFI_ERROR (Status
)) {
933 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName
, Status
));
941 Updates the firmware image of the device.
943 This function updates the hardware with the new firmware image.
944 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
945 If the firmware image is updatable, the function should perform the following minimal validations
946 before proceeding to do the firmware image update.
947 - Validate the image authentication if image has attribute
948 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
949 EFI_SECURITY_VIOLATION if the validation fails.
950 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
951 the image is unsupported. The function can optionally provide more detailed information on
952 why the image is not a supported image.
953 - Validate the data from VendorCode if not null. Image validation must be performed before
954 VendorCode data validation. VendorCode data is ignored or considered invalid if image
955 validation failed. The function returns EFI_ABORTED if the data is invalid.
957 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
958 the caller did not specify the policy or use the default policy. As an example, vendor can implement
959 a policy to allow an option to force a firmware image update when the abort reason is due to the new
960 firmware image version is older than the current firmware image version or bad image checksum.
961 Sensitive operations such as those wiping the entire firmware image and render the device to be
962 non-functional should be encoded in the image itself rather than passed with the VendorCode.
963 AbortReason enables vendor to have the option to provide a more detailed description of the abort
964 reason to the caller.
966 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
967 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
968 The number is between 1 and DescriptorCount.
969 @param[in] Image Points to the new image.
970 @param[in] ImageSize Size of the new image in bytes.
971 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
972 Null indicates the caller did not specify the policy or use the default policy.
973 @param[in] Progress A function used by the driver to report the progress of the firmware update.
974 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
975 details for the aborted operation. The buffer is allocated by this function
976 with AllocatePool(), and it is the caller's responsibility to free it with a
979 @retval EFI_SUCCESS The device was successfully updated with the new image.
980 @retval EFI_ABORTED The operation is aborted.
981 @retval EFI_INVALID_PARAMETER The Image was NULL.
982 @retval EFI_UNSUPPORTED The operation is not supported.
983 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
989 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
991 IN CONST VOID
*Image
,
993 IN CONST VOID
*VendorCode
,
994 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress
,
995 OUT CHAR16
**AbortReason
999 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
1001 BOOLEAN BooleanValue
;
1002 UINT32 FmpHeaderSize
;
1004 UINTN FmpPayloadSize
;
1005 UINT32 AllHeaderSize
;
1006 UINT32 IncomingFwVersion
;
1007 UINT32 LastAttemptStatus
;
1009 UINT32 LowestSupportedVersion
;
1010 EFI_FIRMWARE_IMAGE_DEP
*Dependencies
;
1011 UINT32 DependenciesSize
;
1013 Status
= EFI_SUCCESS
;
1015 BooleanValue
= FALSE
;
1020 IncomingFwVersion
= 0;
1021 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1022 Dependencies
= NULL
;
1023 DependenciesSize
= 0;
1025 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable
)) {
1026 return EFI_UNSUPPORTED
;
1030 // Retrieve the private context structure
1032 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This
);
1033 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
1036 // Make sure the descriptor has already been loaded or refreshed
1038 PopulateDescriptor (Private
);
1041 // Set to 0 to clear any previous results.
1043 SetLastAttemptVersionInVariable (Private
, IncomingFwVersion
);
1046 // if we have locked the device, then skip the set operation.
1047 // it should be blocked by hardware too but we can catch here even faster
1049 if (Private
->FmpDeviceLocked
) {
1050 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName
));
1051 Status
= EFI_UNSUPPORTED
;
1056 // Call check image to verify the image
1058 Status
= CheckTheImage (This
, ImageIndex
, Image
, ImageSize
, &Updateable
);
1059 if (EFI_ERROR (Status
)) {
1060 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName
, Status
));
1061 if (Status
== EFI_SECURITY_VIOLATION
) {
1062 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR
;
1068 // Get the dependency from Image.
1070 Dependencies
= GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, &DependenciesSize
);
1073 // No functional error in CheckTheImage. Attempt to get the Version to
1074 // support better error reporting.
1076 FmpHeader
= GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, DependenciesSize
, &FmpPayloadSize
);
1077 if (FmpHeader
== NULL
) {
1078 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName
));
1079 Status
= EFI_ABORTED
;
1082 Status
= GetFmpPayloadHeaderVersion (FmpHeader
, FmpPayloadSize
, &IncomingFwVersion
);
1083 if (!EFI_ERROR (Status
)) {
1085 // Set to actual value
1087 SetLastAttemptVersionInVariable (Private
, IncomingFwVersion
);
1091 if (Updateable
!= IMAGE_UPDATABLE_VALID
) {
1094 "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
1095 mImageIdName
, Updateable
)
1097 if (Private
->DependenciesSatisfied
== FALSE
) {
1098 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES
;
1100 Status
= EFI_ABORTED
;
1104 if (Progress
== NULL
) {
1105 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName
));
1106 Status
= EFI_INVALID_PARAMETER
;
1110 mProgressFunc
= Progress
;
1113 // Checking the image is at least 1%
1115 Status
= Progress (1);
1116 if (EFI_ERROR (Status
)) {
1117 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName
, Status
));
1121 //Check System Power
1123 Status
= CheckSystemPower (&BooleanValue
);
1124 if (EFI_ERROR (Status
)) {
1125 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName
, Status
));
1128 if (!BooleanValue
) {
1129 Status
= EFI_ABORTED
;
1132 "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName
)
1134 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT
;
1141 //Check System Thermal
1143 Status
= CheckSystemThermal (&BooleanValue
);
1144 if (EFI_ERROR (Status
)) {
1145 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName
, Status
));
1148 if (!BooleanValue
) {
1149 Status
= EFI_ABORTED
;
1152 "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName
)
1160 //Check System Environment
1162 Status
= CheckSystemEnvironment (&BooleanValue
);
1163 if (EFI_ERROR (Status
)) {
1164 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName
, Status
));
1167 if (!BooleanValue
) {
1168 Status
= EFI_ABORTED
;
1171 "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName
)
1179 // Save LastAttemptStatus as error so that if SetImage never returns the error
1180 // state is recorded.
1182 SetLastAttemptStatusInVariable (Private
, LastAttemptStatus
);
1185 // Strip off all the headers so the device can process its firmware
1187 Status
= GetFmpPayloadHeaderSize (FmpHeader
, FmpPayloadSize
, &FmpHeaderSize
);
1188 if (EFI_ERROR (Status
)) {
1189 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName
, Status
));
1193 AllHeaderSize
= GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, FmpHeaderSize
+ DependenciesSize
);
1194 if (AllHeaderSize
== 0) {
1195 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName
));
1196 Status
= EFI_ABORTED
;
1201 // Indicate that control is handed off to FmpDeviceLib
1206 //Copy the requested image to the firmware using the FmpDeviceLib
1208 Status
= FmpDeviceSetImage (
1209 (((UINT8
*)Image
) + AllHeaderSize
),
1210 ImageSize
- AllHeaderSize
,
1216 if (EFI_ERROR (Status
)) {
1217 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName
, Status
));
1222 // Store the dependency
1224 if (Private
->Descriptor
.AttributesSetting
& IMAGE_ATTRIBUTE_DEPENDENCY
) {
1225 Status
= SaveFmpDependency (Dependencies
, DependenciesSize
);
1226 if (EFI_ERROR (Status
)) {
1227 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName
, Status
));
1229 Status
= EFI_SUCCESS
;
1233 // Finished the update without error
1234 // Indicate that control has been returned from FmpDeviceLib
1239 // Update the version stored in variable
1241 if (!Private
->RuntimeVersionSupported
) {
1242 Version
= DEFAULT_VERSION
;
1243 GetFmpPayloadHeaderVersion (FmpHeader
, FmpPayloadSize
, &Version
);
1244 SetVersionInVariable (Private
, Version
);
1248 // Update lowest supported variable
1250 LowestSupportedVersion
= DEFAULT_LOWESTSUPPORTEDVERSION
;
1251 GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader
, FmpPayloadSize
, &LowestSupportedVersion
);
1252 SetLowestSupportedVersionInVariable (Private
, LowestSupportedVersion
);
1254 LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1257 mProgressFunc
= NULL
;
1258 SetLastAttemptStatusInVariable (Private
, LastAttemptStatus
);
1260 if (Progress
!= NULL
) {
1262 // Set progress to 100 after everything is done including recording Status.
1268 // Need repopulate after SetImage is called to
1269 // update LastAttemptVersion and LastAttemptStatus.
1271 Private
->DescriptorPopulated
= FALSE
;
1277 Returns information about the firmware package.
1279 This function returns package information.
1281 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1282 @param[out] PackageVersion A version number that represents all the firmware images in the device.
1283 The format is vendor specific and new version must have a greater value
1284 than the old version. If PackageVersion is not supported, the value is
1285 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
1286 comparison is to be performed using PackageVersionName. A value of
1287 0xFFFFFFFD indicates that package version update is in progress.
1288 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
1289 the package version name. The buffer is allocated by this function with
1290 AllocatePool(), and it is the caller's responsibility to free it with a
1292 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
1293 package version name. A value of 0 indicates the device does not support
1294 update of package version name. Length is the number of Unicode characters,
1295 including the terminating null character.
1296 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
1297 Definitions' for possible returned values of this parameter. A value of 1
1298 indicates the attribute is supported and the current setting value is
1299 indicated in AttributesSetting. A value of 0 indicates the attribute is not
1300 supported and the current setting value in AttributesSetting is meaningless.
1301 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
1302 values of this parameter
1304 @retval EFI_SUCCESS The package information was successfully returned.
1305 @retval EFI_UNSUPPORTED The operation is not supported.
1311 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
1312 OUT UINT32
*PackageVersion
,
1313 OUT CHAR16
**PackageVersionName
,
1314 OUT UINT32
*PackageVersionNameMaxLen
,
1315 OUT UINT64
*AttributesSupported
,
1316 OUT UINT64
*AttributesSetting
1319 return EFI_UNSUPPORTED
;
1323 Updates information about the firmware package.
1325 This function updates package information.
1326 This function returns EFI_UNSUPPORTED if the package information is not updatable.
1327 VendorCode enables vendor to implement vendor-specific package information update policy.
1328 Null if the caller did not specify this policy or use the default policy.
1330 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1331 @param[in] Image Points to the authentication image.
1332 Null if authentication is not required.
1333 @param[in] ImageSize Size of the authentication image in bytes.
1334 0 if authentication is not required.
1335 @param[in] VendorCode This enables vendor to implement vendor-specific firmware
1336 image update policy.
1337 Null indicates the caller did not specify this policy or use
1339 @param[in] PackageVersion The new package version.
1340 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
1341 the package version name.
1342 The string length is equal to or less than the value returned in
1343 PackageVersionNameMaxLen.
1345 @retval EFI_SUCCESS The device was successfully updated with the new package
1347 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
1348 returned in PackageVersionNameMaxLen.
1349 @retval EFI_UNSUPPORTED The operation is not supported.
1350 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1356 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
1357 IN CONST VOID
*Image
,
1359 IN CONST VOID
*VendorCode
,
1360 IN UINT32 PackageVersion
,
1361 IN CONST CHAR16
*PackageVersionName
1364 return EFI_UNSUPPORTED
;
1368 Event notification function that is invoked when the event GUID specified by
1369 PcdFmpDeviceLockEventGuid is signaled.
1371 @param[in] Event Event whose notification function is being invoked.
1372 @param[in] Context The pointer to the notification function's context,
1373 which is implementation-dependent.
1377 FmpDxeLockEventNotify (
1383 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
1385 Private
= (FIRMWARE_MANAGEMENT_PRIVATE_DATA
*)Context
;
1387 if (!Private
->FmpDeviceLocked
) {
1389 // Lock the firmware device
1391 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
1392 Status
= FmpDeviceLock();
1393 if (EFI_ERROR (Status
)) {
1394 if (Status
!= EFI_UNSUPPORTED
) {
1395 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName
, Status
));
1397 DEBUG ((DEBUG_WARN
, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName
, Status
));
1400 Private
->FmpDeviceLocked
= TRUE
;
1405 Function to install FMP instance.
1407 @param[in] Handle The device handle to install a FMP instance on.
1409 @retval EFI_SUCCESS FMP Installed
1410 @retval EFI_INVALID_PARAMETER Handle was invalid
1411 @retval other Error installing FMP
1416 InstallFmpInstance (
1417 IN EFI_HANDLE Handle
1421 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1422 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
1425 // Only allow a single FMP Protocol instance to be installed
1427 Status
= gBS
->OpenProtocol (
1429 &gEfiFirmwareManagementProtocolGuid
,
1433 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1435 if (!EFI_ERROR (Status
)) {
1436 return EFI_ALREADY_STARTED
;
1440 // Allocate FMP Protocol instance
1442 Private
= AllocateCopyPool (
1443 sizeof (mFirmwareManagementPrivateDataTemplate
),
1444 &mFirmwareManagementPrivateDataTemplate
1446 if (Private
== NULL
) {
1447 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName
));
1448 Status
= EFI_OUT_OF_RESOURCES
;
1453 // Initialize private context data structure
1455 Private
->Handle
= Handle
;
1456 Private
->FmpDeviceContext
= NULL
;
1457 Status
= FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
1458 if (Status
== EFI_UNSUPPORTED
) {
1459 Private
->FmpDeviceContext
= NULL
;
1460 } else if (EFI_ERROR (Status
)) {
1465 // Make sure the descriptor has already been loaded or refreshed
1467 PopulateDescriptor (Private
);
1469 if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
1471 // Register all UEFI Variables used by this module to be locked.
1473 Status
= LockAllFmpVariables (Private
);
1474 if (EFI_ERROR (Status
)) {
1475 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName
, Status
));
1477 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): All variables registered to lock\n", mImageIdName
));
1481 // Create and register notify function to lock the FMP device.
1483 Status
= gBS
->CreateEventEx (
1486 FmpDxeLockEventNotify
,
1489 &Private
->FmpDeviceLockEvent
1491 if (EFI_ERROR (Status
)) {
1492 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName
, Status
));
1494 ASSERT_EFI_ERROR (Status
);
1496 DEBUG ((DEBUG_VERBOSE
, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName
));
1500 // Install FMP Protocol and FMP Progress Protocol
1502 Status
= gBS
->InstallMultipleProtocolInterfaces (
1504 &gEfiFirmwareManagementProtocolGuid
, &Private
->Fmp
,
1505 &gEdkiiFirmwareManagementProgressProtocolGuid
, &mFmpProgress
,
1508 if (EFI_ERROR (Status
)) {
1509 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName
, Status
));
1515 if (EFI_ERROR (Status
)) {
1516 if (Private
!= NULL
) {
1517 if (Private
->FmpDeviceLockEvent
!= NULL
) {
1518 gBS
->CloseEvent (Private
->FmpDeviceLockEvent
);
1520 if (Private
->Descriptor
.VersionName
!= NULL
) {
1521 FreePool (Private
->Descriptor
.VersionName
);
1523 if (Private
->FmpDeviceContext
!= NULL
) {
1524 FmpDeviceSetContext (NULL
, &Private
->FmpDeviceContext
);
1526 if (Private
->VersionVariableName
!= NULL
) {
1527 FreePool (Private
->VersionVariableName
);
1529 if (Private
->LsvVariableName
!= NULL
) {
1530 FreePool (Private
->LsvVariableName
);
1532 if (Private
->LastAttemptStatusVariableName
!= NULL
) {
1533 FreePool (Private
->LastAttemptStatusVariableName
);
1535 if (Private
->LastAttemptVersionVariableName
!= NULL
) {
1536 FreePool (Private
->LastAttemptVersionVariableName
);
1538 if (Private
->FmpStateVariableName
!= NULL
) {
1539 FreePool (Private
->FmpStateVariableName
);
1549 Function to uninstall FMP instance.
1551 @param[in] Handle The device handle to install a FMP instance on.
1553 @retval EFI_SUCCESS FMP Installed
1554 @retval EFI_INVALID_PARAMETER Handle was invalid
1555 @retval other Error installing FMP
1560 UninstallFmpInstance (
1561 IN EFI_HANDLE Handle
1565 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1566 FIRMWARE_MANAGEMENT_PRIVATE_DATA
*Private
;
1568 Status
= gBS
->OpenProtocol (
1570 &gEfiFirmwareManagementProtocolGuid
,
1574 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1576 if (EFI_ERROR (Status
)) {
1577 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName
, Status
));
1581 Private
= FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp
);
1582 FmpDeviceSetContext (Private
->Handle
, &Private
->FmpDeviceContext
);
1584 if (Private
->FmpDeviceLockEvent
!= NULL
) {
1585 gBS
->CloseEvent (Private
->FmpDeviceLockEvent
);
1588 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1590 &gEfiFirmwareManagementProtocolGuid
, &Private
->Fmp
,
1591 &gEdkiiFirmwareManagementProgressProtocolGuid
, &mFmpProgress
,
1594 if (EFI_ERROR (Status
)) {
1595 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName
, Status
));
1599 if (Private
->Descriptor
.VersionName
!= NULL
) {
1600 FreePool (Private
->Descriptor
.VersionName
);
1602 if (Private
->FmpDeviceContext
!= NULL
) {
1603 FmpDeviceSetContext (NULL
, &Private
->FmpDeviceContext
);
1605 if (Private
->VersionVariableName
!= NULL
) {
1606 FreePool (Private
->VersionVariableName
);
1608 if (Private
->LsvVariableName
!= NULL
) {
1609 FreePool (Private
->LsvVariableName
);
1611 if (Private
->LastAttemptStatusVariableName
!= NULL
) {
1612 FreePool (Private
->LastAttemptStatusVariableName
);
1614 if (Private
->LastAttemptVersionVariableName
!= NULL
) {
1615 FreePool (Private
->LastAttemptVersionVariableName
);
1617 if (Private
->FmpStateVariableName
!= NULL
) {
1618 FreePool (Private
->FmpStateVariableName
);
1626 Unloads the application and its installed protocol.
1628 @param ImageHandle Handle that identifies the image to be unloaded.
1629 @param SystemTable The system table.
1631 @retval EFI_SUCCESS The image has been unloaded.
1636 FmpDxeLibDestructor (
1637 IN EFI_HANDLE ImageHandle
,
1638 IN EFI_SYSTEM_TABLE
*SystemTable
1641 if (mFmpSingleInstance
) {
1642 return UninstallFmpInstance (ImageHandle
);
1648 Main entry for this driver/library.
1650 @param[in] ImageHandle Image handle this driver.
1651 @param[in] SystemTable Pointer to SystemTable.
1657 IN EFI_HANDLE ImageHandle
,
1658 IN EFI_SYSTEM_TABLE
*SystemTable
1664 // Verify that a new FILE_GUID value has been provided in the <Defines>
1665 // section of this module. The FILE_GUID is the ESRT GUID that must be
1666 // unique for each updatable firmware image.
1668 if (CompareGuid (&mDefaultModuleFileGuid
, &gEfiCallerIdGuid
)) {
1669 DEBUG ((DEBUG_ERROR
, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));
1671 return EFI_UNSUPPORTED
;
1675 // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.
1677 mImageIdName
= (CHAR16
*) PcdGetPtr (PcdFmpDeviceImageIdName
);
1678 if (PcdGetSize (PcdFmpDeviceImageIdName
) <= 2 || mImageIdName
[0] == 0) {
1680 // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
1682 DEBUG ((DEBUG_ERROR
, "FmpDxe: PcdFmpDeviceImageIdName is an empty string.\n"));
1684 return EFI_UNSUPPORTED
;
1688 // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
1693 // Fill in FMP Progress Protocol fields for Version 1
1695 mFmpProgress
.Version
= 1;
1696 mFmpProgress
.ProgressBarForegroundColor
.Raw
= PcdGet32 (PcdFmpDeviceProgressColor
);
1697 mFmpProgress
.WatchdogSeconds
= PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds
);
1699 // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
1700 // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
1701 // gEfiEndOfDxeEventGroupGuid is used.
1703 mLockGuid
= &gEfiEndOfDxeEventGroupGuid
;
1704 if (PcdGetSize (PcdFmpDeviceLockEventGuid
) == sizeof (EFI_GUID
)) {
1705 mLockGuid
= (EFI_GUID
*)PcdGetPtr (PcdFmpDeviceLockEventGuid
);
1707 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName
, mLockGuid
));
1710 // Register with library the install function so if the library uses
1711 // UEFI driver model/driver binding protocol it can install FMP on its device handle
1712 // If library is simple lib that does not use driver binding then it should return
1713 // unsupported and this will install the FMP instance on the ImageHandle
1715 Status
= RegisterFmpInstaller (InstallFmpInstance
);
1716 if (Status
== EFI_UNSUPPORTED
) {
1717 mFmpSingleInstance
= TRUE
;
1718 DEBUG ((DEBUG_INFO
, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName
));
1719 Status
= RegisterFmpUninstaller (UninstallFmpInstance
);
1720 if (Status
== EFI_UNSUPPORTED
) {
1721 Status
= InstallFmpInstance (ImageHandle
);
1723 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName
));
1724 Status
= EFI_UNSUPPORTED
;
1726 } else if (EFI_ERROR (Status
)) {
1727 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName
, Status
));
1731 "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n",
1734 Status
= RegisterFmpUninstaller (UninstallFmpInstance
);
1735 if (EFI_ERROR (Status
)) {
1736 DEBUG ((DEBUG_ERROR
, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName
));