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, Intel Corporation. All rights reserved.<BR>
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11 1. Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation
15 and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <Library/DebugLib.h>
32 #include <Library/BaseLib.h>
33 #include <Library/BaseMemoryLib.h>
34 #include <Library/UefiBootServicesTableLib.h>
35 #include <Library/MemoryAllocationLib.h>
36 #include <Library/UefiLib.h>
37 #include <Library/FmpAuthenticationLib.h>
38 #include <Library/FmpDeviceLib.h>
39 #include <Library/FmpPayloadHeaderLib.h>
40 #include <Library/CapsuleUpdatePolicyLib.h>
41 #include <Protocol/FirmwareManagement.h>
42 #include <Protocol/FirmwareManagementProgress.h>
43 #include <Guid/SystemResourceTable.h>
44 #include <Guid/EventGroup.h>
45 #include "VariableSupport.h"
47 #define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED"
48 #define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE"
51 Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches
52 the test key. PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of
53 the test key. For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the
54 SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest. If the
55 SHA256 hash matches or there is then error computing the SHA256 hash, then
56 set PcdTestKeyUsed to TRUE. Skip this check if PcdTestKeyUsed is already
57 TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE
66 /// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
67 /// FILE_GUID must always be overridden in the <Defines> section to provide
68 /// the ESRT GUID value associated with the updatable firmware image. A
69 /// check is made in this module's driver entry point to verify that a
70 /// new FILE_GUID value has been defined.
72 const EFI_GUID mDefaultModuleFileGuid
= {
73 0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }
76 EFI_FIRMWARE_IMAGE_DESCRIPTOR mDesc
;
77 BOOLEAN mDescriptorPopulated
= FALSE
;
78 BOOLEAN mRuntimeVersionSupported
= TRUE
;
79 BOOLEAN mFmpInstalled
= FALSE
;
82 /// Function pointer to progress function
84 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc
= NULL
;
85 BOOLEAN mProgressSupported
= FALSE
;
87 CHAR16
*mImageIdName
= NULL
;
88 UINT64 mImageId
= 0x1;
89 CHAR16
*mVersionName
= NULL
;
91 EFI_EVENT mFmpDeviceLockEvent
;
93 // Indicates if an attempt has been made to lock a
94 // FLASH storage device by calling FmpDeviceLock().
95 // A FLASH storage device may not support being locked,
96 // so this variable is set to TRUE even if FmpDeviceLock()
99 BOOLEAN mFmpDeviceLocked
= FALSE
;
102 Callback function to report the process of the firmware updating.
104 Wrap the caller's version in this so that progress from the device lib is
105 within the expected range. Convert device lib 0% - 100% to 6% - 98%.
107 FmpDxe 1% - 5% for validation
108 FmpDeviceLib 6% - 98% for flashing/update
109 FmpDxe 99% - 100% finish
111 @param[in] Completion A value between 1 and 100 indicating the current
112 completion progress of the firmware update. Completion
113 progress is reported as from 1 to 100 percent. A value
114 of 0 is used by the driver to indicate that progress
115 reporting is not supported.
117 @retval EFI_SUCCESS The progress was updated.
118 @retval EFI_UNSUPPORTED Updating progress is not supported.
129 Status
= EFI_UNSUPPORTED
;
131 if (!mProgressSupported
) {
135 if (mProgressFunc
== NULL
) {
140 // Reserve 6% - 98% for the FmpDeviceLib. Call the real progress function.
142 Status
= mProgressFunc (((Completion
* 92) / 100) + 6);
144 if (Status
== EFI_UNSUPPORTED
) {
145 mProgressSupported
= FALSE
;
146 mProgressFunc
= NULL
;
153 Returns a pointer to the ImageTypeId GUID value. An attempt is made to get
154 the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide
155 a GUID value, then gEfiCallerIdGuid is returned.
157 @return The ImageTypeId GUID
166 EFI_GUID
*FmpDeviceLibGuid
;
168 FmpDeviceLibGuid
= NULL
;
169 Status
= FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid
);
170 if (EFI_ERROR (Status
)) {
171 if (Status
!= EFI_UNSUPPORTED
) {
172 DEBUG ((DEBUG_ERROR
, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", Status
));
174 return &gEfiCallerIdGuid
;
176 if (FmpDeviceLibGuid
== NULL
) {
177 DEBUG ((DEBUG_ERROR
, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n"));
178 return &gEfiCallerIdGuid
;
180 return FmpDeviceLibGuid
;
184 Returns a pointer to the Null-terminated Unicode ImageIdName string.
186 @return Null-terminated Unicode ImageIdName string.
190 GetImageTypeNameString (
198 Lowest supported version is a combo of three parts.
199 1. Check if the device lib has a lowest supported version
200 2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)
201 3. Check Fixed at build PCD
203 Take the largest value
207 GetLowestSupportedVersion (
212 UINT32 DeviceLibLowestSupportedVersion
;
213 UINT32 VariableLowestSupportedVersion
;
217 // Get the LowestSupportedVersion.
220 if (!IsLowestSupportedVersionCheckRequired ()) {
222 // Any Version can pass the 0 LowestSupportedVersion check.
227 ReturnLsv
= PcdGet32 (PcdFmpDeviceBuildTimeLowestSupportedVersion
);
230 // Check the FmpDeviceLib
232 DeviceLibLowestSupportedVersion
= DEFAULT_LOWESTSUPPORTEDVERSION
;
233 Status
= FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion
);
234 if (EFI_ERROR (Status
)) {
235 DeviceLibLowestSupportedVersion
= DEFAULT_LOWESTSUPPORTEDVERSION
;
238 if (DeviceLibLowestSupportedVersion
> ReturnLsv
) {
239 ReturnLsv
= DeviceLibLowestSupportedVersion
;
243 // Check the lowest supported version UEFI variable for this device
245 VariableLowestSupportedVersion
= GetLowestSupportedVersionFromVariable();
246 if (VariableLowestSupportedVersion
> ReturnLsv
) {
247 ReturnLsv
= VariableLowestSupportedVersion
;
251 // Return the largest value
257 Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the module global
268 mDesc
.ImageIndex
= 1;
269 CopyGuid (&mDesc
.ImageTypeId
, GetImageTypeIdGuid());
270 mDesc
.ImageId
= mImageId
;
271 mDesc
.ImageIdName
= GetImageTypeNameString();
274 // Get the version. Some devices don't support getting the firmware version
275 // at runtime. If FmpDeviceLib does not support returning a version, then
276 // it is stored in a UEFI variable.
278 Status
= FmpDeviceGetVersion (&mDesc
.Version
);
279 if (Status
== EFI_UNSUPPORTED
) {
280 mRuntimeVersionSupported
= FALSE
;
281 mDesc
.Version
= GetVersionFromVariable();
282 } else if (EFI_ERROR (Status
)) {
284 // Unexpected error. Use default version.
286 DEBUG ((DEBUG_ERROR
, "FmpDxe: GetVersion() from FmpDeviceLib (%s) returned %r\n", GetImageTypeNameString(), Status
));
287 mDesc
.Version
= DEFAULT_VERSION
;
291 // Free the current version name. Shouldn't really happen but this populate
292 // function could be called multiple times (to refresh).
294 if (mVersionName
!= NULL
) {
295 FreePool (mVersionName
);
300 // Attempt to get the version string from the FmpDeviceLib
302 Status
= FmpDeviceGetVersionString (&mVersionName
);
303 if (Status
== EFI_UNSUPPORTED
) {
304 DEBUG ((DEBUG_INFO
, "FmpDxe: GetVersionString() unsupported in FmpDeviceLib.\n"));
305 mVersionName
= AllocateCopyPool (
306 sizeof (VERSION_STRING_NOT_SUPPORTED
),
307 VERSION_STRING_NOT_SUPPORTED
309 } else if (EFI_ERROR (Status
)) {
310 DEBUG ((DEBUG_INFO
, "FmpDxe: GetVersionString() not available in FmpDeviceLib.\n"));
311 mVersionName
= AllocateCopyPool (
312 sizeof (VERSION_STRING_NOT_AVAILABLE
),
313 VERSION_STRING_NOT_AVAILABLE
317 mDesc
.VersionName
= mVersionName
;
319 mDesc
.LowestSupportedImageVersion
= GetLowestSupportedVersion();
322 // Get attributes from the FmpDeviceLib
324 FmpDeviceGetAttributes (&mDesc
.AttributesSupported
, &mDesc
.AttributesSetting
);
327 // Force set the updatable bits in the attributes;
329 mDesc
.AttributesSupported
|= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE
;
330 mDesc
.AttributesSetting
|= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE
;
333 // Force set the authentication bits in the attributes;
335 mDesc
.AttributesSupported
|= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED
);
336 mDesc
.AttributesSetting
|= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED
);
338 mDesc
.Compatibilities
= 0;
341 // Get the size of the firmware image from the FmpDeviceLib
343 Status
= FmpDeviceGetSize (&mDesc
.Size
);
344 if (EFI_ERROR (Status
)) {
348 mDesc
.LastAttemptVersion
= GetLastAttemptVersionFromVariable ();
349 mDesc
.LastAttemptStatus
= GetLastAttemptStatusFromVariable ();
351 mDescriptorPopulated
= TRUE
;
355 Returns information about the current firmware image(s) of the device.
357 This function allows a copy of the current firmware image to be created and saved.
358 The saved copy could later been used, for example, in firmware image recovery or rollback.
360 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
361 @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
362 On input, this is the size of the buffer allocated by the caller.
363 On output, it is the size of the buffer returned by the firmware
364 if the buffer was large enough, or the size of the buffer needed
365 to contain the image(s) information if the buffer was too small.
366 @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
367 information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
368 @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
369 associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
370 @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
371 descriptors or firmware images within this device.
372 @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
373 of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
374 @param[out] PackageVersion A version number that represents all the firmware images in the device.
375 The format is vendor specific and new version must have a greater value
376 than the old version. If PackageVersion is not supported, the value is
377 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
378 is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
379 that package version update is in progress.
380 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
381 package version name. The buffer is allocated by this function with
382 AllocatePool(), and it is the caller's responsibility to free it with a call
385 @retval EFI_SUCCESS The device was successfully updated with the new image.
386 @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
387 needed to hold the image(s) information is returned in ImageInfoSize.
388 @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
389 @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
395 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
396 IN OUT UINTN
*ImageInfoSize
,
397 IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
398 OUT UINT32
*DescriptorVersion
,
399 OUT UINT8
*DescriptorCount
,
400 OUT UINTN
*DescriptorSize
,
401 OUT UINT32
*PackageVersion
,
402 OUT CHAR16
**PackageVersionName
407 Status
= EFI_SUCCESS
;
410 // Check for valid pointer
412 if (ImageInfoSize
== NULL
) {
413 DEBUG ((DEBUG_ERROR
, "FmpDxe: GetImageInfo() - ImageInfoSize is NULL.\n"));
414 Status
= EFI_INVALID_PARAMETER
;
419 // Check the buffer size
420 // NOTE: Check this first so caller can get the necessary memory size it must allocate.
422 if (*ImageInfoSize
< (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
))) {
423 *ImageInfoSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
424 DEBUG ((DEBUG_VERBOSE
, "FmpDxe: GetImageInfo() - ImageInfoSize is to small.\n"));
425 Status
= EFI_BUFFER_TOO_SMALL
;
430 // Confirm that buffer isn't null
432 if ( (ImageInfo
== NULL
) || (DescriptorVersion
== NULL
) || (DescriptorCount
== NULL
) || (DescriptorSize
== NULL
)
433 || (PackageVersion
== NULL
)) {
434 DEBUG ((DEBUG_ERROR
, "FmpDxe: GetImageInfo() - Pointer Parameter is NULL.\n"));
435 Status
= EFI_INVALID_PARAMETER
;
440 // Set the size to whatever we need
442 *ImageInfoSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
445 if (!mDescriptorPopulated
) {
446 PopulateDescriptor();
450 // Copy the image descriptor
452 CopyMem (ImageInfo
, &mDesc
, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
));
454 *DescriptorVersion
= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
;
455 *DescriptorCount
= 1;
456 *DescriptorSize
= sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
460 *PackageVersion
= 0xFFFFFFFF;
463 // Do not update PackageVersionName since it is not supported in this instance.
472 Retrieves a copy of the current firmware image of the device.
474 This function allows a copy of the current firmware image to be created and saved.
475 The saved copy could later been used, for example, in firmware image recovery or rollback.
477 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
478 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
479 The number is between 1 and DescriptorCount.
480 @param[in, out] Image Points to the buffer where the current image is copied to.
481 @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
482 On return, points to the length of the image, in bytes.
484 @retval EFI_SUCCESS The device was successfully updated with the new image.
485 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
486 image. The current buffer size needed to hold the image is returned
488 @retval EFI_INVALID_PARAMETER The Image was NULL.
489 @retval EFI_NOT_FOUND The current image is not copied to the buffer.
490 @retval EFI_UNSUPPORTED The operation is not supported.
491 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
497 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
500 IN OUT UINTN
*ImageSize
506 Status
= EFI_SUCCESS
;
509 // Check to make sure index is 1 (only 1 image for this device)
511 if (ImageIndex
!= 1) {
512 DEBUG ((DEBUG_ERROR
, "FmpDxe: GetImage() - Image Index Invalid.\n"));
513 Status
= EFI_INVALID_PARAMETER
;
517 if (ImageSize
== NULL
) {
518 DEBUG ((DEBUG_ERROR
, "FmpDxe: GetImage() - ImageSize Pointer Parameter is NULL.\n"));
519 Status
= EFI_INVALID_PARAMETER
;
524 // Check the buffer size
526 Status
= FmpDeviceGetSize (&Size
);
527 if (EFI_ERROR (Status
)) {
530 if (*ImageSize
< Size
) {
532 DEBUG ((DEBUG_VERBOSE
, "FmpDxe: GetImage() - ImageSize is to small.\n"));
533 Status
= EFI_BUFFER_TOO_SMALL
;
538 DEBUG ((DEBUG_ERROR
, "FmpDxe: GetImage() - Image Pointer Parameter is NULL.\n"));
539 Status
= EFI_INVALID_PARAMETER
;
543 Status
= FmpDeviceGetImage (Image
, ImageSize
);
550 Helper function to safely retrieve the FMP header from
551 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
553 @param[in] Image Pointer to the image.
554 @param[in] ImageSize Size of the image.
555 @param[out] PayloadSize
557 @retval !NULL Valid pointer to the header.
558 @retval NULL Structure is bad and pointer cannot be found.
563 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION
*Image
,
564 IN CONST UINTN ImageSize
,
565 OUT UINTN
*PayloadSize
569 // Check to make sure that operation can be safely performed.
571 if (((UINTN
)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
) < (UINTN
)Image
|| \
572 ((UINTN
)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
) >= (UINTN
)Image
+ ImageSize
) {
574 // Pointer overflow. Invalid image.
579 *PayloadSize
= ImageSize
- (sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
);
580 return (VOID
*)((UINT8
*)Image
+ sizeof (Image
->MonotonicCount
) + Image
->AuthInfo
.Hdr
.dwLength
);
584 Helper function to safely calculate the size of all headers
585 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
587 @param[in] Image Pointer to the image.
588 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
590 @retval UINT32>0 Valid size of all the headers.
591 @retval 0 Structure is bad and size cannot be found.
596 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION
*Image
,
597 IN UINT32 AdditionalHeaderSize
600 UINT32 CalculatedSize
;
602 CalculatedSize
= sizeof (Image
->MonotonicCount
) +
603 AdditionalHeaderSize
+
604 Image
->AuthInfo
.Hdr
.dwLength
;
607 // Check to make sure that operation can be safely performed.
609 if (CalculatedSize
< sizeof (Image
->MonotonicCount
) ||
610 CalculatedSize
< AdditionalHeaderSize
||
611 CalculatedSize
< Image
->AuthInfo
.Hdr
.dwLength
) {
613 // Integer overflow. Invalid image.
618 return CalculatedSize
;
622 Checks if the firmware image is valid for the device.
624 This function allows firmware update application to validate the firmware image without
625 invoking the SetImage() first.
627 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
628 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
629 The number is between 1 and DescriptorCount.
630 @param[in] Image Points to the new image.
631 @param[in] ImageSize Size of the new image in bytes.
632 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
633 if available, additional information if the image is invalid.
635 @retval EFI_SUCCESS The image was successfully checked.
636 @retval EFI_ABORTED The operation is aborted.
637 @retval EFI_INVALID_PARAMETER The Image was NULL.
638 @retval EFI_UNSUPPORTED The operation is not supported.
639 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
645 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
647 IN CONST VOID
*Image
,
649 OUT UINT32
*ImageUpdatable
654 VOID
*FmpPayloadHeader
;
655 UINTN FmpPayloadSize
;
657 UINT32 FmpHeaderSize
;
661 UINTN PublicKeyDataLength
;
662 UINT8
*PublicKeyDataXdr
;
663 UINT8
*PublicKeyDataXdrEnd
;
665 Status
= EFI_SUCCESS
;
667 FmpPayloadHeader
= NULL
;
674 // make sure the descriptor has already been loaded
676 if (!mDescriptorPopulated
) {
677 PopulateDescriptor();
680 if (ImageUpdatable
== NULL
) {
681 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n"));
682 Status
= EFI_INVALID_PARAMETER
;
687 //Set to valid and then if any tests fail it will update this flag.
689 *ImageUpdatable
= IMAGE_UPDATABLE_VALID
;
692 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckImage() - Image Pointer Parameter is NULL.\n"));
694 // not sure if this is needed
696 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
697 return EFI_INVALID_PARAMETER
;
700 PublicKeyDataXdr
= PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr
);
701 PublicKeyDataXdrEnd
= PublicKeyDataXdr
+ PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr
);
703 if (PublicKeyDataXdr
== NULL
|| (PublicKeyDataXdr
== PublicKeyDataXdrEnd
)) {
704 DEBUG ((DEBUG_ERROR
, "FmpDxe: Invalid certificate, skipping it.\n"));
705 Status
= EFI_ABORTED
;
708 // Try each key from PcdFmpDevicePkcs7CertBufferXdr
710 for (Index
= 1; PublicKeyDataXdr
< PublicKeyDataXdrEnd
; Index
++) {
714 "FmpDxe: Certificate #%d [%p..%p].\n",
721 if ((PublicKeyDataXdr
+ sizeof (UINT32
)) > PublicKeyDataXdrEnd
) {
723 // Key data extends beyond end of PCD
725 DEBUG ((DEBUG_ERROR
, "FmpDxe: Certificate size extends beyond end of PCD, skipping it.\n"));
726 Status
= EFI_ABORTED
;
730 // Read key length stored in big-endian format
732 PublicKeyDataLength
= SwapBytes32 (*(UINT32
*)(PublicKeyDataXdr
));
734 // Point to the start of the key data
736 PublicKeyDataXdr
+= sizeof (UINT32
);
737 if (PublicKeyDataXdr
+ PublicKeyDataLength
> PublicKeyDataXdrEnd
) {
739 // Key data extends beyond end of PCD
741 DEBUG ((DEBUG_ERROR
, "FmpDxe: Certificate extends beyond end of PCD, skipping it.\n"));
742 Status
= EFI_ABORTED
;
745 PublicKeyData
= PublicKeyDataXdr
;
746 Status
= AuthenticateFmpImage (
747 (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
,
752 if (!EFI_ERROR (Status
)) {
755 PublicKeyDataXdr
+= PublicKeyDataLength
;
756 PublicKeyDataXdr
= (UINT8
*)ALIGN_POINTER (PublicKeyDataXdr
, sizeof (UINT32
));
760 if (EFI_ERROR (Status
)) {
761 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckTheImage() - Authentication Failed %r.\n", Status
));
766 // Check to make sure index is 1
768 if (ImageIndex
!= 1) {
769 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckImage() - Image Index Invalid.\n"));
770 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID_TYPE
;
771 Status
= EFI_SUCCESS
;
777 // Check the FmpPayloadHeader
779 FmpPayloadHeader
= GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, &FmpPayloadSize
);
780 if (FmpPayloadHeader
== NULL
) {
781 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckTheImage() - GetFmpHeader failed.\n"));
782 Status
= EFI_ABORTED
;
785 Status
= GetFmpPayloadHeaderVersion (FmpPayloadHeader
, FmpPayloadSize
, &Version
);
786 if (EFI_ERROR (Status
)) {
787 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", Status
));
788 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
789 Status
= EFI_SUCCESS
;
794 // Check the lowest supported version
796 if (Version
< mDesc
.LowestSupportedImageVersion
) {
799 "FmpDxe: CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
800 Version
, mDesc
.LowestSupportedImageVersion
)
802 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID_OLD
;
803 Status
= EFI_SUCCESS
;
808 // Get the FmpHeaderSize so we can determine the real payload size
810 Status
= GetFmpPayloadHeaderSize (FmpPayloadHeader
, FmpPayloadSize
, &FmpHeaderSize
);
811 if (EFI_ERROR (Status
)) {
812 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status
));
813 *ImageUpdatable
= IMAGE_UPDATABLE_INVALID
;
814 Status
= EFI_SUCCESS
;
819 // Call FmpDevice Lib Check Image on the
820 // Raw payload. So all headers need stripped off
822 AllHeaderSize
= GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, FmpHeaderSize
);
823 if (AllHeaderSize
== 0) {
824 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckTheImage() - GetAllHeaderSize failed.\n"));
825 Status
= EFI_ABORTED
;
828 RawSize
= ImageSize
- AllHeaderSize
;
831 // FmpDeviceLib CheckImage function to do any specific checks
833 Status
= FmpDeviceCheckImage ((((UINT8
*)Image
) + AllHeaderSize
), RawSize
, ImageUpdatable
);
834 if (EFI_ERROR (Status
)) {
835 DEBUG ((DEBUG_ERROR
, "FmpDxe: CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", Status
));
843 Updates the firmware image of the device.
845 This function updates the hardware with the new firmware image.
846 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
847 If the firmware image is updatable, the function should perform the following minimal validations
848 before proceeding to do the firmware image update.
849 - Validate the image authentication if image has attribute
850 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
851 EFI_SECURITY_VIOLATION if the validation fails.
852 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
853 the image is unsupported. The function can optionally provide more detailed information on
854 why the image is not a supported image.
855 - Validate the data from VendorCode if not null. Image validation must be performed before
856 VendorCode data validation. VendorCode data is ignored or considered invalid if image
857 validation failed. The function returns EFI_ABORTED if the data is invalid.
859 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
860 the caller did not specify the policy or use the default policy. As an example, vendor can implement
861 a policy to allow an option to force a firmware image update when the abort reason is due to the new
862 firmware image version is older than the current firmware image version or bad image checksum.
863 Sensitive operations such as those wiping the entire firmware image and render the device to be
864 non-functional should be encoded in the image itself rather than passed with the VendorCode.
865 AbortReason enables vendor to have the option to provide a more detailed description of the abort
866 reason to the caller.
868 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
869 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
870 The number is between 1 and DescriptorCount.
871 @param[in] Image Points to the new image.
872 @param[in] ImageSize Size of the new image in bytes.
873 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
874 Null indicates the caller did not specify the policy or use the default policy.
875 @param[in] Progress A function used by the driver to report the progress of the firmware update.
876 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
877 details for the aborted operation. The buffer is allocated by this function
878 with AllocatePool(), and it is the caller's responsibility to free it with a
881 @retval EFI_SUCCESS The device was successfully updated with the new image.
882 @retval EFI_ABORTED The operation is aborted.
883 @retval EFI_INVALID_PARAMETER The Image was NULL.
884 @retval EFI_UNSUPPORTED The operation is not supported.
885 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
891 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
893 IN CONST VOID
*Image
,
895 IN CONST VOID
*VendorCode
,
896 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress
,
897 OUT CHAR16
**AbortReason
902 BOOLEAN BooleanValue
;
903 UINT32 FmpHeaderSize
;
905 UINTN FmpPayloadSize
;
906 UINT32 AllHeaderSize
;
907 UINT32 IncommingFwVersion
;
908 UINT32 LastAttemptStatus
;
909 EFI_STATUS GetAttributesStatus
;
910 UINT64 AttributesSupported
;
911 UINT64 AttributesSetting
;
913 UINT32 LowestSupportedVersion
;
915 Status
= EFI_SUCCESS
;
917 BooleanValue
= FALSE
;
922 IncommingFwVersion
= 0;
923 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
926 SetLastAttemptVersionInVariable (IncommingFwVersion
); //set to 0 to clear any previous results.
929 // if we have locked the device, then skip the set operation.
930 // it should be blocked by hardware too but we can catch here even faster
932 if (mFmpDeviceLocked
) {
933 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - Device is already locked. Can't update.\n"));
934 Status
= EFI_UNSUPPORTED
;
939 // Call check image to verify the image
941 Status
= CheckTheImage (This
, ImageIndex
, Image
, ImageSize
, &Updateable
);
942 if (EFI_ERROR (Status
)) {
943 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - Check The Image failed with %r.\n", Status
));
944 if (Status
== EFI_SECURITY_VIOLATION
) {
945 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR
;
951 // No functional error in CheckTheImage. Attempt to get the Version to
952 // support better error reporting.
954 FmpHeader
= GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, ImageSize
, &FmpPayloadSize
);
955 if (FmpHeader
== NULL
) {
956 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - GetFmpHeader failed.\n"));
957 Status
= EFI_ABORTED
;
960 Status
= GetFmpPayloadHeaderVersion (FmpHeader
, FmpPayloadSize
, &IncommingFwVersion
);
961 if (!EFI_ERROR (Status
)) {
963 // Set to actual value
965 SetLastAttemptVersionInVariable (IncommingFwVersion
);
969 if (Updateable
!= IMAGE_UPDATABLE_VALID
) {
972 "FmpDxed: SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
975 Status
= EFI_ABORTED
;
979 if (Progress
== NULL
) {
980 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - Invalid progress callback\n"));
981 Status
= EFI_INVALID_PARAMETER
;
985 mProgressFunc
= Progress
;
986 mProgressSupported
= TRUE
;
989 // Checking the image is at least 1%
991 Status
= Progress (1);
992 if (EFI_ERROR (Status
)) {
993 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - Progress Callback failed with Status %r.\n", Status
));
999 Status
= CheckSystemPower (&BooleanValue
);
1000 if (EFI_ERROR (Status
)) {
1001 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - CheckSystemPower - API call failed %r.\n", Status
));
1004 if (!BooleanValue
) {
1005 Status
= EFI_ABORTED
;
1008 "FmpDxe: SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n")
1010 LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT
;
1017 //Check System Thermal
1019 Status
= CheckSystemThermal (&BooleanValue
);
1020 if (EFI_ERROR (Status
)) {
1021 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - CheckSystemThermal - API call failed %r.\n", Status
));
1024 if (!BooleanValue
) {
1025 Status
= EFI_ABORTED
;
1028 "FmpDxe: SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n")
1036 //Check System Environment
1038 Status
= CheckSystemEnvironment (&BooleanValue
);
1039 if (EFI_ERROR (Status
)) {
1040 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", Status
));
1043 if (!BooleanValue
) {
1044 Status
= EFI_ABORTED
;
1047 "FmpDxe: SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n")
1055 // Save LastAttemptStatus as error so that if SetImage never returns the error
1056 // state is recorded.
1058 SetLastAttemptStatusInVariable (LastAttemptStatus
);
1061 // Strip off all the headers so the device can process its firmware
1063 Status
= GetFmpPayloadHeaderSize (FmpHeader
, FmpPayloadSize
, &FmpHeaderSize
);
1064 if (EFI_ERROR (Status
)) {
1065 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status
));
1069 AllHeaderSize
= GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION
*)Image
, FmpHeaderSize
);
1070 if (AllHeaderSize
== 0) {
1071 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() - GetAllHeaderSize failed.\n"));
1072 Status
= EFI_ABORTED
;
1077 // Indicate that control is handed off to FmpDeviceLib
1082 //Copy the requested image to the firmware using the FmpDeviceLib
1084 Status
= FmpDeviceSetImage (
1085 (((UINT8
*)Image
) + AllHeaderSize
),
1086 ImageSize
- AllHeaderSize
,
1092 if (EFI_ERROR (Status
)) {
1093 DEBUG ((DEBUG_ERROR
, "FmpDxe: SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", Status
));
1099 // Finished the update without error
1100 // Indicate that control has been returned from FmpDeviceLib
1105 // Update the version stored in variable
1107 if (!mRuntimeVersionSupported
) {
1108 Version
= DEFAULT_VERSION
;
1109 GetFmpPayloadHeaderVersion (FmpHeader
, FmpPayloadSize
, &Version
);
1110 SetVersionInVariable (Version
);
1114 // Update lowest supported variable
1117 LowestSupportedVersion
= DEFAULT_LOWESTSUPPORTEDVERSION
;
1118 GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader
, FmpPayloadSize
, &LowestSupportedVersion
);
1119 SetLowestSupportedVersionInVariable (LowestSupportedVersion
);
1122 LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1125 // Set flag so the descriptor is repopulated
1126 // This is only applied to devices that do not require reset
1128 GetAttributesStatus
= FmpDeviceGetAttributes (&AttributesSupported
, &AttributesSetting
);
1129 if (!EFI_ERROR (GetAttributesStatus
)) {
1130 if (((AttributesSupported
& IMAGE_ATTRIBUTE_RESET_REQUIRED
) == 0) ||
1131 ((AttributesSetting
& IMAGE_ATTRIBUTE_RESET_REQUIRED
) == 0)) {
1132 mDescriptorPopulated
= FALSE
;
1137 mProgressFunc
= NULL
;
1138 mProgressSupported
= FALSE
;
1139 SetLastAttemptStatusInVariable (LastAttemptStatus
);
1141 if (Progress
!= NULL
) {
1143 // Set progress to 100 after everything is done including recording Status.
1152 Returns information about the firmware package.
1154 This function returns package information.
1156 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1157 @param[out] PackageVersion A version number that represents all the firmware images in the device.
1158 The format is vendor specific and new version must have a greater value
1159 than the old version. If PackageVersion is not supported, the value is
1160 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
1161 comparison is to be performed using PackageVersionName. A value of
1162 0xFFFFFFFD indicates that package version update is in progress.
1163 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
1164 the package version name. The buffer is allocated by this function with
1165 AllocatePool(), and it is the caller's responsibility to free it with a
1167 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
1168 package version name. A value of 0 indicates the device does not support
1169 update of package version name. Length is the number of Unicode characters,
1170 including the terminating null character.
1171 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
1172 Definitions' for possible returned values of this parameter. A value of 1
1173 indicates the attribute is supported and the current setting value is
1174 indicated in AttributesSetting. A value of 0 indicates the attribute is not
1175 supported and the current setting value in AttributesSetting is meaningless.
1176 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
1177 values of this parameter
1179 @retval EFI_SUCCESS The package information was successfully returned.
1180 @retval EFI_UNSUPPORTED The operation is not supported.
1186 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
1187 OUT UINT32
*PackageVersion
,
1188 OUT CHAR16
**PackageVersionName
,
1189 OUT UINT32
*PackageVersionNameMaxLen
,
1190 OUT UINT64
*AttributesSupported
,
1191 OUT UINT64
*AttributesSetting
1194 return EFI_UNSUPPORTED
;
1198 Updates information about the firmware package.
1200 This function updates package information.
1201 This function returns EFI_UNSUPPORTED if the package information is not updatable.
1202 VendorCode enables vendor to implement vendor-specific package information update policy.
1203 Null if the caller did not specify this policy or use the default policy.
1205 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1206 @param[in] Image Points to the authentication image.
1207 Null if authentication is not required.
1208 @param[in] ImageSize Size of the authentication image in bytes.
1209 0 if authentication is not required.
1210 @param[in] VendorCode This enables vendor to implement vendor-specific firmware
1211 image update policy.
1212 Null indicates the caller did not specify this policy or use
1214 @param[in] PackageVersion The new package version.
1215 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
1216 the package version name.
1217 The string length is equal to or less than the value returned in
1218 PackageVersionNameMaxLen.
1220 @retval EFI_SUCCESS The device was successfully updated with the new package
1222 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
1223 returned in PackageVersionNameMaxLen.
1224 @retval EFI_UNSUPPORTED The operation is not supported.
1225 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1231 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
1232 IN CONST VOID
*Image
,
1234 IN CONST VOID
*VendorCode
,
1235 IN UINT32 PackageVersion
,
1236 IN CONST CHAR16
*PackageVersionName
1239 return EFI_UNSUPPORTED
;
1243 Event notification function that is invoked when the event GUID specified by
1244 PcdFmpDeviceLockEventGuid is signaled.
1246 @param[in] Event Event whose notification function is being invoked.
1247 @param[in] Context The pointer to the notification function's context,
1248 which is implementation-dependent.
1252 FmpDxeLockEventNotify (
1259 if (!mFmpDeviceLocked
) {
1260 if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
1262 // Lock all UEFI Variables used by this module.
1264 Status
= LockAllFmpVariables ();
1265 if (EFI_ERROR (Status
)) {
1266 DEBUG ((DEBUG_ERROR
, "FmpDxe: Failed to lock variables. Status = %r.\n"));
1268 DEBUG ((DEBUG_INFO
, "FmpDxe: All variables locked\n"));
1272 // Lock the firmware device
1274 Status
= FmpDeviceLock();
1275 if (EFI_ERROR (Status
)) {
1276 if (Status
!= EFI_UNSUPPORTED
) {
1277 DEBUG ((DEBUG_ERROR
, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status
));
1279 DEBUG ((DEBUG_WARN
, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status
));
1282 mFmpDeviceLocked
= TRUE
;
1284 DEBUG ((DEBUG_VERBOSE
, "FmpDxe: Not calling FmpDeviceLock() because mfg mode\n"));
1290 Function to install FMP instance.
1292 @param[in] Handle The device handle to install a FMP instance on.
1294 @retval EFI_SUCCESS FMP Installed
1295 @retval EFI_INVALID_PARAMETER Handle was invalid
1296 @retval other Error installing FMP
1301 InstallFmpInstance (
1302 IN EFI_HANDLE Handle
1306 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1307 EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL
*FmpProgress
;
1309 Status
= EFI_SUCCESS
;
1314 // Only allow a single FMP Protocol instance to be installed
1316 if (mFmpInstalled
) {
1317 return EFI_ALREADY_STARTED
;
1321 // Allocate FMP Protocol instance
1323 Fmp
= AllocateZeroPool (sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL
));
1325 DEBUG ((DEBUG_ERROR
, "FmpDxe: Failed to allocate memory for FMP Protocol instance.\n"));
1326 Status
= EFI_OUT_OF_RESOURCES
;
1331 // Allocate FMP Progress Protocol instance
1333 FmpProgress
= AllocateZeroPool (sizeof (EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL
));
1334 if (FmpProgress
== NULL
) {
1335 DEBUG ((DEBUG_ERROR
, "FmpDxe: Failed to allocate memory for FMP Progress Protocol instance.\n"));
1336 Status
= EFI_OUT_OF_RESOURCES
;
1342 // Set up FMP Protocol function pointers
1344 Fmp
->GetImageInfo
= GetTheImageInfo
;
1345 Fmp
->GetImage
= GetTheImage
;
1346 Fmp
->SetImage
= SetTheImage
;
1347 Fmp
->CheckImage
= CheckTheImage
;
1348 Fmp
->GetPackageInfo
= GetPackageInfo
;
1349 Fmp
->SetPackageInfo
= SetPackageInfo
;
1352 // Fill in FMP Progress Protocol fields for Version 1
1354 FmpProgress
->Version
= 1;
1355 FmpProgress
->ProgressBarForegroundColor
.Raw
= PcdGet32 (PcdFmpDeviceProgressColor
);
1356 FmpProgress
->WatchdogSeconds
= PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds
);
1359 // Install FMP Protocol and FMP Progress Protocol
1361 Status
= gBS
->InstallMultipleProtocolInterfaces (
1363 &gEfiFirmwareManagementProtocolGuid
,
1365 &gEdkiiFirmwareManagementProgressProtocolGuid
,
1370 if (EFI_ERROR (Status
)) {
1371 DEBUG ((DEBUG_ERROR
, "FmpDxe: FMP Protocol install error. Status = %r.\n", Status
));
1376 DEBUG ((DEBUG_INFO
, "FmpDxe: FMP Protocol Installed!\n"));
1377 mFmpInstalled
= TRUE
;
1385 Main entry for this driver/library.
1387 @param[in] ImageHandle Image handle this driver.
1388 @param[in] SystemTable Pointer to SystemTable.
1394 IN EFI_HANDLE ImageHandle
,
1395 IN EFI_SYSTEM_TABLE
*SystemTable
1402 // Verify that a new FILE_GUID value has been provided in the <Defines>
1403 // section of this module. The FILE_GUID is the ESRT GUID that must be
1404 // unique for each updatable firmware image.
1406 if (CompareGuid (&mDefaultModuleFileGuid
, &gEfiCallerIdGuid
)) {
1407 DEBUG ((DEBUG_ERROR
, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));
1409 return EFI_UNSUPPORTED
;
1413 // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.
1415 mImageIdName
= (CHAR16
*) PcdGetPtr (PcdFmpDeviceImageIdName
);
1416 if (PcdGetSize (PcdFmpDeviceImageIdName
) <= 2 || mImageIdName
[0] == 0) {
1418 // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
1420 DEBUG ((DEBUG_ERROR
, "FmpDxe: FmpDeviceLib PcdFmpDeviceImageIdName is an empty string.\n"));
1425 // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
1430 // Register with library the install function so if the library uses
1431 // UEFI driver model/driver binding protocol it can install FMP on its device handle
1432 // If library is simple lib that does not use driver binding then it should return
1433 // unsupported and this will install the FMP instance on the ImageHandle
1435 Status
= RegisterFmpInstaller (InstallFmpInstance
);
1436 if (Status
== EFI_UNSUPPORTED
) {
1437 DEBUG ((DEBUG_INFO
, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n"));
1438 Status
= InstallFmpInstance (ImageHandle
);
1439 } else if (EFI_ERROR (Status
)) {
1440 DEBUG ((DEBUG_ERROR
, "FmpDxe: FmpDeviceLib registration returned %r. No FMP installed.\n", Status
));
1444 "FmpDxe: FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n"
1449 // Register notify function to lock the FMP device.
1450 // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
1451 // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
1452 // gEfiEndOfDxeEventGroupGuid is used.
1454 LockGuid
= &gEfiEndOfDxeEventGroupGuid
;
1455 if (PcdGetSize (PcdFmpDeviceLockEventGuid
) == sizeof (EFI_GUID
)) {
1456 LockGuid
= (EFI_GUID
*)PcdGetPtr (PcdFmpDeviceLockEventGuid
);
1458 DEBUG ((DEBUG_INFO
, "FmpDxe: Lock GUID: %g\n", LockGuid
));
1460 Status
= gBS
->CreateEventEx (
1463 FmpDxeLockEventNotify
,
1466 &mFmpDeviceLockEvent
1468 if (EFI_ERROR (Status
)) {
1469 DEBUG ((DEBUG_ERROR
, "FmpDxe: Failed to register for ready to boot. Status = %r\n", Status
));
1471 ASSERT_EFI_ERROR (Status
);