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>
		
			
				
	
	
		
			848 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			848 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  UEFI variable support functions for Firmware Management Protocol based
 | 
						|
  firmware updates.
 | 
						|
 | 
						|
  Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "FmpDxe.h"
 | 
						|
#include "VariableSupport.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieve the value of a 32-bit UEFI Variable specified by VariableName and
 | 
						|
  a GUID of gEfiCallerIdGuid.
 | 
						|
 | 
						|
  @param[in]  VariableName  Pointer to the UEFI Variable name to retrieve.
 | 
						|
  @param[out] Valid         Set to TRUE if UEFI Variable is present and the size
 | 
						|
                            of the UEFI Variable value is 32-bits.  Otherwise
 | 
						|
                            FALSE.
 | 
						|
  @param[out] Value         If Valid is set to TRUE, then the 32-bit value of
 | 
						|
                            the UEFI Variable.  Otherwise 0.
 | 
						|
**/
 | 
						|
static
 | 
						|
VOID
 | 
						|
GetFmpVariable (
 | 
						|
  IN  CHAR16   *VariableName,
 | 
						|
  OUT BOOLEAN  *Valid,
 | 
						|
  OUT UINT32   *Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       Size;
 | 
						|
  UINT32      *Buffer;
 | 
						|
 | 
						|
  *Valid = FALSE;
 | 
						|
  *Value = 0;
 | 
						|
  Size   = 0;
 | 
						|
  Buffer = NULL;
 | 
						|
  Status = GetVariable2 (
 | 
						|
             VariableName,
 | 
						|
             &gEfiCallerIdGuid,
 | 
						|
             (VOID **)&Buffer,
 | 
						|
             &Size
 | 
						|
             );
 | 
						|
  if (!EFI_ERROR (Status) && (Size == sizeof (*Value)) && (Buffer != NULL)) {
 | 
						|
    *Valid = TRUE;
 | 
						|
    *Value = *Buffer;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Buffer != NULL) {
 | 
						|
    FreePool (Buffer);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Delete the UEFI Variable with name specified by VariableName and GUID of
 | 
						|
  gEfiCallerIdGuid.  If the variable can not be deleted, then print a
 | 
						|
  DEBUG_ERROR message.
 | 
						|
 | 
						|
  @param[in] VariableName  Pointer to the UEFI Variable name to delete.
 | 
						|
**/
 | 
						|
static
 | 
						|
VOID
 | 
						|
DeleteFmpVariable (
 | 
						|
  IN CHAR16  *VariableName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  BOOLEAN     Valid;
 | 
						|
  UINT32      Value;
 | 
						|
 | 
						|
  GetFmpVariable (VariableName, &Valid, &Value);
 | 
						|
  if (Valid) {
 | 
						|
    Status = gRT->SetVariable (VariableName, &gEfiCallerIdGuid, 0, 0, NULL);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to delete variable %s.  Status = %r\n", mImageIdName, VariableName, Status));
 | 
						|
    } else {
 | 
						|
      DEBUG ((DEBUG_INFO, "FmpDxe(%s): Deleted variable %s\n", mImageIdName, VariableName));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieve the FMP Controller State UEFI Variable value.  Return NULL if
 | 
						|
  the variable does not exist or if the size of the UEFI Variable is not the
 | 
						|
  size of FMP_CONTROLLER_STATE.  The buffer for the UEFI Variable value
 | 
						|
  if allocated using the UEFI Boot Service AllocatePool().
 | 
						|
 | 
						|
  @param[in] Private  Private context structure for the managed controller.
 | 
						|
 | 
						|
  @return  Pointer to the allocated FMP Controller State.  Returns NULL
 | 
						|
           if the variable does not exist or is a different size than expected.
 | 
						|
**/
 | 
						|
static
 | 
						|
FMP_CONTROLLER_STATE *
 | 
						|
GetFmpControllerState (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  UINTN                 Size;
 | 
						|
 | 
						|
  FmpControllerState = NULL;
 | 
						|
  Size               = 0;
 | 
						|
  Status             = GetVariable2 (
 | 
						|
                         Private->FmpStateVariableName,
 | 
						|
                         &gEfiCallerIdGuid,
 | 
						|
                         (VOID **)&FmpControllerState,
 | 
						|
                         &Size
 | 
						|
                         );
 | 
						|
  if (EFI_ERROR (Status) || (FmpControllerState == NULL)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to get the controller state.  Status = %r\n", mImageIdName, Status));
 | 
						|
  } else {
 | 
						|
    if (Size == sizeof (*FmpControllerState)) {
 | 
						|
      return FmpControllerState;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Getting controller state returned a size different than expected. Size = 0x%x\n", mImageIdName, Size));
 | 
						|
  }
 | 
						|
 | 
						|
  if (FmpControllerState != NULL) {
 | 
						|
    FreePool (FmpControllerState);
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generates a Null-terminated Unicode string UEFI Variable name from a base name
 | 
						|
  and a hardware instance.  If the hardware instance value is 0, then the base
 | 
						|
  name is returned.  If the hardware instance value is non-zero, then the 64-bit
 | 
						|
  hardware instance value is converted to a 16 character hex string and appended
 | 
						|
  to base name.  The UEFI Variable name returned is allocated using the UEFI
 | 
						|
  Boot Service AllocatePool().
 | 
						|
 | 
						|
  @param[in] HardwareInstance  64-bit hardware instance value.
 | 
						|
  @param[in] BaseVariableName  Null-terminated Unicode string that is the base
 | 
						|
                               name of the UEFI Variable.
 | 
						|
 | 
						|
  @return  Pointer to the allocated UEFI Variable name.  Returns NULL if the
 | 
						|
           UEFI Variable can not be allocated.
 | 
						|
**/
 | 
						|
static
 | 
						|
CHAR16 *
 | 
						|
GenerateFmpVariableName (
 | 
						|
  IN  UINT64  HardwareInstance,
 | 
						|
  IN  CHAR16  *BaseVariableName
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN   Size;
 | 
						|
  CHAR16  *VariableName;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate Unicode string with room for BaseVariableName and a 16 digit
 | 
						|
  // hexadecimal value for the HardwareInstance value.
 | 
						|
  //
 | 
						|
  Size         = StrSize (BaseVariableName) + 16 * sizeof (CHAR16);
 | 
						|
  VariableName = AllocateCopyPool (Size, BaseVariableName);
 | 
						|
  if (VariableName == NULL) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to generate variable name %s.\n", mImageIdName, BaseVariableName));
 | 
						|
    return VariableName;
 | 
						|
  }
 | 
						|
 | 
						|
  if (HardwareInstance == 0) {
 | 
						|
    return VariableName;
 | 
						|
  }
 | 
						|
 | 
						|
  UnicodeValueToStringS (
 | 
						|
    &VariableName[StrLen (BaseVariableName)],
 | 
						|
    Size,
 | 
						|
    PREFIX_ZERO | RADIX_HEX,
 | 
						|
    HardwareInstance,
 | 
						|
    16
 | 
						|
    );
 | 
						|
  return VariableName;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generate the names of the UEFI Variables used to store state information for
 | 
						|
  a managed controller.  The UEFI Variables names are a combination of a base
 | 
						|
  name and an optional hardware instance value as a 16 character hex value.  If
 | 
						|
  the hardware instance value is 0, then the 16 character hex value is not
 | 
						|
  included.  These storage for the UEFI Variable names are allocated using the
 | 
						|
  UEFI Boot Service AllocatePool() and the pointers are stored in the Private.
 | 
						|
  The following are examples of variable names produces for hardware instance
 | 
						|
  value 0 and value 0x1234567812345678.
 | 
						|
 | 
						|
    FmpVersion
 | 
						|
    FmpLsv
 | 
						|
    LastAttemptStatus
 | 
						|
    LastAttemptVersion
 | 
						|
    FmpState
 | 
						|
 | 
						|
    FmpVersion1234567812345678
 | 
						|
    FmpLsv1234567812345678
 | 
						|
    LastAttemptStatus1234567812345678
 | 
						|
    LastAttemptVersion1234567812345678
 | 
						|
    FmpState1234567812345678
 | 
						|
 | 
						|
  @param[in,out] Private  Private context structure for the managed controller.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
GenerateFmpVariableNames (
 | 
						|
  IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  VOID                  *Buffer;
 | 
						|
  FMP_CONTROLLER_STATE  FmpControllerState;
 | 
						|
 | 
						|
  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);
 | 
						|
  }
 | 
						|
 | 
						|
  Private->VersionVariableName = GenerateFmpVariableName (
 | 
						|
                                   Private->Descriptor.HardwareInstance,
 | 
						|
                                   VARNAME_VERSION
 | 
						|
                                   );
 | 
						|
  Private->LsvVariableName = GenerateFmpVariableName (
 | 
						|
                               Private->Descriptor.HardwareInstance,
 | 
						|
                               VARNAME_LSV
 | 
						|
                               );
 | 
						|
  Private->LastAttemptStatusVariableName = GenerateFmpVariableName (
 | 
						|
                                             Private->Descriptor.HardwareInstance,
 | 
						|
                                             VARNAME_LASTATTEMPTSTATUS
 | 
						|
                                             );
 | 
						|
  Private->LastAttemptVersionVariableName = GenerateFmpVariableName (
 | 
						|
                                              Private->Descriptor.HardwareInstance,
 | 
						|
                                              VARNAME_LASTATTEMPTVERSION
 | 
						|
                                              );
 | 
						|
  Private->FmpStateVariableName = GenerateFmpVariableName (
 | 
						|
                                    Private->Descriptor.HardwareInstance,
 | 
						|
                                    VARNAME_FMPSTATE
 | 
						|
                                    );
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->VersionVariableName));
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LsvVariableName));
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->FmpStateVariableName));
 | 
						|
 | 
						|
  Buffer = GetFmpControllerState (Private);
 | 
						|
  if (Buffer != NULL) {
 | 
						|
    //
 | 
						|
    // FMP Controller State was found with correct size.
 | 
						|
    // Delete old variables if they exist.
 | 
						|
    //
 | 
						|
    FreePool (Buffer);
 | 
						|
    DeleteFmpVariable (Private->VersionVariableName);
 | 
						|
    DeleteFmpVariable (Private->LsvVariableName);
 | 
						|
    DeleteFmpVariable (Private->LastAttemptStatusVariableName);
 | 
						|
    DeleteFmpVariable (Private->LastAttemptVersionVariableName);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // FMP Controller State was either not found or is wrong size.
 | 
						|
  // Create a new FMP Controller State variable with the correct size.
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Create controller state\n", mImageIdName));
 | 
						|
  GetFmpVariable (
 | 
						|
    Private->VersionVariableName,
 | 
						|
    &FmpControllerState.VersionValid,
 | 
						|
    &FmpControllerState.Version
 | 
						|
    );
 | 
						|
  GetFmpVariable (
 | 
						|
    Private->LsvVariableName,
 | 
						|
    &FmpControllerState.LsvValid,
 | 
						|
    &FmpControllerState.Lsv
 | 
						|
    );
 | 
						|
  GetFmpVariable (
 | 
						|
    Private->LastAttemptStatusVariableName,
 | 
						|
    &FmpControllerState.LastAttemptStatusValid,
 | 
						|
    &FmpControllerState.LastAttemptStatus
 | 
						|
    );
 | 
						|
  GetFmpVariable (
 | 
						|
    Private->LastAttemptVersionVariableName,
 | 
						|
    &FmpControllerState.LastAttemptVersionValid,
 | 
						|
    &FmpControllerState.LastAttemptVersion
 | 
						|
    );
 | 
						|
  Status = gRT->SetVariable (
 | 
						|
                  Private->FmpStateVariableName,
 | 
						|
                  &gEfiCallerIdGuid,
 | 
						|
                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                  sizeof (FmpControllerState),
 | 
						|
                  &FmpControllerState
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Failed to create FMP Controller State.  In this case, do not
 | 
						|
    // delete the individual variables.  They can be used again on next boot
 | 
						|
    // to create the FMP Controller State.
 | 
						|
    //
 | 
						|
    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to create controller state.  Status = %r\n", mImageIdName, Status));
 | 
						|
  } else {
 | 
						|
    DeleteFmpVariable (Private->VersionVariableName);
 | 
						|
    DeleteFmpVariable (Private->LsvVariableName);
 | 
						|
    DeleteFmpVariable (Private->LastAttemptStatusVariableName);
 | 
						|
    DeleteFmpVariable (Private->LastAttemptVersionVariableName);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns the value used to fill in the Version field of the
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
 | 
						|
  service of the Firmware Management Protocol.  The value is read from a UEFI
 | 
						|
  variable.  If the UEFI variables does not exist, then a default version value
 | 
						|
  is returned.
 | 
						|
 | 
						|
  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
 | 
						|
 | 
						|
  @param[in] Private  Private context structure for the managed controller.
 | 
						|
 | 
						|
  @return  The version of the firmware image in the firmware device.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
GetVersionFromVariable (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  UINT32                Value;
 | 
						|
 | 
						|
  Value              = DEFAULT_VERSION;
 | 
						|
  FmpControllerState = GetFmpControllerState (Private);
 | 
						|
  if (FmpControllerState != NULL) {
 | 
						|
    if (FmpControllerState->VersionValid) {
 | 
						|
      Value = FmpControllerState->Version;
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "FmpDxe(%s): Get variable %g %s Version %08x\n",
 | 
						|
        mImageIdName,
 | 
						|
        &gEfiCallerIdGuid,
 | 
						|
        Private->FmpStateVariableName,
 | 
						|
        Value
 | 
						|
        ));
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (FmpControllerState);
 | 
						|
  }
 | 
						|
 | 
						|
  return Value;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns the value used to fill in the LowestSupportedVersion field of the
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
 | 
						|
  service of the Firmware Management Protocol.  The value is read from a UEFI
 | 
						|
  variable.  If the UEFI variables does not exist, then a default lowest
 | 
						|
  supported version value is returned.
 | 
						|
 | 
						|
  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
 | 
						|
 | 
						|
  @param[in] Private  Private context structure for the managed controller.
 | 
						|
 | 
						|
  @return  The lowest supported version of the firmware image in the firmware
 | 
						|
           device.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
GetLowestSupportedVersionFromVariable (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  UINT32                Value;
 | 
						|
 | 
						|
  Value              = DEFAULT_LOWESTSUPPORTEDVERSION;
 | 
						|
  FmpControllerState = GetFmpControllerState (Private);
 | 
						|
  if (FmpControllerState != NULL) {
 | 
						|
    if (FmpControllerState->LsvValid) {
 | 
						|
      Value = FmpControllerState->Lsv;
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "FmpDxe(%s): Get variable %g %s LowestSupportedVersion %08x\n",
 | 
						|
        mImageIdName,
 | 
						|
        &gEfiCallerIdGuid,
 | 
						|
        Private->FmpStateVariableName,
 | 
						|
        Value
 | 
						|
        ));
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (FmpControllerState);
 | 
						|
  }
 | 
						|
 | 
						|
  return Value;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns the value used to fill in the LastAttemptStatus field of the
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
 | 
						|
  service of the Firmware Management Protocol.  The value is read from a UEFI
 | 
						|
  variable.  If the UEFI variables does not exist, then a default last attempt
 | 
						|
  status value is returned.
 | 
						|
 | 
						|
  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
 | 
						|
 | 
						|
  @param[in] Private  Private context structure for the managed controller.
 | 
						|
 | 
						|
  @return  The last attempt status value for the most recent capsule update.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
GetLastAttemptStatusFromVariable (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  UINT32                Value;
 | 
						|
 | 
						|
  Value              = DEFAULT_LASTATTEMPTSTATUS;
 | 
						|
  FmpControllerState = GetFmpControllerState (Private);
 | 
						|
  if (FmpControllerState != NULL) {
 | 
						|
    if (FmpControllerState->LastAttemptStatusValid) {
 | 
						|
      Value = FmpControllerState->LastAttemptStatus;
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "FmpDxe(%s): Get variable %g %s LastAttemptStatus %08x\n",
 | 
						|
        mImageIdName,
 | 
						|
        &gEfiCallerIdGuid,
 | 
						|
        Private->FmpStateVariableName,
 | 
						|
        Value
 | 
						|
        ));
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (FmpControllerState);
 | 
						|
  }
 | 
						|
 | 
						|
  return Value;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns the value used to fill in the LastAttemptVersion field of the
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
 | 
						|
  service of the Firmware Management Protocol.  The value is read from a UEFI
 | 
						|
  variable.  If the UEFI variables does not exist, then a default last attempt
 | 
						|
  version value is returned.
 | 
						|
 | 
						|
  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
 | 
						|
 | 
						|
  @param[in] Private  Private context structure for the managed controller.
 | 
						|
 | 
						|
  @return  The last attempt version value for the most recent capsule update.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
GetLastAttemptVersionFromVariable (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  UINT32                Value;
 | 
						|
 | 
						|
  Value              = DEFAULT_LASTATTEMPTVERSION;
 | 
						|
  FmpControllerState = GetFmpControllerState (Private);
 | 
						|
  if (FmpControllerState != NULL) {
 | 
						|
    if (FmpControllerState->LastAttemptVersionValid) {
 | 
						|
      Value = FmpControllerState->LastAttemptVersion;
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "FmpDxe(%s): Get variable %g %s LastAttemptVersion %08x\n",
 | 
						|
        mImageIdName,
 | 
						|
        &gEfiCallerIdGuid,
 | 
						|
        Private->FmpStateVariableName,
 | 
						|
        Value
 | 
						|
        ));
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (FmpControllerState);
 | 
						|
  }
 | 
						|
 | 
						|
  return Value;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Saves the version current of the firmware image in the firmware device to a
 | 
						|
  UEFI variable.
 | 
						|
 | 
						|
  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
 | 
						|
 | 
						|
  @param[in] Private  Private context structure for the managed controller.
 | 
						|
  @param[in] Version  The version of the firmware image in the firmware device.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetVersionInVariable (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private,
 | 
						|
  IN UINT32                            Version
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  BOOLEAN               Update;
 | 
						|
 | 
						|
  FmpControllerState = GetFmpControllerState (Private);
 | 
						|
  if (FmpControllerState == NULL) {
 | 
						|
    //
 | 
						|
    // Can not update value if FMP Controller State does not exist.
 | 
						|
    // This variable is guaranteed to be created by GenerateFmpVariableNames().
 | 
						|
    //
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Update = FALSE;
 | 
						|
  if (!FmpControllerState->VersionValid) {
 | 
						|
    Update = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (FmpControllerState->Version != Version) {
 | 
						|
    Update = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Update) {
 | 
						|
    DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state.  Same value as before.\n", mImageIdName));
 | 
						|
  } else {
 | 
						|
    FmpControllerState->VersionValid = TRUE;
 | 
						|
    FmpControllerState->Version      = Version;
 | 
						|
    Status                           = gRT->SetVariable (
 | 
						|
                                              Private->FmpStateVariableName,
 | 
						|
                                              &gEfiCallerIdGuid,
 | 
						|
                                              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                                              sizeof (*FmpControllerState),
 | 
						|
                                              FmpControllerState
 | 
						|
                                              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state.  Status = %r\n", mImageIdName, Status));
 | 
						|
    } else {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "FmpDxe(%s): Set variable %g %s Version %08x\n",
 | 
						|
        mImageIdName,
 | 
						|
        &gEfiCallerIdGuid,
 | 
						|
        Private->FmpStateVariableName,
 | 
						|
        Version
 | 
						|
        ));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (FmpControllerState);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Saves the lowest supported version current of the firmware image in the
 | 
						|
  firmware device to a UEFI variable.
 | 
						|
 | 
						|
  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
 | 
						|
 | 
						|
  @param[in] Private                 Private context structure for the managed
 | 
						|
                                     controller.
 | 
						|
  @param[in] LowestSupportedVersion  The lowest supported version of the
 | 
						|
                                     firmware image in the firmware device.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetLowestSupportedVersionInVariable (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private,
 | 
						|
  IN UINT32                            LowestSupportedVersion
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  BOOLEAN               Update;
 | 
						|
 | 
						|
  FmpControllerState = GetFmpControllerState (Private);
 | 
						|
  if (FmpControllerState == NULL) {
 | 
						|
    //
 | 
						|
    // Can not update value if FMP Controller State does not exist.
 | 
						|
    // This variable is guaranteed to be created by GenerateFmpVariableNames().
 | 
						|
    //
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Update = FALSE;
 | 
						|
  if (!FmpControllerState->LsvValid) {
 | 
						|
    Update = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (FmpControllerState->Lsv < LowestSupportedVersion) {
 | 
						|
    Update = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Update) {
 | 
						|
    DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state.  Same value as before.\n", mImageIdName));
 | 
						|
  } else {
 | 
						|
    FmpControllerState->LsvValid = TRUE;
 | 
						|
    FmpControllerState->Lsv      = LowestSupportedVersion;
 | 
						|
    Status                       = gRT->SetVariable (
 | 
						|
                                          Private->FmpStateVariableName,
 | 
						|
                                          &gEfiCallerIdGuid,
 | 
						|
                                          EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                                          sizeof (*FmpControllerState),
 | 
						|
                                          FmpControllerState
 | 
						|
                                          );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state.  Status = %r\n", mImageIdName, Status));
 | 
						|
    } else {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "FmpDxe(%s): Set variable %g %s LowestSupportedVersion %08x\n",
 | 
						|
        mImageIdName,
 | 
						|
        &gEfiCallerIdGuid,
 | 
						|
        Private->FmpStateVariableName,
 | 
						|
        LowestSupportedVersion
 | 
						|
        ));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (FmpControllerState);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Saves the last attempt status value of the most recent FMP capsule update to a
 | 
						|
  UEFI variable.
 | 
						|
 | 
						|
  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
 | 
						|
 | 
						|
  @param[in] Private            Private context structure for the managed
 | 
						|
                                controller.
 | 
						|
  @param[in] LastAttemptStatus  The last attempt status of the most recent FMP
 | 
						|
                                capsule update.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetLastAttemptStatusInVariable (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private,
 | 
						|
  IN UINT32                            LastAttemptStatus
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  BOOLEAN               Update;
 | 
						|
 | 
						|
  FmpControllerState = GetFmpControllerState (Private);
 | 
						|
  if (FmpControllerState == NULL) {
 | 
						|
    //
 | 
						|
    // Can not update value if FMP Controller State does not exist.
 | 
						|
    // This variable is guaranteed to be created by GenerateFmpVariableNames().
 | 
						|
    //
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Update = FALSE;
 | 
						|
  if (!FmpControllerState->LastAttemptStatusValid) {
 | 
						|
    Update = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {
 | 
						|
    Update = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Update) {
 | 
						|
    DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state.  Same value as before.\n", mImageIdName));
 | 
						|
  } else {
 | 
						|
    FmpControllerState->LastAttemptStatusValid = TRUE;
 | 
						|
    FmpControllerState->LastAttemptStatus      = LastAttemptStatus;
 | 
						|
    Status                                     = gRT->SetVariable (
 | 
						|
                                                        Private->FmpStateVariableName,
 | 
						|
                                                        &gEfiCallerIdGuid,
 | 
						|
                                                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                                                        sizeof (*FmpControllerState),
 | 
						|
                                                        FmpControllerState
 | 
						|
                                                        );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state.  Status = %r\n", mImageIdName, Status));
 | 
						|
    } else {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "FmpDxe(%s): Set variable %g %s LastAttemptStatus %08x\n",
 | 
						|
        mImageIdName,
 | 
						|
        &gEfiCallerIdGuid,
 | 
						|
        Private->FmpStateVariableName,
 | 
						|
        LastAttemptStatus
 | 
						|
        ));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (FmpControllerState);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Saves the last attempt version value of the most recent FMP capsule update to
 | 
						|
  a UEFI variable.
 | 
						|
 | 
						|
  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
 | 
						|
 | 
						|
  @param[in] Private             Private context structure for the managed
 | 
						|
                                 controller.
 | 
						|
  @param[in] LastAttemptVersion  The last attempt version value of the most
 | 
						|
                                 recent FMP capsule update.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetLastAttemptVersionInVariable (
 | 
						|
  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private,
 | 
						|
  IN UINT32                            LastAttemptVersion
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  FMP_CONTROLLER_STATE  *FmpControllerState;
 | 
						|
  BOOLEAN               Update;
 | 
						|
 | 
						|
  FmpControllerState = GetFmpControllerState (Private);
 | 
						|
  if (FmpControllerState == NULL) {
 | 
						|
    //
 | 
						|
    // Can not update value if FMP Controller State does not exist.
 | 
						|
    // This variable is guaranteed to be created by GenerateFmpVariableNames().
 | 
						|
    //
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Update = FALSE;
 | 
						|
  if (!FmpControllerState->LastAttemptVersionValid) {
 | 
						|
    Update = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {
 | 
						|
    Update = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Update) {
 | 
						|
    DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state.  Same value as before.\n", mImageIdName));
 | 
						|
  } else {
 | 
						|
    FmpControllerState->LastAttemptVersionValid = TRUE;
 | 
						|
    FmpControllerState->LastAttemptVersion      = LastAttemptVersion;
 | 
						|
    Status                                      = gRT->SetVariable (
 | 
						|
                                                         Private->FmpStateVariableName,
 | 
						|
                                                         &gEfiCallerIdGuid,
 | 
						|
                                                         EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                                                         sizeof (*FmpControllerState),
 | 
						|
                                                         FmpControllerState
 | 
						|
                                                         );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state.  Status = %r\n", mImageIdName, Status));
 | 
						|
    } else {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "FmpDxe(%s): Set variable %g %s LastAttemptVersion %08x\n",
 | 
						|
        mImageIdName,
 | 
						|
        &gEfiCallerIdGuid,
 | 
						|
        Private->FmpStateVariableName,
 | 
						|
        LastAttemptVersion
 | 
						|
        ));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (FmpControllerState);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Attempts to lock a single UEFI Variable propagating the error state of the
 | 
						|
  first lock attempt that fails.  Uses gEfiCallerIdGuid as the variable GUID.
 | 
						|
 | 
						|
  @param[in] PreviousStatus  The previous UEFI Variable lock attempt status.
 | 
						|
  @param[in] VariableLock    The EDK II Variable Lock Protocol instance.
 | 
						|
  @param[in] VariableName    The name of the UEFI Variable to lock.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS  The UEFI Variable was locked and the previous variable
 | 
						|
                        lock attempt also succeeded.
 | 
						|
  @retval  Other        The UEFI Variable could not be locked or the previous
 | 
						|
                        variable lock attempt failed.
 | 
						|
**/
 | 
						|
static
 | 
						|
EFI_STATUS
 | 
						|
LockFmpVariable (
 | 
						|
  IN EFI_STATUS                      PreviousStatus,
 | 
						|
  IN EDKII_VARIABLE_POLICY_PROTOCOL  *VariablePolicy,
 | 
						|
  IN CHAR16                          *VariableName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  // If success, go ahead and set the policies to protect the target variables.
 | 
						|
  Status = RegisterBasicVariablePolicy (
 | 
						|
             VariablePolicy,
 | 
						|
             &gEfiCallerIdGuid,
 | 
						|
             VariableName,
 | 
						|
             VARIABLE_POLICY_NO_MIN_SIZE,
 | 
						|
             VARIABLE_POLICY_NO_MAX_SIZE,
 | 
						|
             VARIABLE_POLICY_NO_MUST_ATTR,
 | 
						|
             VARIABLE_POLICY_NO_CANT_ATTR,
 | 
						|
             VARIABLE_POLICY_TYPE_LOCK_NOW
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_ERROR,
 | 
						|
      "FmpDxe(%s): Failed to lock variable %g %s. Status = %r\n",
 | 
						|
      mImageIdName,
 | 
						|
      &gEfiCallerIdGuid,
 | 
						|
      VariableName,
 | 
						|
      Status
 | 
						|
      ));
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (PreviousStatus)) {
 | 
						|
    return PreviousStatus;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently
 | 
						|
  executing module.
 | 
						|
 | 
						|
  @param[in] Private  Private context structure for the managed controller.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS      All UEFI variables are locked.
 | 
						|
  @retval  EFI_UNSUPPORTED  Variable Lock Protocol not found.
 | 
						|
  @retval  Other            One of the UEFI variables could not be locked.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
LockAllFmpVariables (
 | 
						|
  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EDKII_VARIABLE_POLICY_PROTOCOL  *VariablePolicy;
 | 
						|
 | 
						|
  // Locate the VariablePolicy protocol.
 | 
						|
  Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "FmpDxe %a - Could not locate VariablePolicy protocol! %r\n", __FUNCTION__, Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
  Status = LockFmpVariable (Status, VariablePolicy, Private->VersionVariableName);
 | 
						|
  Status = LockFmpVariable (Status, VariablePolicy, Private->LsvVariableName);
 | 
						|
  Status = LockFmpVariable (Status, VariablePolicy, Private->LastAttemptStatusVariableName);
 | 
						|
  Status = LockFmpVariable (Status, VariablePolicy, Private->LastAttemptVersionVariableName);
 | 
						|
  Status = LockFmpVariable (Status, VariablePolicy, Private->FmpStateVariableName);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |