Original code GetFmpImageDescriptors for OriginalFmpImageInfoBuf pointer, if failed, return a NULL pointer. The OriginalFmpImageInfoBuf should not be NULL and the NULL pointer dereference case should be false positive. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Chao Zhang <chao.b.zhang@intel.com> Signed-off-by: Vin Xue <vinxue@outlook.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
		
			
				
	
	
		
			888 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			888 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  SetImage instance to update system firmware.
 | 
						|
 | 
						|
  Caution: This module requires additional review when modified.
 | 
						|
  This module will have external input - capsule image.
 | 
						|
  This external input must be validated carefully to avoid security issue like
 | 
						|
  buffer overflow, integer overflow.
 | 
						|
 | 
						|
  FmpSetImage() will receive untrusted input and do basic validation.
 | 
						|
 | 
						|
  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "SystemFirmwareDxe.h"
 | 
						|
 | 
						|
//
 | 
						|
// SystemFmp driver private data
 | 
						|
//
 | 
						|
SYSTEM_FMP_PRIVATE_DATA *mSystemFmpPrivate = NULL;
 | 
						|
 | 
						|
EFI_GUID mCurrentImageTypeId;
 | 
						|
 | 
						|
BOOLEAN  mNvRamUpdated = FALSE;
 | 
						|
 | 
						|
/**
 | 
						|
  Parse Config data file to get the updated data array.
 | 
						|
 | 
						|
  @param[in]      DataBuffer      Config raw file buffer.
 | 
						|
  @param[in]      BufferSize      Size of raw buffer.
 | 
						|
  @param[in, out] ConfigHeader    Pointer to the config header.
 | 
						|
  @param[in, out] UpdateArray     Pointer to the config of update data.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND         No config data is found.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
 | 
						|
  @retval EFI_SUCCESS           Parse the config file successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ParseUpdateDataFile (
 | 
						|
  IN      UINT8                         *DataBuffer,
 | 
						|
  IN      UINTN                         BufferSize,
 | 
						|
  IN OUT  CONFIG_HEADER                 *ConfigHeader,
 | 
						|
  IN OUT  UPDATE_CONFIG_DATA            **UpdateArray
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Update System Firmware image component.
 | 
						|
 | 
						|
  @param[in]  SystemFirmwareImage     Points to the System Firmware image.
 | 
						|
  @param[in]  SystemFirmwareImageSize The length of the System Firmware image in bytes.
 | 
						|
  @param[in]  ConfigData              Points to the component configuration structure.
 | 
						|
  @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[in]  Progress                A function used by the driver to report the progress of the firmware update.
 | 
						|
  @param[in]  StartPercentage         The start completion percentage value that may be used to report progress during the flash write operation.
 | 
						|
  @param[in]  EndPercentage           The end completion percentage value that may be used to report progress during the flash write operation.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The System Firmware image is updated.
 | 
						|
  @retval EFI_WRITE_PROTECTED     The flash device is read only.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PerformUpdate (
 | 
						|
  IN VOID                                           *SystemFirmwareImage,
 | 
						|
  IN UINTN                                          SystemFirmwareImageSize,
 | 
						|
  IN UPDATE_CONFIG_DATA                             *ConfigData,
 | 
						|
  OUT UINT32                                        *LastAttemptVersion,
 | 
						|
  OUT UINT32                                        *LastAttemptStatus,
 | 
						|
  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress,
 | 
						|
  IN UINTN                                          StartPercentage,
 | 
						|
  IN UINTN                                          EndPercentage
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
 | 
						|
  DEBUG((DEBUG_INFO, "PlatformUpdate:"));
 | 
						|
  DEBUG((DEBUG_INFO, "  BaseAddress - 0x%lx,", ConfigData->BaseAddress));
 | 
						|
  DEBUG((DEBUG_INFO, "  ImageOffset - 0x%x,", ConfigData->ImageOffset));
 | 
						|
  DEBUG((DEBUG_INFO, "  Legnth - 0x%x\n", ConfigData->Length));
 | 
						|
  if (Progress != NULL) {
 | 
						|
    Progress (StartPercentage);
 | 
						|
  }
 | 
						|
  Status = PerformFlashWriteWithProgress (
 | 
						|
             ConfigData->FirmwareType,
 | 
						|
             ConfigData->BaseAddress,
 | 
						|
             ConfigData->AddressType,
 | 
						|
             (VOID *)((UINTN)SystemFirmwareImage + (UINTN)ConfigData->ImageOffset),
 | 
						|
             ConfigData->Length,
 | 
						|
             Progress,
 | 
						|
             StartPercentage,
 | 
						|
             EndPercentage
 | 
						|
             );
 | 
						|
  if (Progress != NULL) {
 | 
						|
    Progress (EndPercentage);
 | 
						|
  }
 | 
						|
  if (!EFI_ERROR(Status)) {
 | 
						|
    *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
 | 
						|
    if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) {
 | 
						|
      mNvRamUpdated = TRUE;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update System Firmware image.
 | 
						|
 | 
						|
  @param[in]  SystemFirmwareImage     Points to the System Firmware image.
 | 
						|
  @param[in]  SystemFirmwareImageSize The length of the System Firmware image in bytes.
 | 
						|
  @param[in]  ConfigImage             Points to the config file image.
 | 
						|
  @param[in]  ConfigImageSize         The length of the config file image in bytes.
 | 
						|
  @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[in]  Progress                A function used by the driver to report the progress of the firmware update.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The System Firmware image is updated.
 | 
						|
  @retval EFI_WRITE_PROTECTED     The flash device is read only.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
UpdateImage (
 | 
						|
  IN VOID                                           *SystemFirmwareImage,
 | 
						|
  IN UINTN                                          SystemFirmwareImageSize,
 | 
						|
  IN VOID                                           *ConfigImage,
 | 
						|
  IN UINTN                                          ConfigImageSize,
 | 
						|
  OUT UINT32                                        *LastAttemptVersion,
 | 
						|
  OUT UINT32                                        *LastAttemptStatus,
 | 
						|
  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  UPDATE_CONFIG_DATA                    *ConfigData;
 | 
						|
  UPDATE_CONFIG_DATA                    *UpdateConfigData;
 | 
						|
  CONFIG_HEADER                         ConfigHeader;
 | 
						|
  UINTN                                 Index;
 | 
						|
  UINTN                                 TotalSize;
 | 
						|
  UINTN                                 BytesWritten;
 | 
						|
  UINTN                                 StartPercentage;
 | 
						|
  UINTN                                 EndPercentage;
 | 
						|
 | 
						|
  if (ConfigImage == NULL) {
 | 
						|
    DEBUG((DEBUG_INFO, "PlatformUpdate (NoConfig):"));
 | 
						|
    DEBUG((DEBUG_INFO, "  BaseAddress - 0x%x,", 0));
 | 
						|
    DEBUG((DEBUG_INFO, "  Length - 0x%x\n", SystemFirmwareImageSize));
 | 
						|
    // ASSUME the whole System Firmware include NVRAM region.
 | 
						|
    StartPercentage = 0;
 | 
						|
    EndPercentage = 100;
 | 
						|
    if (Progress != NULL) {
 | 
						|
      Progress (StartPercentage);
 | 
						|
    }
 | 
						|
    Status = PerformFlashWriteWithProgress (
 | 
						|
               PlatformFirmwareTypeNvRam,
 | 
						|
               0,
 | 
						|
               FlashAddressTypeRelativeAddress,
 | 
						|
               SystemFirmwareImage,
 | 
						|
               SystemFirmwareImageSize,
 | 
						|
               Progress,
 | 
						|
               StartPercentage,
 | 
						|
               EndPercentage
 | 
						|
               );
 | 
						|
    if (Progress != NULL) {
 | 
						|
      Progress (EndPercentage);
 | 
						|
    }
 | 
						|
    if (!EFI_ERROR(Status)) {
 | 
						|
      *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
 | 
						|
      mNvRamUpdated = TRUE;
 | 
						|
    } else {
 | 
						|
      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
 | 
						|
    }
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG((DEBUG_INFO, "PlatformUpdate (With Config):\n"));
 | 
						|
  ConfigData        = NULL;
 | 
						|
  ZeroMem (&ConfigHeader, sizeof(ConfigHeader));
 | 
						|
  Status            = ParseUpdateDataFile (
 | 
						|
                        ConfigImage,
 | 
						|
                        ConfigImageSize,
 | 
						|
                        &ConfigHeader,
 | 
						|
                        &ConfigData
 | 
						|
                        );
 | 
						|
  DEBUG((DEBUG_INFO, "ParseUpdateDataFile - %r\n", Status));
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  DEBUG((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n", ConfigHeader.NumOfUpdates));
 | 
						|
  DEBUG((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid)));
 | 
						|
 | 
						|
  TotalSize = 0;
 | 
						|
  for (Index = 0; Index < ConfigHeader.NumOfUpdates; Index++) {
 | 
						|
    if (CompareGuid(&ConfigData[Index].FileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))) {
 | 
						|
      TotalSize = TotalSize + ConfigData[Index].Length;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  BytesWritten = 0;
 | 
						|
  Index = 0;
 | 
						|
  UpdateConfigData = ConfigData;
 | 
						|
  while (Index < ConfigHeader.NumOfUpdates) {
 | 
						|
    if (CompareGuid(&UpdateConfigData->FileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))) {
 | 
						|
      DEBUG((DEBUG_INFO, "FileGuid - %g (processing)\n", &UpdateConfigData->FileGuid));
 | 
						|
      StartPercentage = (BytesWritten * 100) / TotalSize;
 | 
						|
      EndPercentage   = ((BytesWritten + UpdateConfigData->Length) * 100) / TotalSize;
 | 
						|
      Status = PerformUpdate (
 | 
						|
                 SystemFirmwareImage,
 | 
						|
                 SystemFirmwareImageSize,
 | 
						|
                 UpdateConfigData,
 | 
						|
                 LastAttemptVersion,
 | 
						|
                 LastAttemptStatus,
 | 
						|
                 Progress,
 | 
						|
                 StartPercentage,
 | 
						|
                 EndPercentage
 | 
						|
                 );
 | 
						|
      //
 | 
						|
      // Shall updates be serialized so that if an update is not successfully completed,
 | 
						|
      // the remaining updates won't be performed.
 | 
						|
      //
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      DEBUG((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData->FileGuid));
 | 
						|
    }
 | 
						|
 | 
						|
    BytesWritten += UpdateConfigData->Length;
 | 
						|
 | 
						|
    Index++;
 | 
						|
    UpdateConfigData++;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Authenticate and update System Firmware image.
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
 | 
						|
  @param[in]  Image              The EDKII system FMP capsule image.
 | 
						|
  @param[in]  ImageSize          The size of the EDKII system FMP capsule image in bytes.
 | 
						|
  @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[out] LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             EDKII system FMP capsule passes authentication and the System Firmware image is updated.
 | 
						|
  @retval EFI_SECURITY_VIOLATION  EDKII system FMP capsule fails authentication and the System Firmware image is not updated.
 | 
						|
  @retval EFI_WRITE_PROTECTED     The flash device is read only.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SystemFirmwareAuthenticatedUpdate (
 | 
						|
  IN VOID                                           *Image,
 | 
						|
  IN UINTN                                          ImageSize,
 | 
						|
  OUT UINT32                                        *LastAttemptVersion,
 | 
						|
  OUT UINT32                                        *LastAttemptStatus,
 | 
						|
  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  VOID                        *SystemFirmwareImage;
 | 
						|
  UINTN                       SystemFirmwareImageSize;
 | 
						|
  VOID                        *ConfigImage;
 | 
						|
  UINTN                       ConfigImageSize;
 | 
						|
  VOID                        *AuthenticatedImage;
 | 
						|
  UINTN                       AuthenticatedImageSize;
 | 
						|
 | 
						|
  AuthenticatedImage     = NULL;
 | 
						|
  AuthenticatedImageSize = 0;
 | 
						|
 | 
						|
  DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate...\n"));
 | 
						|
 | 
						|
  Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImage ...\n"));
 | 
						|
  ExtractSystemFirmwareImage(AuthenticatedImage, AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize);
 | 
						|
  DEBUG((DEBUG_INFO, "ExtractConfigImage ...\n"));
 | 
						|
  ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);
 | 
						|
 | 
						|
  DEBUG((DEBUG_INFO, "UpdateImage ...\n"));
 | 
						|
  Status = UpdateImage(SystemFirmwareImage, SystemFirmwareImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus, Progress);
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    DEBUG((DEBUG_INFO, "UpdateImage - %r\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate Done\n"));
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  This code finds variable in storage blocks (Volatile or Non-Volatile).
 | 
						|
 | 
						|
  @param[in]      VariableName               Name of Variable to be found.
 | 
						|
  @param[in]      VendorGuid                 Variable vendor GUID.
 | 
						|
  @param[out]     Attributes                 Attribute value of the variable found.
 | 
						|
  @param[in, out] DataSize                   Size of Data found. If size is less than the
 | 
						|
                                             data, this value contains the required size.
 | 
						|
  @param[out]     Data                       Data pointer.
 | 
						|
 | 
						|
  @return EFI_INVALID_PARAMETER     Invalid parameter.
 | 
						|
  @return EFI_SUCCESS               Find the specified variable.
 | 
						|
  @return EFI_NOT_FOUND             Not found.
 | 
						|
  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetVariableHook (
 | 
						|
  IN      CHAR16            *VariableName,
 | 
						|
  IN      EFI_GUID          *VendorGuid,
 | 
						|
  OUT     UINT32            *Attributes OPTIONAL,
 | 
						|
  IN OUT  UINTN             *DataSize,
 | 
						|
  OUT     VOID              *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG((DEBUG_INFO, "GetVariableHook - %S, %g\n", VariableName, VendorGuid));
 | 
						|
  return EFI_NOT_AVAILABLE_YET;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  This code Finds the Next available variable.
 | 
						|
 | 
						|
  @param[in, out] VariableNameSize           Size of the variable name.
 | 
						|
  @param[in, out] VariableName               Pointer to variable name.
 | 
						|
  @param[in, out] VendorGuid                 Variable Vendor Guid.
 | 
						|
 | 
						|
  @return EFI_INVALID_PARAMETER     Invalid parameter.
 | 
						|
  @return EFI_SUCCESS               Find the specified variable.
 | 
						|
  @return EFI_NOT_FOUND             Not found.
 | 
						|
  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetNextVariableNameHook (
 | 
						|
  IN OUT  UINTN             *VariableNameSize,
 | 
						|
  IN OUT  CHAR16            *VariableName,
 | 
						|
  IN OUT  EFI_GUID          *VendorGuid
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG((DEBUG_INFO, "GetNextVariableNameHook - %S, %g\n", VariableName, VendorGuid));
 | 
						|
  return EFI_NOT_AVAILABLE_YET;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  This code sets variable in storage blocks (Volatile or Non-Volatile).
 | 
						|
 | 
						|
  @param[in] VariableName                     Name of Variable to be found.
 | 
						|
  @param[in] VendorGuid                       Variable vendor GUID.
 | 
						|
  @param[in] Attributes                       Attribute value of the variable found
 | 
						|
  @param[in] DataSize                         Size of Data found. If size is less than the
 | 
						|
                                              data, this value contains the required size.
 | 
						|
  @param[in] Data                             Data pointer.
 | 
						|
 | 
						|
  @return EFI_INVALID_PARAMETER           Invalid parameter.
 | 
						|
  @return EFI_SUCCESS                     Set successfully.
 | 
						|
  @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable.
 | 
						|
  @return EFI_NOT_FOUND                   Not found.
 | 
						|
  @return EFI_WRITE_PROTECTED             Variable is read-only.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SetVariableHook (
 | 
						|
  IN CHAR16                  *VariableName,
 | 
						|
  IN EFI_GUID                *VendorGuid,
 | 
						|
  IN UINT32                  Attributes,
 | 
						|
  IN UINTN                   DataSize,
 | 
						|
  IN VOID                    *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG((DEBUG_INFO, "SetVariableHook - %S, %g, 0x%x (0x%x)\n", VariableName, VendorGuid, Attributes, DataSize));
 | 
						|
  return EFI_NOT_AVAILABLE_YET;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  This code returns information about the EFI variables.
 | 
						|
 | 
						|
  @param[in]  Attributes                     Attributes bitmask to specify the type of variables
 | 
						|
                                             on which to return information.
 | 
						|
  @param[out] MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
 | 
						|
                                             for the EFI variables associated with the attributes specified.
 | 
						|
  @param[out] RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
 | 
						|
                                             for EFI variables associated with the attributes specified.
 | 
						|
  @param[out] MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
 | 
						|
                                             associated with the attributes specified.
 | 
						|
 | 
						|
  @return EFI_SUCCESS                   Query successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
QueryVariableInfoHook (
 | 
						|
  IN  UINT32                 Attributes,
 | 
						|
  OUT UINT64                 *MaximumVariableStorageSize,
 | 
						|
  OUT UINT64                 *RemainingVariableStorageSize,
 | 
						|
  OUT UINT64                 *MaximumVariableSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG((DEBUG_INFO, "QueryVariableInfoHook - 0x%x\n", Attributes));
 | 
						|
  return EFI_NOT_AVAILABLE_YET;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
FmpSetImage (
 | 
						|
  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;
 | 
						|
  EFI_STATUS              VarStatus;
 | 
						|
  SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate;
 | 
						|
 | 
						|
  if (Image == NULL || ImageSize == 0 || AbortReason == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(This);
 | 
						|
  *AbortReason     = NULL;
 | 
						|
 | 
						|
  if (ImageIndex == 0 || ImageIndex > SystemFmpPrivate->DescriptorCount) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = SystemFirmwareAuthenticatedUpdate((VOID *)Image, ImageSize, &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastAttempt.LastAttemptStatus, Progress);
 | 
						|
  DEBUG((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus));
 | 
						|
 | 
						|
  //
 | 
						|
  // If NVRAM is updated, we should no longer touch variable services, because
 | 
						|
  // the current variable driver may not manage the new NVRAM region.
 | 
						|
  //
 | 
						|
  if (mNvRamUpdated) {
 | 
						|
    DEBUG ((DEBUG_INFO, "NvRamUpdated, Update Variable Services\n"));
 | 
						|
    gRT->GetVariable         = GetVariableHook;
 | 
						|
    gRT->GetNextVariableName = GetNextVariableNameHook;
 | 
						|
    gRT->SetVariable         = SetVariableHook;
 | 
						|
    gRT->QueryVariableInfo   = QueryVariableInfoHook;
 | 
						|
 | 
						|
    gRT->Hdr.CRC32 = 0;
 | 
						|
    gBS->CalculateCrc32 (
 | 
						|
          (UINT8 *) &gRT->Hdr,
 | 
						|
          gRT->Hdr.HeaderSize,
 | 
						|
          &gRT->Hdr.CRC32
 | 
						|
          );
 | 
						|
  }
 | 
						|
 | 
						|
  VarStatus = gRT->SetVariable(
 | 
						|
                     SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
 | 
						|
                     &gSystemFmpLastAttemptVariableGuid,
 | 
						|
                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                     sizeof(SystemFmpPrivate->LastAttempt),
 | 
						|
                     &SystemFmpPrivate->LastAttempt
 | 
						|
                     );
 | 
						|
  DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus));
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the set of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures from an FMP Protocol.
 | 
						|
 | 
						|
  @param[in]  Handle             Handle with an FMP Protocol or a System FMP
 | 
						|
                                 Protocol.
 | 
						|
  @param[in]  ProtocolGuid       Pointer to the FMP Protocol GUID or System FMP
 | 
						|
                                 Protocol GUID.
 | 
						|
  @param[out] FmpImageInfoCount  Pointer to the number of
 | 
						|
                                 EFI_FIRMWARE_IMAGE_DESCRIPTOR structures.
 | 
						|
  @param[out] DescriptorSize     Pointer to the size, in bytes, of each
 | 
						|
                                 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure.
 | 
						|
 | 
						|
  @return NULL   No EFI_FIRMWARE_IMAGE_DESCRIPTOR structures found.
 | 
						|
  @return !NULL  Pointer to a buffer of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures
 | 
						|
                 allocated using AllocatePool().  Caller must free buffer with
 | 
						|
                 FreePool().
 | 
						|
**/
 | 
						|
EFI_FIRMWARE_IMAGE_DESCRIPTOR *
 | 
						|
GetFmpImageDescriptors (
 | 
						|
  IN  EFI_HANDLE  Handle,
 | 
						|
  IN  EFI_GUID    *ProtocolGuid,
 | 
						|
  OUT UINT8       *FmpImageInfoCount,
 | 
						|
  OUT UINTN       *DescriptorSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | 
						|
  UINTN                             ImageInfoSize;
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;
 | 
						|
  UINT32                            FmpImageInfoDescriptorVer;
 | 
						|
  UINT32                            PackageVersion;
 | 
						|
  CHAR16                            *PackageVersionName;
 | 
						|
 | 
						|
  *FmpImageInfoCount = 0;
 | 
						|
  *DescriptorSize    = 0;
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Handle,
 | 
						|
                  ProtocolGuid,
 | 
						|
                  (VOID **)&Fmp
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Determine the size required for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
 | 
						|
  //
 | 
						|
  ImageInfoSize = 0;
 | 
						|
  Status = Fmp->GetImageInfo (
 | 
						|
                  Fmp,                         // FMP Pointer
 | 
						|
                  &ImageInfoSize,              // Buffer Size (in this case 0)
 | 
						|
                  NULL,                        // NULL so we can get size
 | 
						|
                  &FmpImageInfoDescriptorVer,  // DescriptorVersion
 | 
						|
                  FmpImageInfoCount,           // DescriptorCount
 | 
						|
                  DescriptorSize,              // DescriptorSize
 | 
						|
                  &PackageVersion,             // PackageVersion
 | 
						|
                  &PackageVersionName          // PackageVersionName
 | 
						|
                  );
 | 
						|
  if (Status != EFI_BUFFER_TOO_SMALL) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Unexpected Failure.  Status = %r\n", Status));
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate buffer for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
 | 
						|
  //
 | 
						|
  FmpImageInfoBuf = NULL;
 | 
						|
  FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
 | 
						|
  if (FmpImageInfoBuf == NULL) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to allocate memory for descriptors.\n"));
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
 | 
						|
  //
 | 
						|
  PackageVersionName = NULL;
 | 
						|
  Status = Fmp->GetImageInfo (
 | 
						|
                  Fmp,
 | 
						|
                  &ImageInfoSize,              // ImageInfoSize
 | 
						|
                  FmpImageInfoBuf,             // ImageInfo
 | 
						|
                  &FmpImageInfoDescriptorVer,  // DescriptorVersion
 | 
						|
                  FmpImageInfoCount,           // DescriptorCount
 | 
						|
                  DescriptorSize,              // DescriptorSize
 | 
						|
                  &PackageVersion,             // PackageVersion
 | 
						|
                  &PackageVersionName          // PackageVersionName
 | 
						|
                  );
 | 
						|
 | 
						|
  //
 | 
						|
  // Free unused PackageVersionName return buffer
 | 
						|
  //
 | 
						|
  if (PackageVersionName != NULL) {
 | 
						|
    FreePool (PackageVersionName);
 | 
						|
    PackageVersionName = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failure in GetImageInfo.  Status = %r\n", Status));
 | 
						|
    if (FmpImageInfoBuf != NULL) {
 | 
						|
      FreePool (FmpImageInfoBuf);
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return FmpImageInfoBuf;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Search for handles with an FMP protocol whose EFI_FIRMWARE_IMAGE_DESCRIPTOR
 | 
						|
  ImageTypeId matches the ImageTypeId produced by this module.
 | 
						|
 | 
						|
  @param[in]  ProtocolGuid  Pointer to the GUID of the protocol to search.
 | 
						|
  @param[out] HandleCount   Pointer to the number of returned handles.
 | 
						|
 | 
						|
  @return NULL   No matching handles found.
 | 
						|
  @return !NULL  Pointer to a buffer of handles allocated using AllocatePool().
 | 
						|
                 Caller must free buffer with FreePool().
 | 
						|
**/
 | 
						|
EFI_HANDLE *
 | 
						|
FindMatchingFmpHandles (
 | 
						|
  IN  EFI_GUID  *ProtocolGuid,
 | 
						|
  OUT UINTN     *HandleCount
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  UINTN                          TempHandleCount;
 | 
						|
  EFI_HANDLE                     *HandleBuffer;
 | 
						|
  UINTN                          Index;
 | 
						|
  UINTN                          Index2;
 | 
						|
  UINTN                          Index3;
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *OriginalFmpImageInfoBuf;
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfoBuf;
 | 
						|
  UINT8                          FmpImageInfoCount;
 | 
						|
  UINTN                          DescriptorSize;
 | 
						|
  BOOLEAN                        MatchFound;
 | 
						|
 | 
						|
  *HandleCount  = 0;
 | 
						|
  TempHandleCount = 0;
 | 
						|
  HandleBuffer = NULL;
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                   ByProtocol,
 | 
						|
                   ProtocolGuid,
 | 
						|
                   NULL,
 | 
						|
                   &TempHandleCount,
 | 
						|
                   &HandleBuffer
 | 
						|
                   );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < TempHandleCount; Index++) {
 | 
						|
    OriginalFmpImageInfoBuf = GetFmpImageDescriptors (
 | 
						|
                                HandleBuffer[Index],
 | 
						|
                                ProtocolGuid,
 | 
						|
                                &FmpImageInfoCount,
 | 
						|
                                &DescriptorSize
 | 
						|
                                );
 | 
						|
 | 
						|
    //
 | 
						|
    // Loop through the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
 | 
						|
    //
 | 
						|
    MatchFound = FALSE;
 | 
						|
    if (OriginalFmpImageInfoBuf != NULL) {
 | 
						|
      FmpImageInfoBuf = OriginalFmpImageInfoBuf;
 | 
						|
 | 
						|
      for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
 | 
						|
        for (Index3 = 0; Index3 < mSystemFmpPrivate->DescriptorCount; Index3++) {
 | 
						|
          MatchFound = CompareGuid (
 | 
						|
                        &FmpImageInfoBuf->ImageTypeId,
 | 
						|
                        &mSystemFmpPrivate->ImageDescriptor[Index3].ImageTypeId
 | 
						|
                        );
 | 
						|
          if (MatchFound) {
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        if (MatchFound) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Increment the buffer pointer ahead by the size of the descriptor
 | 
						|
        //
 | 
						|
        FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpImageInfoBuf) + DescriptorSize);
 | 
						|
      }
 | 
						|
      if (MatchFound) {
 | 
						|
        HandleBuffer[*HandleCount] = HandleBuffer[Index];
 | 
						|
        (*HandleCount)++;
 | 
						|
      }
 | 
						|
 | 
						|
      FreePool (OriginalFmpImageInfoBuf);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if ((*HandleCount) == 0) {
 | 
						|
    //
 | 
						|
    // No any matching handle.
 | 
						|
    //
 | 
						|
    FreePool (HandleBuffer);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  return HandleBuffer;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Uninstall System FMP Protocol instances that may have been installed by
 | 
						|
  SystemFirmwareUpdateDxe drivers dispatches by other capsules.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS  All System FMP Protocols found were uninstalled.
 | 
						|
  @return Other        One or more System FMP Protocols could not be uninstalled.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
UninstallMatchingSystemFmpProtocols (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_HANDLE                        *HandleBuffer;
 | 
						|
  UINTN                             HandleCount;
 | 
						|
  UINTN                             Index;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *SystemFmp;
 | 
						|
 | 
						|
  //
 | 
						|
  // Uninstall SystemFmpProtocol instances that may have been produced by
 | 
						|
  // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules.
 | 
						|
  //
 | 
						|
  HandleBuffer = FindMatchingFmpHandles (
 | 
						|
                   &gSystemFmpProtocolGuid,
 | 
						|
                   &HandleCount
 | 
						|
                   );
 | 
						|
  DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching System FMP instances\n", HandleCount));
 | 
						|
 | 
						|
  for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
    Status = gBS->HandleProtocol(
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gSystemFmpProtocolGuid,
 | 
						|
                    (VOID **)&SystemFmp
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Uninstall SystemFmp produced by another capsule\n"));
 | 
						|
    Status = gBS->UninstallProtocolInterface (
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gSystemFmpProtocolGuid,
 | 
						|
                    SystemFmp
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to uninstall SystemFmp %r.  Exiting.\n", Status));
 | 
						|
      FreePool (HandleBuffer);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (HandleBuffer != NULL) {
 | 
						|
    FreePool (HandleBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  System FMP module entrypoint
 | 
						|
 | 
						|
  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
 | 
						|
  @param[in] SystemTable  A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           System FMP module is initialized.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  There are not enough resources avaulable to
 | 
						|
                                initialize this module.
 | 
						|
  @retval Other                 System FMP Protocols could not be uninstalled.
 | 
						|
  @retval Other                 System FMP Protocol could not be installed.
 | 
						|
  @retval Other                 FMP Protocol could not be installed.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SystemFirmwareUpdateMainDxe (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  EFI_HANDLE  *HandleBuffer;
 | 
						|
  UINTN       HandleCount;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize SystemFmpPrivateData
 | 
						|
  //
 | 
						|
  mSystemFmpPrivate = AllocateZeroPool (sizeof (SYSTEM_FMP_PRIVATE_DATA));
 | 
						|
  if (mSystemFmpPrivate == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = InitializePrivateData (mSystemFmpPrivate);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (mSystemFmpPrivate);
 | 
						|
    mSystemFmpPrivate = NULL;
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Uninstall SystemFmpProtocol instances that may have been produced by
 | 
						|
  // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules.
 | 
						|
  //
 | 
						|
  Status = UninstallMatchingSystemFmpProtocols ();
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (mSystemFmpPrivate);
 | 
						|
    mSystemFmpPrivate = NULL;
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Look for a handle with matching Firmware Management Protocol
 | 
						|
  //
 | 
						|
  HandleCount = 0;
 | 
						|
  HandleBuffer = FindMatchingFmpHandles (
 | 
						|
                   &gEfiFirmwareManagementProtocolGuid,
 | 
						|
                   &HandleCount
 | 
						|
                   );
 | 
						|
  DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching FMP instances\n", HandleCount));
 | 
						|
 | 
						|
  switch (HandleCount) {
 | 
						|
  case 0:
 | 
						|
    //
 | 
						|
    // Install FMP protocol onto a new handle.
 | 
						|
    //
 | 
						|
    DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install FMP onto a new handle\n"));
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                    &mSystemFmpPrivate->Handle,
 | 
						|
                    &gEfiFirmwareManagementProtocolGuid,
 | 
						|
                    &mSystemFmpPrivate->Fmp,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    break;
 | 
						|
  case 1:
 | 
						|
    //
 | 
						|
    // Install System FMP protocol onto handle with matching FMP Protocol
 | 
						|
    //
 | 
						|
    DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install System FMP onto matching FMP handle\n"));
 | 
						|
    mSystemFmpPrivate->Handle = HandleBuffer[0];
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                    &HandleBuffer[0],
 | 
						|
                    &gSystemFmpProtocolGuid,
 | 
						|
                    &mSystemFmpPrivate->Fmp,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    //
 | 
						|
    // More than one matching handle is not expected.  Unload driver.
 | 
						|
    //
 | 
						|
    DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: More than one matching FMP handle.  Unload driver.\n"));
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  if (HandleBuffer != NULL) {
 | 
						|
    FreePool (HandleBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (mSystemFmpPrivate);
 | 
						|
    mSystemFmpPrivate = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |