REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the FmpDevicePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1976 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1976 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Produces a Firmware Management Protocol that supports updates to a firmware
 | |
|   image stored in a firmware device with platform and firmware device specific
 | |
|   information provided through PCDs and libraries.
 | |
| 
 | |
|   Copyright (c) Microsoft Corporation.<BR>
 | |
|   Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "FmpDxe.h"
 | |
| #include "VariableSupport.h"
 | |
| 
 | |
| ///
 | |
| /// FILE_GUID from FmpDxe.inf.  When FmpDxe.inf is used in a platform, the
 | |
| /// FILE_GUID must always be overridden in the <Defines> section to provide
 | |
| /// the ESRT GUID value associated with the updatable firmware image.  A
 | |
| /// check is made in this module's driver entry point to verify that a
 | |
| /// new FILE_GUID value has been defined.
 | |
| ///
 | |
| const EFI_GUID  mDefaultModuleFileGuid = {
 | |
|   0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }
 | |
| };
 | |
| 
 | |
| ///
 | |
| /// TRUE if FmpDeviceLib manages a single firmware storage device.
 | |
| ///
 | |
| BOOLEAN  mFmpSingleInstance = FALSE;
 | |
| 
 | |
| ///
 | |
| /// Firmware Management Protocol instance that is initialized in the entry
 | |
| /// point from PCD settings.
 | |
| ///
 | |
| EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL  mFmpProgress;
 | |
| 
 | |
| //
 | |
| // Template of the private context structure for the Firmware Management
 | |
| // Protocol instance
 | |
| //
 | |
| const FIRMWARE_MANAGEMENT_PRIVATE_DATA  mFirmwareManagementPrivateDataTemplate = {
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE, // Signature
 | |
|   NULL,                                       // Handle
 | |
|   {                                            // Fmp
 | |
|     GetTheImageInfo,
 | |
|     GetTheImage,
 | |
|     SetTheImage,
 | |
|     CheckTheImage,
 | |
|     GetPackageInfo,
 | |
|     SetPackageInfo
 | |
|   },
 | |
|   FALSE,            // DescriptorPopulated
 | |
|   {                 // Desc
 | |
|     1,              // ImageIndex
 | |
|     //
 | |
|     // ImageTypeId
 | |
|     //
 | |
|     { 0x00000000,   0x0000,0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
 | |
|     },
 | |
|     1,     // ImageId
 | |
|     NULL,  // ImageIdName
 | |
|     0,     // Version
 | |
|     NULL,  // VersionName
 | |
|     0,     // Size
 | |
|     0,     // AttributesSupported
 | |
|     0,     // AttributesSetting
 | |
|     0,     // Compatibilities
 | |
|     0,     // LowestSupportedImageVersion
 | |
|     0,     // LastAttemptVersion
 | |
|     0,     // LastAttemptStatus
 | |
|     0      // HardwareInstance
 | |
|   },
 | |
|   NULL,             // ImageIdName
 | |
|   NULL,             // VersionName
 | |
|   TRUE,             // RuntimeVersionSupported
 | |
|   NULL,             // FmpDeviceLockEvent
 | |
|   FALSE,            // FmpDeviceLocked
 | |
|   NULL,             // FmpDeviceContext
 | |
|   NULL,             // VersionVariableName
 | |
|   NULL,             // LsvVariableName
 | |
|   NULL,             // LastAttemptStatusVariableName
 | |
|   NULL,             // LastAttemptVersionVariableName
 | |
|   NULL,             // FmpStateVariableName
 | |
|   TRUE              // DependenciesSatisfied
 | |
| };
 | |
| 
 | |
| ///
 | |
| /// GUID that is used to create event used to lock the firmware storage device.
 | |
| ///
 | |
| EFI_GUID  *mLockGuid = NULL;
 | |
| 
 | |
| ///
 | |
| /// Progress() function pointer passed into SetTheImage()
 | |
| ///
 | |
| EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  mProgressFunc = NULL;
 | |
| 
 | |
| ///
 | |
| /// Null-terminated Unicode string retrieved from PcdFmpDeviceImageIdName.
 | |
| ///
 | |
| CHAR16  *mImageIdName = NULL;
 | |
| 
 | |
| /**
 | |
|   Callback function to report the process of the firmware updating.
 | |
| 
 | |
|   Wrap the caller's version in this so that progress from the device lib is
 | |
|   within the expected range.  Convert device lib 0% - 100% to 6% - 98%.
 | |
| 
 | |
|   FmpDxe        1% -   5%  for validation
 | |
|   FmpDeviceLib  6% -  98%  for flashing/update
 | |
|   FmpDxe       99% - 100%  finish
 | |
| 
 | |
|   @param[in] Completion  A value between 1 and 100 indicating the current
 | |
|                          completion progress of the firmware update. Completion
 | |
|                          progress is reported as from 1 to 100 percent. A value
 | |
|                          of 0 is used by the driver to indicate that progress
 | |
|                          reporting is not supported.
 | |
| 
 | |
|   @retval  EFI_SUCCESS      The progress was updated.
 | |
|   @retval  EFI_UNSUPPORTED  Updating progress is not supported.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FmpDxeProgress (
 | |
|   IN UINTN  Completion
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_UNSUPPORTED;
 | |
| 
 | |
|   if (mProgressFunc == NULL) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Reserve 6% - 98% for the FmpDeviceLib.  Call the real progress function.
 | |
|   //
 | |
|   Status = mProgressFunc (((Completion * 92) / 100) + 6);
 | |
| 
 | |
|   if (Status == EFI_UNSUPPORTED) {
 | |
|     mProgressFunc = NULL;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Returns a pointer to the ImageTypeId GUID value.  An attempt is made to get
 | |
|   the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide
 | |
|   a GUID value, then PcdFmpDeviceImageTypeIdGuid is used.  If the size of
 | |
|   PcdFmpDeviceImageTypeIdGuid is not the size of EFI_GUID, then gEfiCallerIdGuid
 | |
|   is returned.
 | |
| 
 | |
|   @retval  The ImageTypeId GUID
 | |
| 
 | |
| **/
 | |
| EFI_GUID *
 | |
| GetImageTypeIdGuid (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   EFI_GUID    *FmpDeviceLibGuid;
 | |
|   UINTN       ImageTypeIdGuidSize;
 | |
| 
 | |
|   FmpDeviceLibGuid = NULL;
 | |
|   Status           = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (Status != EFI_UNSUPPORTED) {
 | |
|       DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName, Status));
 | |
|     }
 | |
|   } else if (FmpDeviceLibGuid == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName));
 | |
|     Status = EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     ImageTypeIdGuidSize = PcdGetSize (PcdFmpDeviceImageTypeIdGuid);
 | |
|     if (ImageTypeIdGuidSize == sizeof (EFI_GUID)) {
 | |
|       FmpDeviceLibGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceImageTypeIdGuid);
 | |
|     } else {
 | |
|       DEBUG ((DEBUG_WARN, "FmpDxe(%s): Fall back to ImageTypeIdGuid of gEfiCallerIdGuid\n", mImageIdName));
 | |
|       FmpDeviceLibGuid = &gEfiCallerIdGuid;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FmpDeviceLibGuid;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Returns a pointer to the Null-terminated Unicode ImageIdName string.
 | |
| 
 | |
|   @retval  Null-terminated Unicode ImageIdName string.
 | |
| 
 | |
| **/
 | |
| CHAR16 *
 | |
| GetImageTypeNameString (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   return mImageIdName;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Lowest supported version is a combo of three parts.
 | |
|   1. Check if the device lib has a lowest supported version
 | |
|   2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)
 | |
|   3. Check Fixed at build PCD
 | |
| 
 | |
|   @param[in] Private  Pointer to the private context structure for the
 | |
|                       Firmware Management Protocol instance.
 | |
| 
 | |
|   @retval  The largest value
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| GetLowestSupportedVersion (
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      DeviceLibLowestSupportedVersion;
 | |
|   UINT32      VariableLowestSupportedVersion;
 | |
|   UINT32      ReturnLsv;
 | |
| 
 | |
|   //
 | |
|   // Get the LowestSupportedVersion.
 | |
|   //
 | |
| 
 | |
|   if (!IsLowestSupportedVersionCheckRequired ()) {
 | |
|     //
 | |
|     // Any Version can pass the 0 LowestSupportedVersion check.
 | |
|     //
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   ReturnLsv = PcdGet32 (PcdFmpDeviceBuildTimeLowestSupportedVersion);
 | |
| 
 | |
|   //
 | |
|   // Check the FmpDeviceLib
 | |
|   //
 | |
|   DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
 | |
|   Status                          = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
 | |
|   }
 | |
| 
 | |
|   if (DeviceLibLowestSupportedVersion > ReturnLsv) {
 | |
|     ReturnLsv = DeviceLibLowestSupportedVersion;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check the lowest supported version UEFI variable for this device
 | |
|   //
 | |
|   VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private);
 | |
|   if (VariableLowestSupportedVersion > ReturnLsv) {
 | |
|     ReturnLsv = VariableLowestSupportedVersion;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Return the largest value
 | |
|   //
 | |
|   return ReturnLsv;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the private
 | |
|   context structure.
 | |
| 
 | |
|   @param[in] Private  Pointer to the private context structure for the
 | |
|                       Firmware Management Protocol instance.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PopulateDescriptor (
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      DependenciesSize;
 | |
| 
 | |
|   if (Private == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): PopulateDescriptor() - Private is NULL.\n", mImageIdName));
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (Private->DescriptorPopulated) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Private->Descriptor.ImageIndex = 1;
 | |
|   CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid ());
 | |
|   Private->Descriptor.ImageId     = Private->Descriptor.ImageIndex;
 | |
|   Private->Descriptor.ImageIdName = GetImageTypeNameString ();
 | |
| 
 | |
|   //
 | |
|   // Get the hardware instance from FmpDeviceLib
 | |
|   //
 | |
|   Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);
 | |
|   if (Status == EFI_UNSUPPORTED) {
 | |
|     Private->Descriptor.HardwareInstance = 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Generate UEFI Variable names used to store status information for this
 | |
|   // FMP instance.
 | |
|   //
 | |
|   GenerateFmpVariableNames (Private);
 | |
| 
 | |
|   //
 | |
|   // Get the version.  Some devices don't support getting the firmware version
 | |
|   // at runtime.  If FmpDeviceLib does not support returning a version, then
 | |
|   // it is stored in a UEFI variable.
 | |
|   //
 | |
|   Status = FmpDeviceGetVersion (&Private->Descriptor.Version);
 | |
|   if (Status == EFI_UNSUPPORTED) {
 | |
|     Private->RuntimeVersionSupported = FALSE;
 | |
|     Private->Descriptor.Version      = GetVersionFromVariable (Private);
 | |
|   } else if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Unexpected error.   Use default version.
 | |
|     //
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString (), Status));
 | |
|     Private->Descriptor.Version = DEFAULT_VERSION;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free the current version name.  Shouldn't really happen but this populate
 | |
|   // function could be called multiple times (to refresh).
 | |
|   //
 | |
|   if (Private->Descriptor.VersionName != NULL) {
 | |
|     FreePool (Private->Descriptor.VersionName);
 | |
|     Private->Descriptor.VersionName = NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Attempt to get the version string from the FmpDeviceLib
 | |
|   //
 | |
|   Status = FmpDeviceGetVersionString (&Private->Descriptor.VersionName);
 | |
|   if (Status == EFI_UNSUPPORTED) {
 | |
|     DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName));
 | |
|     Private->Descriptor.VersionName = AllocateCopyPool (
 | |
|                                         sizeof (VERSION_STRING_NOT_SUPPORTED),
 | |
|                                         VERSION_STRING_NOT_SUPPORTED
 | |
|                                         );
 | |
|   } else if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName));
 | |
|     Private->Descriptor.VersionName = AllocateCopyPool (
 | |
|                                         sizeof (VERSION_STRING_NOT_AVAILABLE),
 | |
|                                         VERSION_STRING_NOT_AVAILABLE
 | |
|                                         );
 | |
|   }
 | |
| 
 | |
|   Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);
 | |
| 
 | |
|   //
 | |
|   // Get attributes from the FmpDeviceLib
 | |
|   //
 | |
|   FmpDeviceGetAttributes (
 | |
|     &Private->Descriptor.AttributesSupported,
 | |
|     &Private->Descriptor.AttributesSetting
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Force set the updatable bits in the attributes;
 | |
|   //
 | |
|   Private->Descriptor.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
 | |
|   Private->Descriptor.AttributesSetting   |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
 | |
| 
 | |
|   //
 | |
|   // Force set the authentication bits in the attributes;
 | |
|   //
 | |
|   Private->Descriptor.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
 | |
|   Private->Descriptor.AttributesSetting   |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
 | |
| 
 | |
|   Private->Descriptor.Compatibilities = 0;
 | |
| 
 | |
|   //
 | |
|   // Get the size of the firmware image from the FmpDeviceLib
 | |
|   //
 | |
|   Status = FmpDeviceGetSize (&Private->Descriptor.Size);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Private->Descriptor.Size = 0;
 | |
|   }
 | |
| 
 | |
|   Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);
 | |
|   Private->Descriptor.LastAttemptStatus  = GetLastAttemptStatusFromVariable (Private);
 | |
| 
 | |
|   //
 | |
|   // Get the dependency from the FmpDependencyDeviceLib.
 | |
|   //
 | |
|   Private->Descriptor.Dependencies = NULL;
 | |
| 
 | |
|   //
 | |
|   // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
 | |
|   //
 | |
|   if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
 | |
|     Private->Descriptor.Dependencies = GetFmpDependency (&DependenciesSize);
 | |
|   }
 | |
| 
 | |
|   Private->DescriptorPopulated = TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Returns information about the current firmware image(s) of the device.
 | |
| 
 | |
|   This function allows a copy of the current firmware image to be created and saved.
 | |
|   The saved copy could later been used, for example, in firmware image recovery or rollback.
 | |
| 
 | |
|   @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
 | |
|   @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
 | |
|                                      On input, this is the size of the buffer allocated by the caller.
 | |
|                                      On output, it is the size of the buffer returned by the firmware
 | |
|                                      if the buffer was large enough, or the size of the buffer needed
 | |
|                                      to contain the image(s) information if the buffer was too small.
 | |
|   @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
 | |
|                                      information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
 | |
|   @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
 | |
|                                      associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | |
|   @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
 | |
|                                      descriptors or firmware images within this device.
 | |
|   @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
 | |
|                                      of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | |
|   @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
 | |
|                                      The format is vendor specific and new version must have a greater value
 | |
|                                      than the old version. If PackageVersion is not supported, the value is
 | |
|                                      0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
 | |
|                                      is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
 | |
|                                      that package version update is in progress.
 | |
|   @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
 | |
|                                      package version name. The buffer is allocated by this function with
 | |
|                                      AllocatePool(), and it is the caller's responsibility to free it with a call
 | |
|                                      to FreePool().
 | |
| 
 | |
|   @retval EFI_SUCCESS                The device was successfully updated with the new image.
 | |
|   @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
 | |
|                                      needed to hold the image(s) information is returned in ImageInfoSize.
 | |
|   @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
 | |
|   @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GetTheImageInfo (
 | |
|   IN     EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
 | |
|   IN OUT UINTN                             *ImageInfoSize,
 | |
|   IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR     *ImageInfo,
 | |
|   OUT    UINT32                            *DescriptorVersion,
 | |
|   OUT    UINT8                             *DescriptorCount,
 | |
|   OUT    UINTN                             *DescriptorSize,
 | |
|   OUT    UINT32                            *PackageVersion,
 | |
|   OUT    CHAR16                            **PackageVersionName
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - This is NULL.\n", mImageIdName));
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve the private context structure
 | |
|   //
 | |
|   Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
 | |
|   FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
 | |
| 
 | |
|   //
 | |
|   // Check for valid pointer
 | |
|   //
 | |
|   if (ImageInfoSize == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName));
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check the buffer size
 | |
|   // NOTE: Check this first so caller can get the necessary memory size it must allocate.
 | |
|   //
 | |
|   if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) {
 | |
|     *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
 | |
|     DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName));
 | |
|     Status = EFI_BUFFER_TOO_SMALL;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Confirm that buffer isn't null
 | |
|   //
 | |
|   if (  (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)
 | |
|      || (PackageVersion == NULL))
 | |
|   {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName));
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set the size to whatever we need
 | |
|   //
 | |
|   *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
 | |
| 
 | |
|   //
 | |
|   // Make sure the descriptor has already been loaded or refreshed
 | |
|   //
 | |
|   PopulateDescriptor (Private);
 | |
| 
 | |
|   //
 | |
|   // Copy the image descriptor
 | |
|   //
 | |
|   CopyMem (ImageInfo, &Private->Descriptor, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));
 | |
| 
 | |
|   *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
 | |
|   *DescriptorCount   = 1;
 | |
|   *DescriptorSize    = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
 | |
|   //
 | |
|   // means unsupported
 | |
|   //
 | |
|   *PackageVersion = 0xFFFFFFFF;
 | |
| 
 | |
|   //
 | |
|   // Do not update PackageVersionName since it is not supported in this instance.
 | |
|   //
 | |
| 
 | |
| cleanup:
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Retrieves a copy of the current firmware image of the device.
 | |
| 
 | |
|   This function allows a copy of the current firmware image to be created and saved.
 | |
|   The saved copy could later been used, for example, in firmware image recovery or rollback.
 | |
| 
 | |
|   @param[in]      This           A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
 | |
|   @param[in]      ImageIndex     A unique number identifying the firmware image(s) within the device.
 | |
|                                  The number is between 1 and DescriptorCount.
 | |
|   @param[in, out] Image          Points to the buffer where the current image is copied to.
 | |
|   @param[in, out] ImageSize      On entry, points to the size of the buffer pointed to by Image, in bytes.
 | |
|                                  On return, points to the length of the image, in bytes.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The device was successfully updated with the new image.
 | |
|   @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
 | |
|                                  image. The current buffer size needed to hold the image is returned
 | |
|                                  in ImageSize.
 | |
|   @retval EFI_INVALID_PARAMETER  The Image was NULL.
 | |
|   @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
 | |
|   @retval EFI_UNSUPPORTED        The operation is not supported.
 | |
|   @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GetTheImage (
 | |
|   IN     EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
 | |
|   IN     UINT8                             ImageIndex,
 | |
|   IN OUT VOID                              *Image,
 | |
|   IN OUT UINTN                             *ImageSize
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;
 | |
|   UINTN                             Size;
 | |
| 
 | |
|   if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - This is NULL.\n", mImageIdName));
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve the private context structure
 | |
|   //
 | |
|   Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
 | |
|   FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
 | |
| 
 | |
|   //
 | |
|   // Check to make sure index is 1 (only 1 image for this device)
 | |
|   //
 | |
|   if (ImageIndex != 1) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName));
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   if (ImageSize == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName));
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check the buffer size
 | |
|   //
 | |
|   Status = FmpDeviceGetSize (&Size);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Size = 0;
 | |
|   }
 | |
| 
 | |
|   if (*ImageSize < Size) {
 | |
|     *ImageSize = Size;
 | |
|     DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));
 | |
|     Status = EFI_BUFFER_TOO_SMALL;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   if (Image == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   Status = FmpDeviceGetImage (Image, ImageSize);
 | |
| cleanup:
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Helper function to safely retrieve the FMP header from
 | |
|   within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
 | |
| 
 | |
|   @param[in]   Image                 Pointer to the image.
 | |
|   @param[in]   ImageSize             Size of the image.
 | |
|   @param[in]   AdditionalHeaderSize  Size of any headers that cannot be calculated by this function.
 | |
|   @param[out]  PayloadSize           An optional pointer to a UINTN that holds the size of the payload
 | |
|                                      (image size minus headers)
 | |
| 
 | |
|   @retval  !NULL  Valid pointer to the header.
 | |
|   @retval  NULL   Structure is bad and pointer cannot be found.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| GetFmpHeader (
 | |
|   IN  CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION  *Image,
 | |
|   IN  CONST UINTN                              ImageSize,
 | |
|   IN  CONST UINTN                              AdditionalHeaderSize,
 | |
|   OUT UINTN                                    *PayloadSize OPTIONAL
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Check to make sure that operation can be safely performed.
 | |
|   //
 | |
|   if ((((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize < (UINTN)Image) || \
 | |
|       (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize >= (UINTN)Image + ImageSize))
 | |
|   {
 | |
|     //
 | |
|     // Pointer overflow. Invalid image.
 | |
|     //
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   if (PayloadSize != NULL) {
 | |
|     *PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);
 | |
|   }
 | |
| 
 | |
|   return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength  + AdditionalHeaderSize);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Helper function to safely calculate the size of all headers
 | |
|   within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
 | |
| 
 | |
|   @param[in]  Image                 Pointer to the image.
 | |
|   @param[in]  AdditionalHeaderSize  Size of any headers that cannot be calculated by this function.
 | |
| 
 | |
|   @retval  UINT32>0  Valid size of all the headers.
 | |
|   @retval  0         Structure is bad and size cannot be found.
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| GetAllHeaderSize (
 | |
|   IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION  *Image,
 | |
|   IN UINT32                                   AdditionalHeaderSize
 | |
|   )
 | |
| {
 | |
|   UINT32  CalculatedSize;
 | |
| 
 | |
|   if (Image == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetAllHeaderSize() - Image is NULL.\n", mImageIdName));
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   CalculatedSize = sizeof (Image->MonotonicCount) +
 | |
|                    AdditionalHeaderSize +
 | |
|                    Image->AuthInfo.Hdr.dwLength;
 | |
| 
 | |
|   //
 | |
|   // Check to make sure that operation can be safely performed.
 | |
|   //
 | |
|   if ((CalculatedSize < sizeof (Image->MonotonicCount)) ||
 | |
|       (CalculatedSize < AdditionalHeaderSize) ||
 | |
|       (CalculatedSize < Image->AuthInfo.Hdr.dwLength))
 | |
|   {
 | |
|     //
 | |
|     // Integer overflow. Invalid image.
 | |
|     //
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   return CalculatedSize;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Checks if the firmware image is valid for the device.
 | |
| 
 | |
|   This function allows firmware update application to validate the firmware image without
 | |
|   invoking the SetImage() first.
 | |
| 
 | |
|   @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
 | |
|   @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
 | |
|                                  The number is between 1 and DescriptorCount.
 | |
|   @param[in]  Image              Points to the new image.
 | |
|   @param[in]  ImageSize          Size of the new image in bytes.
 | |
|   @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
 | |
|                                  if available, additional information if the image is invalid.
 | |
|   @param[out] LastAttemptStatus  A pointer to a UINT32 that holds the last attempt status to report
 | |
|                                  back to the ESRT table in case of error.  If an error does not occur,
 | |
|                                  this function will set the value to LAST_ATTEMPT_STATUS_SUCCESS.
 | |
| 
 | |
|                                  This function will return error codes that occur within this function
 | |
|                                  implementation within a driver range of last attempt error codes from
 | |
|                                  LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE
 | |
|                                  to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE.
 | |
| 
 | |
|                                  This function might also return error codes that occur within libraries
 | |
|                                  linked against this module that return last attempt error codes such as:
 | |
| 
 | |
|                                  LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE to
 | |
|                                  LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MAX_ERROR_CODE_VALUE
 | |
| 
 | |
|                                  LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE to
 | |
|                                  LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MAX_ERROR_CODE_VALUE
 | |
| 
 | |
|   @retval EFI_SUCCESS            The image was successfully checked.
 | |
|   @retval EFI_ABORTED            The operation is aborted.
 | |
|   @retval EFI_INVALID_PARAMETER  The Image was NULL.
 | |
|   @retval EFI_UNSUPPORTED        The operation is not supported.
 | |
|   @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CheckTheImageInternal (
 | |
|   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
 | |
|   IN  UINT8                             ImageIndex,
 | |
|   IN  CONST VOID                        *Image,
 | |
|   IN  UINTN                             ImageSize,
 | |
|   OUT UINT32                            *ImageUpdatable,
 | |
|   OUT UINT32                            *LastAttemptStatus
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   UINT32                            LocalLastAttemptStatus;
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;
 | |
|   UINTN                             RawSize;
 | |
|   VOID                              *FmpPayloadHeader;
 | |
|   UINTN                             FmpPayloadSize;
 | |
|   UINT32                            Version;
 | |
|   UINT32                            FmpHeaderSize;
 | |
|   UINTN                             AllHeaderSize;
 | |
|   UINT32                            Index;
 | |
|   VOID                              *PublicKeyData;
 | |
|   UINTN                             PublicKeyDataLength;
 | |
|   UINT8                             *PublicKeyDataXdr;
 | |
|   UINT8                             *PublicKeyDataXdrEnd;
 | |
|   EFI_FIRMWARE_IMAGE_DEP            *Dependencies;
 | |
|   UINT32                            DependenciesSize;
 | |
| 
 | |
|   Status                 = EFI_SUCCESS;
 | |
|   LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
 | |
|   RawSize                = 0;
 | |
|   FmpPayloadHeader       = NULL;
 | |
|   FmpPayloadSize         = 0;
 | |
|   Version                = 0;
 | |
|   FmpHeaderSize          = 0;
 | |
|   AllHeaderSize          = 0;
 | |
|   Dependencies           = NULL;
 | |
|   DependenciesSize       = 0;
 | |
| 
 | |
|   if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (LastAttemptStatus == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImageInternal() - LastAttemptStatus is NULL.\n", mImageIdName));
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // A last attempt status error code will always override the success
 | |
|   // value before returning from the function
 | |
|   //
 | |
|   *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - This is NULL.\n", mImageIdName));
 | |
|     Status             = EFI_INVALID_PARAMETER;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve the private context structure
 | |
|   //
 | |
|   Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
 | |
|   FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
 | |
| 
 | |
|   //
 | |
|   // Make sure the descriptor has already been loaded or refreshed
 | |
|   //
 | |
|   PopulateDescriptor (Private);
 | |
| 
 | |
|   if (ImageUpdatable == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));
 | |
|     Status             = EFI_INVALID_PARAMETER;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set to valid and then if any tests fail it will update this flag.
 | |
|   //
 | |
|   *ImageUpdatable = IMAGE_UPDATABLE_VALID;
 | |
| 
 | |
|   //
 | |
|   // Set to satisfied and then if dependency evaluates to false it will update this flag.
 | |
|   //
 | |
|   Private->DependenciesSatisfied = TRUE;
 | |
| 
 | |
|   if (Image == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
 | |
|     //
 | |
|     // not sure if this is needed
 | |
|     //
 | |
|     *ImageUpdatable    = IMAGE_UPDATABLE_INVALID;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED;
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   PublicKeyDataXdr    = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);
 | |
|   PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);
 | |
| 
 | |
|   if ((PublicKeyDataXdr == NULL) || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));
 | |
|     Status                 = EFI_ABORTED;
 | |
|     LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE;
 | |
|   } else {
 | |
|     //
 | |
|     // Try each key from PcdFmpDevicePkcs7CertBufferXdr
 | |
|     //
 | |
|     for (Index = 1; PublicKeyDataXdr < PublicKeyDataXdrEnd; Index++) {
 | |
|       Index++;
 | |
|       DEBUG (
 | |
|         (DEBUG_INFO,
 | |
|          "FmpDxe(%s): Certificate #%d [%p..%p].\n",
 | |
|          mImageIdName,
 | |
|          Index,
 | |
|          PublicKeyDataXdr,
 | |
|          PublicKeyDataXdrEnd
 | |
|         )
 | |
|         );
 | |
| 
 | |
|       if ((PublicKeyDataXdr + sizeof (UINT32)) > PublicKeyDataXdrEnd) {
 | |
|         //
 | |
|         // Key data extends beyond end of PCD
 | |
|         //
 | |
|         DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));
 | |
|         Status                 = EFI_ABORTED;
 | |
|         LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Read key length stored in big-endian format
 | |
|       //
 | |
|       PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr));
 | |
|       //
 | |
|       // Point to the start of the key data
 | |
|       //
 | |
|       PublicKeyDataXdr += sizeof (UINT32);
 | |
|       if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) {
 | |
|         //
 | |
|         // Key data extends beyond end of PCD
 | |
|         //
 | |
|         DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));
 | |
|         Status                 = EFI_ABORTED;
 | |
|         LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       PublicKeyData = PublicKeyDataXdr;
 | |
|       Status        = AuthenticateFmpImage (
 | |
|                         (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,
 | |
|                         ImageSize,
 | |
|                         PublicKeyData,
 | |
|                         PublicKeyDataLength
 | |
|                         );
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       PublicKeyDataXdr += PublicKeyDataLength;
 | |
|       PublicKeyDataXdr  = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));
 | |
|     if (LocalLastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
 | |
|       *LastAttemptStatus = LocalLastAttemptStatus;
 | |
|     } else {
 | |
|       *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE;
 | |
|     }
 | |
| 
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check to make sure index is 1
 | |
|   //
 | |
|   if (ImageIndex != 1) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));
 | |
|     *ImageUpdatable    = IMAGE_UPDATABLE_INVALID_TYPE;
 | |
|     Status             = EFI_INVALID_PARAMETER;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get the dependency from Image.
 | |
|   //
 | |
|   Dependencies =  GetImageDependency (
 | |
|                     (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,
 | |
|                     ImageSize,
 | |
|                     &DependenciesSize,
 | |
|                     LastAttemptStatus
 | |
|                     );
 | |
|   if (*LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
 | |
|     Status = EFI_ABORTED;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check the FmpPayloadHeader
 | |
|   //
 | |
|   FmpPayloadHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);
 | |
|   if (FmpPayloadHeader == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
 | |
|     Status             = EFI_ABORTED;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
 | |
|     *ImageUpdatable    = IMAGE_UPDATABLE_INVALID;
 | |
|     Status             = EFI_SUCCESS;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check the lowest supported version
 | |
|   //
 | |
|   if (Version < Private->Descriptor.LowestSupportedImageVersion) {
 | |
|     DEBUG (
 | |
|       (DEBUG_ERROR,
 | |
|        "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
 | |
|        mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)
 | |
|       );
 | |
|     *ImageUpdatable    = IMAGE_UPDATABLE_INVALID_OLD;
 | |
|     Status             = EFI_SUCCESS;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Evaluate dependency expression
 | |
|   //
 | |
|   Private->DependenciesSatisfied =  CheckFmpDependency (
 | |
|                                       Private->Descriptor.ImageTypeId,
 | |
|                                       Version,
 | |
|                                       Dependencies,
 | |
|                                       DependenciesSize,
 | |
|                                       &LocalLastAttemptStatus
 | |
|                                       );
 | |
|   if (!Private->DependenciesSatisfied) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));
 | |
|     *ImageUpdatable    = IMAGE_UPDATABLE_INVALID;
 | |
|     Status             = EFI_SUCCESS;
 | |
|     *LastAttemptStatus = LocalLastAttemptStatus;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get the FmpHeaderSize so we can determine the real payload size
 | |
|   //
 | |
|   Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));
 | |
|     *ImageUpdatable    = IMAGE_UPDATABLE_INVALID;
 | |
|     Status             = EFI_SUCCESS;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Call FmpDevice Lib Check Image on the
 | |
|   // Raw payload.  So all headers need stripped off
 | |
|   //
 | |
|   AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
 | |
|   if (AllHeaderSize == 0) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
 | |
|     Status             = EFI_ABORTED;
 | |
|     *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   RawSize = ImageSize - AllHeaderSize;
 | |
| 
 | |
|   //
 | |
|   // FmpDeviceLib CheckImage function to do any specific checks
 | |
|   //
 | |
|   Status = FmpDeviceCheckImageWithStatus ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable, LastAttemptStatus);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));
 | |
| 
 | |
|     //
 | |
|     // LastAttemptStatus returned from the device library should fall within the designated error range
 | |
|     // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]
 | |
|     //
 | |
|     if ((*LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||
 | |
|         (*LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))
 | |
|     {
 | |
|       DEBUG (
 | |
|         (DEBUG_ERROR,
 | |
|          "FmpDxe(%s): CheckTheImage() - LastAttemptStatus %d from FmpDeviceCheckImageWithStatus() is invalid.\n",
 | |
|          mImageIdName,
 | |
|          *LastAttemptStatus)
 | |
|         );
 | |
|       *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| cleanup:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Checks if the firmware image is valid for the device.
 | |
| 
 | |
|   This function allows firmware update application to validate the firmware image without
 | |
|   invoking the SetImage() first.
 | |
| 
 | |
|   @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
 | |
|   @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
 | |
|                                  The number is between 1 and DescriptorCount.
 | |
|   @param[in]  Image              Points to the new image.
 | |
|   @param[in]  ImageSize          Size of the new image in bytes.
 | |
|   @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
 | |
|                                  if available, additional information if the image is invalid.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The image was successfully checked.
 | |
|   @retval EFI_ABORTED            The operation is aborted.
 | |
|   @retval EFI_INVALID_PARAMETER  The Image was NULL.
 | |
|   @retval EFI_UNSUPPORTED        The operation is not supported.
 | |
|   @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CheckTheImage (
 | |
|   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
 | |
|   IN  UINT8                             ImageIndex,
 | |
|   IN  CONST VOID                        *Image,
 | |
|   IN  UINTN                             ImageSize,
 | |
|   OUT UINT32                            *ImageUpdatable
 | |
|   )
 | |
| {
 | |
|   UINT32  LastAttemptStatus;
 | |
| 
 | |
|   return CheckTheImageInternal (This, ImageIndex, Image, ImageSize, ImageUpdatable, &LastAttemptStatus);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Updates the firmware image of the device.
 | |
| 
 | |
|   This function updates the hardware with the new firmware image.
 | |
|   This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
 | |
|   If the firmware image is updatable, the function should perform the following minimal validations
 | |
|   before proceeding to do the firmware image update.
 | |
|   - Validate the image authentication if image has attribute
 | |
|     IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
 | |
|     EFI_SECURITY_VIOLATION if the validation fails.
 | |
|   - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
 | |
|     the image is unsupported. The function can optionally provide more detailed information on
 | |
|     why the image is not a supported image.
 | |
|   - Validate the data from VendorCode if not null. Image validation must be performed before
 | |
|     VendorCode data validation. VendorCode data is ignored or considered invalid if image
 | |
|     validation failed. The function returns EFI_ABORTED if the data is invalid.
 | |
| 
 | |
|   VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
 | |
|   the caller did not specify the policy or use the default policy. As an example, vendor can implement
 | |
|   a policy to allow an option to force a firmware image update when the abort reason is due to the new
 | |
|   firmware image version is older than the current firmware image version or bad image checksum.
 | |
|   Sensitive operations such as those wiping the entire firmware image and render the device to be
 | |
|   non-functional should be encoded in the image itself rather than passed with the VendorCode.
 | |
|   AbortReason enables vendor to have the option to provide a more detailed description of the abort
 | |
|   reason to the caller.
 | |
| 
 | |
|   @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
 | |
|   @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
 | |
|                                  The number is between 1 and DescriptorCount.
 | |
|   @param[in]  Image              Points to the new image.
 | |
|   @param[in]  ImageSize          Size of the new image in bytes.
 | |
|   @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
 | |
|                                  Null indicates the caller did not specify the policy or use the default policy.
 | |
|   @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
 | |
|   @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
 | |
|                                  details for the aborted operation. The buffer is allocated by this function
 | |
|                                  with AllocatePool(), and it is the caller's responsibility to free it with a
 | |
|                                  call to FreePool().
 | |
| 
 | |
|   @retval EFI_SUCCESS            The device was successfully updated with the new image.
 | |
|   @retval EFI_ABORTED            The operation is aborted.
 | |
|   @retval EFI_INVALID_PARAMETER  The Image was NULL.
 | |
|   @retval EFI_UNSUPPORTED        The operation is not supported.
 | |
|   @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SetTheImage (
 | |
|   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL               *This,
 | |
|   IN  UINT8                                          ImageIndex,
 | |
|   IN  CONST VOID                                     *Image,
 | |
|   IN  UINTN                                          ImageSize,
 | |
|   IN  CONST VOID                                     *VendorCode,
 | |
|   IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress,
 | |
|   OUT CHAR16                                         **AbortReason
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;
 | |
|   UINT32                            Updateable;
 | |
|   BOOLEAN                           BooleanValue;
 | |
|   UINT32                            FmpHeaderSize;
 | |
|   VOID                              *FmpHeader;
 | |
|   UINTN                             FmpPayloadSize;
 | |
|   UINT32                            AllHeaderSize;
 | |
|   UINT32                            IncomingFwVersion;
 | |
|   UINT32                            LastAttemptStatus;
 | |
|   UINT32                            Version;
 | |
|   UINT32                            LowestSupportedVersion;
 | |
|   EFI_FIRMWARE_IMAGE_DEP            *Dependencies;
 | |
|   UINT32                            DependenciesSize;
 | |
| 
 | |
|   Status            = EFI_SUCCESS;
 | |
|   Private           = NULL;
 | |
|   Updateable        = 0;
 | |
|   BooleanValue      = FALSE;
 | |
|   FmpHeaderSize     = 0;
 | |
|   FmpHeader         = NULL;
 | |
|   FmpPayloadSize    = 0;
 | |
|   AllHeaderSize     = 0;
 | |
|   IncomingFwVersion = 0;
 | |
|   LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
 | |
|   Dependencies      = NULL;
 | |
|   DependenciesSize  = 0;
 | |
| 
 | |
|   if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - This is NULL.\n", mImageIdName));
 | |
|     Status            = EFI_INVALID_PARAMETER;
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve the private context structure
 | |
|   //
 | |
|   Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
 | |
|   FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
 | |
| 
 | |
|   //
 | |
|   // Make sure the descriptor has already been loaded or refreshed
 | |
|   //
 | |
|   PopulateDescriptor (Private);
 | |
| 
 | |
|   //
 | |
|   // Set to 0 to clear any previous results.
 | |
|   //
 | |
|   SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
 | |
| 
 | |
|   //
 | |
|   // if we have locked the device, then skip the set operation.
 | |
|   // it should be blocked by hardware too but we can catch here even faster
 | |
|   //
 | |
|   if (Private->FmpDeviceLocked) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked.  Can't update.\n", mImageIdName));
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED;
 | |
|     Status            = EFI_UNSUPPORTED;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Call check image to verify the image
 | |
|   //
 | |
|   Status = CheckTheImageInternal (This, ImageIndex, Image, ImageSize, &Updateable, &LastAttemptStatus);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get the dependency from Image.
 | |
|   //
 | |
|   Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize, &LastAttemptStatus);
 | |
| 
 | |
|   //
 | |
|   // No functional error in CheckTheImage.  Attempt to get the Version to
 | |
|   // support better error reporting.
 | |
|   //
 | |
|   FmpHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);
 | |
|   if (FmpHeader == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;
 | |
|     Status            = EFI_ABORTED;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Set to actual value
 | |
|     //
 | |
|     SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
 | |
|   }
 | |
| 
 | |
|   if (Updateable != IMAGE_UPDATABLE_VALID) {
 | |
|     DEBUG (
 | |
|       (DEBUG_ERROR,
 | |
|        "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update.  Updatable value = 0x%X.\n",
 | |
|        mImageIdName, Updateable)
 | |
|       );
 | |
|     if (Private->DependenciesSatisfied == FALSE) {
 | |
|       LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
 | |
|     }
 | |
| 
 | |
|     Status = EFI_ABORTED;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   if (Progress == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR;
 | |
|     Status            = EFI_INVALID_PARAMETER;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   mProgressFunc = Progress;
 | |
| 
 | |
|   //
 | |
|   // Checking the image is at least 1%
 | |
|   //
 | |
|   Status = Progress (1);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status));
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check System Power
 | |
|   //
 | |
|   Status = CheckSystemPower (&BooleanValue);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   if (!BooleanValue) {
 | |
|     Status = EFI_ABORTED;
 | |
|     DEBUG (
 | |
|       (DEBUG_ERROR,
 | |
|        "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False.  Update not allowed due to System Power.\n", mImageIdName)
 | |
|       );
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   Progress (2);
 | |
| 
 | |
|   //
 | |
|   // Check System Thermal
 | |
|   //
 | |
|   Status = CheckSystemThermal (&BooleanValue);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   if (!BooleanValue) {
 | |
|     Status            = EFI_ABORTED;
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL;
 | |
|     DEBUG (
 | |
|       (DEBUG_ERROR,
 | |
|        "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False.  Update not allowed due to System Thermal.\n", mImageIdName)
 | |
|       );
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   Progress (3);
 | |
| 
 | |
|   //
 | |
|   // Check System Environment
 | |
|   //
 | |
|   Status = CheckSystemEnvironment (&BooleanValue);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   if (!BooleanValue) {
 | |
|     Status            = EFI_ABORTED;
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV;
 | |
|     DEBUG (
 | |
|       (DEBUG_ERROR,
 | |
|        "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False.  Update not allowed due to System Environment.\n", mImageIdName)
 | |
|       );
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   Progress (4);
 | |
| 
 | |
|   //
 | |
|   // Save LastAttemptStatus as error so that if SetImage never returns the error
 | |
|   // state is recorded.
 | |
|   //
 | |
|   SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
 | |
| 
 | |
|   //
 | |
|   // Strip off all the headers so the device can process its firmware
 | |
|   //
 | |
|   Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
 | |
|   if (AllHeaderSize == 0) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
 | |
|     LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;
 | |
|     Status            = EFI_ABORTED;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Indicate that control is handed off to FmpDeviceLib
 | |
|   //
 | |
|   Progress (5);
 | |
| 
 | |
|   //
 | |
|   // Copy the requested image to the firmware using the FmpDeviceLib
 | |
|   //
 | |
|   Status = FmpDeviceSetImageWithStatus (
 | |
|              (((UINT8 *)Image) + AllHeaderSize),
 | |
|              ImageSize - AllHeaderSize,
 | |
|              VendorCode,
 | |
|              FmpDxeProgress,
 | |
|              IncomingFwVersion,
 | |
|              AbortReason,
 | |
|              &LastAttemptStatus
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status =  %r.\n", mImageIdName, Status));
 | |
| 
 | |
|     //
 | |
|     // LastAttemptStatus returned from the device library should fall within the designated error range
 | |
|     // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]
 | |
|     //
 | |
|     if ((LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||
 | |
|         (LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))
 | |
|     {
 | |
|       DEBUG (
 | |
|         (DEBUG_ERROR,
 | |
|          "FmpDxe(%s): SetTheImage() - LastAttemptStatus %d from FmpDeviceSetImageWithStatus() is invalid.\n",
 | |
|          mImageIdName,
 | |
|          LastAttemptStatus)
 | |
|         );
 | |
|       LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
 | |
|     }
 | |
| 
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Store the dependency
 | |
|   //
 | |
|   if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
 | |
|     Status = SaveFmpDependency (Dependencies, DependenciesSize);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName, Status));
 | |
|     }
 | |
| 
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Finished the update without error
 | |
|   // Indicate that control has been returned from FmpDeviceLib
 | |
|   //
 | |
|   Progress (99);
 | |
| 
 | |
|   //
 | |
|   // Update the version stored in variable
 | |
|   //
 | |
|   if (!Private->RuntimeVersionSupported) {
 | |
|     Version = DEFAULT_VERSION;
 | |
|     GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);
 | |
|     SetVersionInVariable (Private, Version);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Update lowest supported variable
 | |
|   //
 | |
|   LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
 | |
|   GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);
 | |
|   SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);
 | |
| 
 | |
|   LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
 | |
| 
 | |
| cleanup:
 | |
|   mProgressFunc = NULL;
 | |
| 
 | |
|   if (Private != NULL) {
 | |
|     DEBUG ((DEBUG_INFO, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName, LastAttemptStatus));
 | |
|     SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
 | |
|   }
 | |
| 
 | |
|   if (Progress != NULL) {
 | |
|     //
 | |
|     // Set progress to 100 after everything is done including recording Status.
 | |
|     //
 | |
|     Progress (100);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Need repopulate after SetImage is called to
 | |
|   // update LastAttemptVersion and LastAttemptStatus.
 | |
|   //
 | |
|   if (Private != NULL) {
 | |
|     Private->DescriptorPopulated = FALSE;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Returns information about the firmware package.
 | |
| 
 | |
|   This function returns package information.
 | |
| 
 | |
|   @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
 | |
|   @param[out] PackageVersion           A version number that represents all the firmware images in the device.
 | |
|                                        The format is vendor specific and new version must have a greater value
 | |
|                                        than the old version. If PackageVersion is not supported, the value is
 | |
|                                        0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
 | |
|                                        comparison is to be performed using PackageVersionName. A value of
 | |
|                                        0xFFFFFFFD indicates that package version update is in progress.
 | |
|   @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
 | |
|                                        the package version name. The buffer is allocated by this function with
 | |
|                                        AllocatePool(), and it is the caller's responsibility to free it with a
 | |
|                                        call to FreePool().
 | |
|   @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
 | |
|                                        package version name. A value of 0 indicates the device does not support
 | |
|                                        update of package version name. Length is the number of Unicode characters,
 | |
|                                        including the terminating null character.
 | |
|   @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
 | |
|                                        Definitions' for possible returned values of this parameter. A value of 1
 | |
|                                        indicates the attribute is supported and the current setting value is
 | |
|                                        indicated in AttributesSetting. A value of 0 indicates the attribute is not
 | |
|                                        supported and the current setting value in AttributesSetting is meaningless.
 | |
|   @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
 | |
|                                        values of this parameter
 | |
| 
 | |
|   @retval EFI_SUCCESS                  The package information was successfully returned.
 | |
|   @retval EFI_UNSUPPORTED              The operation is not supported.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GetPackageInfo (
 | |
|   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
 | |
|   OUT UINT32                            *PackageVersion,
 | |
|   OUT CHAR16                            **PackageVersionName,
 | |
|   OUT UINT32                            *PackageVersionNameMaxLen,
 | |
|   OUT UINT64                            *AttributesSupported,
 | |
|   OUT UINT64                            *AttributesSetting
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Updates information about the firmware package.
 | |
| 
 | |
|   This function updates package information.
 | |
|   This function returns EFI_UNSUPPORTED if the package information is not updatable.
 | |
|   VendorCode enables vendor to implement vendor-specific package information update policy.
 | |
|   Null if the caller did not specify this policy or use the default policy.
 | |
| 
 | |
|   @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
 | |
|   @param[in]  Image              Points to the authentication image.
 | |
|                                  Null if authentication is not required.
 | |
|   @param[in]  ImageSize          Size of the authentication image in bytes.
 | |
|                                  0 if authentication is not required.
 | |
|   @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
 | |
|                                  image update policy.
 | |
|                                  Null indicates the caller did not specify this policy or use
 | |
|                                  the default policy.
 | |
|   @param[in]  PackageVersion     The new package version.
 | |
|   @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
 | |
|                                  the package version name.
 | |
|                                  The string length is equal to or less than the value returned in
 | |
|                                  PackageVersionNameMaxLen.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The device was successfully updated with the new package
 | |
|                                  information.
 | |
|   @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
 | |
|                                  returned in PackageVersionNameMaxLen.
 | |
|   @retval EFI_UNSUPPORTED        The operation is not supported.
 | |
|   @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SetPackageInfo (
 | |
|   IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
 | |
|   IN CONST VOID                        *Image,
 | |
|   IN UINTN                             ImageSize,
 | |
|   IN CONST VOID                        *VendorCode,
 | |
|   IN UINT32                            PackageVersion,
 | |
|   IN CONST CHAR16                      *PackageVersionName
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Event notification function that is invoked when the event GUID specified by
 | |
|   PcdFmpDeviceLockEventGuid is signaled.
 | |
| 
 | |
|   @param[in] Event    Event whose notification function is being invoked.
 | |
|   @param[in] Context  The pointer to the notification function's context,
 | |
|                       which is implementation-dependent.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| FmpDxeLockEventNotify (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;
 | |
| 
 | |
|   if (Context == NULL) {
 | |
|     ASSERT (Context != NULL);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;
 | |
| 
 | |
|   if (!Private->FmpDeviceLocked) {
 | |
|     //
 | |
|     // Lock the firmware device
 | |
|     //
 | |
|     FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
 | |
|     Status = FmpDeviceLock ();
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       if (Status != EFI_UNSUPPORTED) {
 | |
|         DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error.  Status = %r\n", mImageIdName, Status));
 | |
|       } else {
 | |
|         DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error.  Status = %r\n", mImageIdName, Status));
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Private->FmpDeviceLocked = TRUE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function to install FMP instance.
 | |
| 
 | |
|   @param[in]  Handle  The device handle to install a FMP instance on.
 | |
| 
 | |
|   @retval  EFI_SUCCESS            FMP Installed
 | |
|   @retval  EFI_INVALID_PARAMETER  Handle was invalid
 | |
|   @retval  other                  Error installing FMP
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InstallFmpInstance (
 | |
|   IN EFI_HANDLE  Handle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;
 | |
| 
 | |
|   //
 | |
|   // Only allow a single FMP Protocol instance to be installed
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Handle,
 | |
|                   &gEfiFirmwareManagementProtocolGuid,
 | |
|                   (VOID **)&Fmp,
 | |
|                   NULL,
 | |
|                   NULL,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     return EFI_ALREADY_STARTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Allocate FMP Protocol instance
 | |
|   //
 | |
|   Private = AllocateCopyPool (
 | |
|               sizeof (mFirmwareManagementPrivateDataTemplate),
 | |
|               &mFirmwareManagementPrivateDataTemplate
 | |
|               );
 | |
|   if (Private == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName));
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Initialize private context data structure
 | |
|   //
 | |
|   Private->Handle           = Handle;
 | |
|   Private->FmpDeviceContext = NULL;
 | |
|   Status                    = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
 | |
|   if (Status == EFI_UNSUPPORTED) {
 | |
|     Private->FmpDeviceContext = NULL;
 | |
|   } else if (EFI_ERROR (Status)) {
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Make sure the descriptor has already been loaded or refreshed
 | |
|   //
 | |
|   PopulateDescriptor (Private);
 | |
| 
 | |
|   if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
 | |
|     //
 | |
|     // Register all UEFI Variables used by this module to be locked.
 | |
|     //
 | |
|     Status = LockAllFmpVariables (Private);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock.  Status = %r.\n", mImageIdName, Status));
 | |
|     } else {
 | |
|       DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName));
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Create and register notify function to lock the FMP device.
 | |
|     //
 | |
|     Status = gBS->CreateEventEx (
 | |
|                     EVT_NOTIFY_SIGNAL,
 | |
|                     TPL_CALLBACK,
 | |
|                     FmpDxeLockEventNotify,
 | |
|                     Private,
 | |
|                     mLockGuid,
 | |
|                     &Private->FmpDeviceLockEvent
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification.  Status = %r\n", mImageIdName, Status));
 | |
|     }
 | |
| 
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   } else {
 | |
|     DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Install FMP Protocol and FMP Progress Protocol
 | |
|   //
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   &Private->Handle,
 | |
|                   &gEfiFirmwareManagementProtocolGuid,
 | |
|                   &Private->Fmp,
 | |
|                   &gEdkiiFirmwareManagementProgressProtocolGuid,
 | |
|                   &mFmpProgress,
 | |
|                   NULL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));
 | |
|     goto cleanup;
 | |
|   }
 | |
| 
 | |
| cleanup:
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (Private != NULL) {
 | |
|       if (Private->FmpDeviceLockEvent != NULL) {
 | |
|         gBS->CloseEvent (Private->FmpDeviceLockEvent);
 | |
|       }
 | |
| 
 | |
|       if (Private->Descriptor.VersionName != NULL) {
 | |
|         FreePool (Private->Descriptor.VersionName);
 | |
|       }
 | |
| 
 | |
|       if (Private->FmpDeviceContext != NULL) {
 | |
|         FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
 | |
|       }
 | |
| 
 | |
|       if (Private->VersionVariableName != NULL) {
 | |
|         FreePool (Private->VersionVariableName);
 | |
|       }
 | |
| 
 | |
|       if (Private->LsvVariableName != NULL) {
 | |
|         FreePool (Private->LsvVariableName);
 | |
|       }
 | |
| 
 | |
|       if (Private->LastAttemptStatusVariableName != NULL) {
 | |
|         FreePool (Private->LastAttemptStatusVariableName);
 | |
|       }
 | |
| 
 | |
|       if (Private->LastAttemptVersionVariableName != NULL) {
 | |
|         FreePool (Private->LastAttemptVersionVariableName);
 | |
|       }
 | |
| 
 | |
|       if (Private->FmpStateVariableName != NULL) {
 | |
|         FreePool (Private->FmpStateVariableName);
 | |
|       }
 | |
| 
 | |
|       FreePool (Private);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function to uninstall FMP instance.
 | |
| 
 | |
|   @param[in]  Handle  The device handle to install a FMP instance on.
 | |
| 
 | |
|   @retval  EFI_SUCCESS            FMP Installed
 | |
|   @retval  EFI_INVALID_PARAMETER  Handle was invalid
 | |
|   @retval  other                  Error installing FMP
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UninstallFmpInstance (
 | |
|   IN EFI_HANDLE  Handle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | |
|   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Handle,
 | |
|                   &gEfiFirmwareManagementProtocolGuid,
 | |
|                   (VOID **)&Fmp,
 | |
|                   NULL,
 | |
|                   NULL,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status));
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp);
 | |
|   FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
 | |
| 
 | |
|   if (Private->FmpDeviceLockEvent != NULL) {
 | |
|     gBS->CloseEvent (Private->FmpDeviceLockEvent);
 | |
|   }
 | |
| 
 | |
|   Status = gBS->UninstallMultipleProtocolInterfaces (
 | |
|                   Private->Handle,
 | |
|                   &gEfiFirmwareManagementProtocolGuid,
 | |
|                   &Private->Fmp,
 | |
|                   &gEdkiiFirmwareManagementProgressProtocolGuid,
 | |
|                   &mFmpProgress,
 | |
|                   NULL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status));
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (Private->Descriptor.VersionName != NULL) {
 | |
|     FreePool (Private->Descriptor.VersionName);
 | |
|   }
 | |
| 
 | |
|   if (Private->FmpDeviceContext != NULL) {
 | |
|     FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
 | |
|   }
 | |
| 
 | |
|   if (Private->VersionVariableName != NULL) {
 | |
|     FreePool (Private->VersionVariableName);
 | |
|   }
 | |
| 
 | |
|   if (Private->LsvVariableName != NULL) {
 | |
|     FreePool (Private->LsvVariableName);
 | |
|   }
 | |
| 
 | |
|   if (Private->LastAttemptStatusVariableName != NULL) {
 | |
|     FreePool (Private->LastAttemptStatusVariableName);
 | |
|   }
 | |
| 
 | |
|   if (Private->LastAttemptVersionVariableName != NULL) {
 | |
|     FreePool (Private->LastAttemptVersionVariableName);
 | |
|   }
 | |
| 
 | |
|   if (Private->FmpStateVariableName != NULL) {
 | |
|     FreePool (Private->FmpStateVariableName);
 | |
|   }
 | |
| 
 | |
|   FreePool (Private);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Unloads the application and its installed protocol.
 | |
| 
 | |
|   @param ImageHandle       Handle that identifies the image to be unloaded.
 | |
|   @param  SystemTable      The system table.
 | |
| 
 | |
|   @retval EFI_SUCCESS      The image has been unloaded.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FmpDxeLibDestructor (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   if (mFmpSingleInstance) {
 | |
|     return UninstallFmpInstance (ImageHandle);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Main entry for this driver/library.
 | |
| 
 | |
|   @param[in] ImageHandle  Image handle this driver.
 | |
|   @param[in] SystemTable  Pointer to SystemTable.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FmpDxeEntryPoint (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // Verify that a new FILE_GUID value has been provided in the <Defines>
 | |
|   // section of this module.  The FILE_GUID is the ESRT GUID that must be
 | |
|   // unique for each updatable firmware image.
 | |
|   //
 | |
|   if (CompareGuid (&mDefaultModuleFileGuid, &gEfiCallerIdGuid)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe: Use of default FILE_GUID detected.  FILE_GUID must be set to a unique value.\n"));
 | |
|     ASSERT (FALSE);
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.
 | |
|   //
 | |
|   mImageIdName = (CHAR16 *)PcdGetPtr (PcdFmpDeviceImageIdName);
 | |
|   if ((PcdGetSize (PcdFmpDeviceImageIdName) <= 2) || (mImageIdName[0] == 0)) {
 | |
|     //
 | |
|     // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
 | |
|     //
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%g): PcdFmpDeviceImageIdName is an empty string.\n", &gEfiCallerIdGuid));
 | |
|     ASSERT (FALSE);
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
 | |
|   //
 | |
|   DetectTestKey ();
 | |
| 
 | |
|   //
 | |
|   // Fill in FMP Progress Protocol fields for Version 1
 | |
|   //
 | |
|   mFmpProgress.Version                        = 1;
 | |
|   mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
 | |
|   mFmpProgress.WatchdogSeconds                = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
 | |
| 
 | |
|   // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
 | |
|   // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
 | |
|   // gEfiEndOfDxeEventGroupGuid is used.
 | |
|   //
 | |
|   mLockGuid = &gEfiEndOfDxeEventGroupGuid;
 | |
|   if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {
 | |
|     mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));
 | |
| 
 | |
|   //
 | |
|   // Register with library the install function so if the library uses
 | |
|   // UEFI driver model/driver binding protocol it can install FMP on its device handle
 | |
|   // If library is simple lib that does not use driver binding then it should return
 | |
|   // unsupported and this will install the FMP instance on the ImageHandle
 | |
|   //
 | |
|   Status = RegisterFmpInstaller (InstallFmpInstance);
 | |
|   if (Status == EFI_UNSUPPORTED) {
 | |
|     mFmpSingleInstance = TRUE;
 | |
|     DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED.  Installing single FMP instance.\n", mImageIdName));
 | |
|     Status = RegisterFmpUninstaller (UninstallFmpInstance);
 | |
|     if (Status == EFI_UNSUPPORTED) {
 | |
|       Status = InstallFmpInstance (ImageHandle);
 | |
|     } else {
 | |
|       DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));
 | |
|       Status = EFI_UNSUPPORTED;
 | |
|     }
 | |
|   } else if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r.  No FMP installed.\n", mImageIdName, Status));
 | |
|   } else {
 | |
|     DEBUG ((
 | |
|       DEBUG_INFO,
 | |
|       "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS.  Expect FMP to be installed during the BDS/Device connection phase.\n",
 | |
|       mImageIdName
 | |
|       ));
 | |
|     Status = RegisterFmpUninstaller (UninstallFmpInstance);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 |