V2: Fix MSFT C4255 warning V1: Enable MSFT C4255 warning. From MSDN: Compiler Warning (level 4) C4255 function' : no function prototype given: converting '()' to '(void)' The compiler did not find an explicit list of arguments to a function. This warning is for the C compiler only. Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Bell Song <binx.song@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			1281 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1281 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Sample platform variable cleanup library implementation.
 | 
						|
 | 
						|
Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "PlatVarCleanup.h"
 | 
						|
 | 
						|
VAR_ERROR_FLAG              mLastVarErrorFlag = VAR_ERROR_FLAG_NO_ERROR;
 | 
						|
EDKII_VAR_CHECK_PROTOCOL    *mVarCheck = NULL;
 | 
						|
 | 
						|
///
 | 
						|
/// The flag to indicate whether the platform has left the DXE phase of execution.
 | 
						|
///
 | 
						|
BOOLEAN                     mEndOfDxe = FALSE;
 | 
						|
 | 
						|
EFI_EVENT                   mPlatVarCleanupLibEndOfDxeEvent = NULL;
 | 
						|
 | 
						|
LIST_ENTRY                  mUserVariableList = INITIALIZE_LIST_HEAD_VARIABLE (mUserVariableList);
 | 
						|
UINT16                      mUserVariableCount = 0;
 | 
						|
UINT16                      mMarkedUserVariableCount = 0;
 | 
						|
 | 
						|
EFI_GUID                    mVariableCleanupHiiGuid = VARIABLE_CLEANUP_HII_GUID;
 | 
						|
CHAR16                      mVarStoreName[] = L"VariableCleanup";
 | 
						|
 | 
						|
HII_VENDOR_DEVICE_PATH      mVarCleanupHiiVendorDevicePath = {
 | 
						|
  {
 | 
						|
    {
 | 
						|
      HARDWARE_DEVICE_PATH,
 | 
						|
      HW_VENDOR_DP,
 | 
						|
      {
 | 
						|
        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
 | 
						|
        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
 | 
						|
      }
 | 
						|
    },
 | 
						|
    VARIABLE_CLEANUP_HII_GUID
 | 
						|
  },
 | 
						|
  {
 | 
						|
    END_DEVICE_PATH_TYPE,
 | 
						|
    END_ENTIRE_DEVICE_PATH_SUBTYPE,
 | 
						|
    {
 | 
						|
      (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),
 | 
						|
      (UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)
 | 
						|
    }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Internal get variable error flag.
 | 
						|
 | 
						|
  @return   Variable error flag.
 | 
						|
 | 
						|
**/
 | 
						|
VAR_ERROR_FLAG
 | 
						|
InternalGetVarErrorFlag (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  UINTN             Size;
 | 
						|
  VAR_ERROR_FLAG    ErrorFlag;
 | 
						|
 | 
						|
  Size = sizeof (ErrorFlag);
 | 
						|
  Status = gRT->GetVariable (
 | 
						|
                  VAR_ERROR_FLAG_NAME,
 | 
						|
                  &gEdkiiVarErrorFlagGuid,
 | 
						|
                  NULL,
 | 
						|
                  &Size,
 | 
						|
                  &ErrorFlag
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_INFO, "%s - not found\n", VAR_ERROR_FLAG_NAME));
 | 
						|
    return VAR_ERROR_FLAG_NO_ERROR;
 | 
						|
  }
 | 
						|
  return ErrorFlag;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Is user variable?
 | 
						|
 | 
						|
  @param[in] Name   Pointer to variable name.
 | 
						|
  @param[in] Guid   Pointer to vendor guid.
 | 
						|
 | 
						|
  @retval TRUE      User variable.
 | 
						|
  @retval FALSE     System variable.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsUserVariable (
 | 
						|
  IN CHAR16                     *Name,
 | 
						|
  IN EFI_GUID                   *Guid
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  VAR_CHECK_VARIABLE_PROPERTY   Property;
 | 
						|
 | 
						|
  if (mVarCheck == NULL) {
 | 
						|
    gBS->LocateProtocol (
 | 
						|
           &gEdkiiVarCheckProtocolGuid,
 | 
						|
           NULL,
 | 
						|
           (VOID **) &mVarCheck
 | 
						|
           );
 | 
						|
  }
 | 
						|
  ASSERT (mVarCheck != NULL);
 | 
						|
 | 
						|
  ZeroMem (&Property, sizeof (Property));
 | 
						|
  Status = mVarCheck->VariablePropertyGet (
 | 
						|
                        Name,
 | 
						|
                        Guid,
 | 
						|
                        &Property
 | 
						|
                        );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // No property, it is user variable.
 | 
						|
    //
 | 
						|
    DEBUG ((EFI_D_INFO, "PlatformVarCleanup - User variable: %g:%s\n", Guid, Name));
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
//  DEBUG ((EFI_D_INFO, "PlatformVarCleanup - Variable Property: %g:%s\n", Guid, Name));
 | 
						|
//  DEBUG ((EFI_D_INFO, "  Revision  - 0x%04x\n", Property.Revision));
 | 
						|
//  DEBUG ((EFI_D_INFO, "  Property  - 0x%04x\n", Property.Property));
 | 
						|
//  DEBUG ((EFI_D_INFO, "  Attribute - 0x%08x\n", Property.Attributes));
 | 
						|
//  DEBUG ((EFI_D_INFO, "  MinSize   - 0x%x\n", Property.MinSize));
 | 
						|
//  DEBUG ((EFI_D_INFO, "  MaxSize   - 0x%x\n", Property.MaxSize));
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find user variable node by variable GUID.
 | 
						|
 | 
						|
  @param[in] Guid   Pointer to vendor guid.
 | 
						|
 | 
						|
  @return Pointer to user variable node.
 | 
						|
 | 
						|
**/
 | 
						|
USER_VARIABLE_NODE *
 | 
						|
FindUserVariableNodeByGuid (
 | 
						|
  IN EFI_GUID   *Guid
 | 
						|
  )
 | 
						|
{
 | 
						|
  USER_VARIABLE_NODE    *UserVariableNode;
 | 
						|
  LIST_ENTRY            *Link;
 | 
						|
 | 
						|
  for (Link = mUserVariableList.ForwardLink
 | 
						|
       ;Link != &mUserVariableList
 | 
						|
       ;Link = Link->ForwardLink) {
 | 
						|
    UserVariableNode = USER_VARIABLE_FROM_LINK (Link);
 | 
						|
 | 
						|
    if (CompareGuid (Guid, &UserVariableNode->Guid)) {
 | 
						|
      //
 | 
						|
      // Found it.
 | 
						|
      //
 | 
						|
      return UserVariableNode;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create new one if not found.
 | 
						|
  //
 | 
						|
  UserVariableNode = AllocateZeroPool (sizeof (*UserVariableNode));
 | 
						|
  ASSERT (UserVariableNode != NULL);
 | 
						|
  UserVariableNode->Signature = USER_VARIABLE_NODE_SIGNATURE;
 | 
						|
  CopyGuid (&UserVariableNode->Guid, Guid);
 | 
						|
  //
 | 
						|
  // (36 chars of "########-####-####-####-############" + 1 space + 1 terminator) * sizeof (CHAR16).
 | 
						|
  //
 | 
						|
  UserVariableNode->PromptString = AllocatePool ((36 + 2) * sizeof (CHAR16));
 | 
						|
  ASSERT (UserVariableNode->PromptString != NULL);
 | 
						|
  UnicodeSPrint (UserVariableNode->PromptString, (36 + 2) * sizeof (CHAR16), L" %g", &UserVariableNode->Guid);
 | 
						|
  InitializeListHead (&UserVariableNode->NameLink);
 | 
						|
  InsertTailList (&mUserVariableList, &UserVariableNode->Link);
 | 
						|
  return UserVariableNode;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create user variable node.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CreateUserVariableNode (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_STATUS                    GetVariableStatus;
 | 
						|
  CHAR16                        *VarName;
 | 
						|
  UINTN                         MaxVarNameSize;
 | 
						|
  UINTN                         VarNameSize;
 | 
						|
  UINTN                         MaxDataSize;
 | 
						|
  UINTN                         DataSize;
 | 
						|
  VOID                          *Data;
 | 
						|
  UINT32                        Attributes;
 | 
						|
  EFI_GUID                      Guid;
 | 
						|
  USER_VARIABLE_NODE            *UserVariableNode;
 | 
						|
  USER_VARIABLE_NAME_NODE       *UserVariableNameNode;
 | 
						|
  UINT16                        Index;
 | 
						|
  UINTN                         StringSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize 128 * sizeof (CHAR16) variable name size.
 | 
						|
  //
 | 
						|
  MaxVarNameSize = 128 * sizeof (CHAR16);
 | 
						|
  VarName = AllocateZeroPool (MaxVarNameSize);
 | 
						|
  ASSERT (VarName != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize 0x1000 variable data size.
 | 
						|
  //
 | 
						|
  MaxDataSize = 0x1000;
 | 
						|
  Data = AllocateZeroPool (MaxDataSize);
 | 
						|
  ASSERT (Data != NULL);
 | 
						|
 | 
						|
  Index = 0;
 | 
						|
  do {
 | 
						|
    VarNameSize = MaxVarNameSize;
 | 
						|
    Status = gRT->GetNextVariableName (&VarNameSize, VarName, &Guid);
 | 
						|
    if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
      VarName = ReallocatePool (MaxVarNameSize, VarNameSize, VarName);
 | 
						|
      ASSERT (VarName != NULL);
 | 
						|
      MaxVarNameSize = VarNameSize;
 | 
						|
      Status = gRT->GetNextVariableName (&VarNameSize, VarName, &Guid);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      if (IsUserVariable (VarName, &Guid)) {
 | 
						|
        DataSize = MaxDataSize;
 | 
						|
        GetVariableStatus = gRT->GetVariable (VarName, &Guid, &Attributes, &DataSize, Data);
 | 
						|
        if (GetVariableStatus == EFI_BUFFER_TOO_SMALL) {
 | 
						|
          Data = ReallocatePool (MaxDataSize, DataSize, Data);
 | 
						|
          ASSERT (Data != NULL);
 | 
						|
          MaxDataSize = DataSize;
 | 
						|
          GetVariableStatus = gRT->GetVariable (VarName, &Guid, &Attributes, &DataSize, Data);
 | 
						|
        }
 | 
						|
        ASSERT_EFI_ERROR (GetVariableStatus);
 | 
						|
 | 
						|
        if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
 | 
						|
          UserVariableNode = FindUserVariableNodeByGuid (&Guid);
 | 
						|
          ASSERT (UserVariableNode != NULL);
 | 
						|
 | 
						|
          //
 | 
						|
          // Different variables that have same variable GUID share same user variable node.
 | 
						|
          //
 | 
						|
          UserVariableNameNode = AllocateZeroPool (sizeof (*UserVariableNameNode));
 | 
						|
          ASSERT (UserVariableNameNode != NULL);
 | 
						|
          UserVariableNameNode->Signature = USER_VARIABLE_NAME_NODE_SIGNATURE;
 | 
						|
          UserVariableNameNode->Name = AllocateCopyPool (VarNameSize, VarName);
 | 
						|
          UserVariableNameNode->Attributes = Attributes;
 | 
						|
          UserVariableNameNode->DataSize = DataSize;
 | 
						|
          UserVariableNameNode->Index = Index;
 | 
						|
          UserVariableNameNode->QuestionId = (EFI_QUESTION_ID) (USER_VARIABLE_QUESTION_ID + Index);
 | 
						|
          //
 | 
						|
          // 2 space * sizeof (CHAR16) + StrSize.
 | 
						|
          //
 | 
						|
          StringSize = 2 * sizeof (CHAR16) + StrSize (UserVariableNameNode->Name);
 | 
						|
          UserVariableNameNode->PromptString = AllocatePool (StringSize);
 | 
						|
          ASSERT (UserVariableNameNode->PromptString != NULL);
 | 
						|
          UnicodeSPrint (UserVariableNameNode->PromptString, StringSize, L"  %s", UserVariableNameNode->Name);
 | 
						|
          //
 | 
						|
          // (33 chars of "Attribtues = 0x and DataSize = 0x" + 1 terminator + (sizeof (UINT32) + sizeof (UINTN)) * 2) * sizeof (CHAR16).
 | 
						|
          //
 | 
						|
          StringSize = (33 + 1 + (sizeof (UINT32) + sizeof (UINTN)) * 2) * sizeof (CHAR16);
 | 
						|
          UserVariableNameNode->HelpString = AllocatePool (StringSize);
 | 
						|
          ASSERT (UserVariableNameNode->HelpString != NULL);
 | 
						|
          UnicodeSPrint (UserVariableNameNode->HelpString, StringSize, L"Attribtues = 0x%08x and DataSize = 0x%x", UserVariableNameNode->Attributes, UserVariableNameNode->DataSize);
 | 
						|
          UserVariableNameNode->Deleted = FALSE;
 | 
						|
          InsertTailList (&UserVariableNode->NameLink, &UserVariableNameNode->Link);
 | 
						|
          Index++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } while (Status != EFI_NOT_FOUND);
 | 
						|
 | 
						|
  mUserVariableCount = Index;
 | 
						|
  ASSERT (mUserVariableCount <= MAX_USER_VARIABLE_COUNT);
 | 
						|
  DEBUG ((EFI_D_INFO, "PlatformVarCleanup - User variable count: 0x%04x\n", mUserVariableCount));
 | 
						|
 | 
						|
  FreePool (VarName);
 | 
						|
  FreePool (Data);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Destroy user variable nodes.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DestroyUserVariableNode (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  USER_VARIABLE_NODE        *UserVariableNode;
 | 
						|
  LIST_ENTRY                *Link;
 | 
						|
  USER_VARIABLE_NAME_NODE   *UserVariableNameNode;
 | 
						|
  LIST_ENTRY                *NameLink;
 | 
						|
 | 
						|
  while (mUserVariableList.ForwardLink != &mUserVariableList) {
 | 
						|
    Link = mUserVariableList.ForwardLink;
 | 
						|
    UserVariableNode = USER_VARIABLE_FROM_LINK (Link);
 | 
						|
 | 
						|
    RemoveEntryList (&UserVariableNode->Link);
 | 
						|
 | 
						|
    while (UserVariableNode->NameLink.ForwardLink != &UserVariableNode->NameLink) {
 | 
						|
      NameLink = UserVariableNode->NameLink.ForwardLink;
 | 
						|
      UserVariableNameNode = USER_VARIABLE_NAME_FROM_LINK (NameLink);
 | 
						|
 | 
						|
      RemoveEntryList (&UserVariableNameNode->Link);
 | 
						|
 | 
						|
      FreePool (UserVariableNameNode->Name);
 | 
						|
      FreePool (UserVariableNameNode->PromptString);
 | 
						|
      FreePool (UserVariableNameNode->HelpString);
 | 
						|
      FreePool (UserVariableNameNode);
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (UserVariableNode->PromptString);
 | 
						|
    FreePool (UserVariableNode);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
 | 
						|
  descriptor with the input data. NO authentication is required in this function.
 | 
						|
 | 
						|
  @param[in, out] DataSize          On input, the size of Data buffer in bytes.
 | 
						|
                                    On output, the size of data returned in Data
 | 
						|
                                    buffer in bytes.
 | 
						|
  @param[in, out] Data              On input, Pointer to data buffer to be wrapped or
 | 
						|
                                    pointer to NULL to wrap an empty payload.
 | 
						|
                                    On output, Pointer to the new payload date buffer allocated from pool,
 | 
						|
                                    it's caller's responsibility to free the memory after using it.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               Create time based payload successfully.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES      There are not enough memory resourses to create time based payload.
 | 
						|
  @retval EFI_INVALID_PARAMETER     The parameter is invalid.
 | 
						|
  @retval Others                    Unexpected error happens.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CreateTimeBasedPayload (
 | 
						|
  IN OUT UINTN      *DataSize,
 | 
						|
  IN OUT UINT8      **Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  UINT8                             *NewData;
 | 
						|
  UINT8                             *Payload;
 | 
						|
  UINTN                             PayloadSize;
 | 
						|
  EFI_VARIABLE_AUTHENTICATION_2     *DescriptorData;
 | 
						|
  UINTN                             DescriptorSize;
 | 
						|
  EFI_TIME                          Time;
 | 
						|
 | 
						|
  if (Data == NULL || DataSize == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // At user physical presence, the variable does not need to be signed but the
 | 
						|
  // parameters to the SetVariable() call still need to be prepared as authenticated
 | 
						|
  // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
 | 
						|
  // data in it.
 | 
						|
  //
 | 
						|
  Payload     = *Data;
 | 
						|
  PayloadSize = *DataSize;
 | 
						|
 | 
						|
  DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
 | 
						|
  NewData = (UINT8 *) AllocateZeroPool (DescriptorSize + PayloadSize);
 | 
						|
  if (NewData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Payload != NULL) && (PayloadSize != 0)) {
 | 
						|
    CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
 | 
						|
  }
 | 
						|
 | 
						|
  DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
 | 
						|
 | 
						|
  ZeroMem (&Time, sizeof (EFI_TIME));
 | 
						|
  Status = gRT->GetTime (&Time, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (NewData);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Time.Pad1       = 0;
 | 
						|
  Time.Nanosecond = 0;
 | 
						|
  Time.TimeZone   = 0;
 | 
						|
  Time.Daylight   = 0;
 | 
						|
  Time.Pad2       = 0;
 | 
						|
  CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
 | 
						|
 | 
						|
  DescriptorData->AuthInfo.Hdr.dwLength         = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
 | 
						|
  DescriptorData->AuthInfo.Hdr.wRevision        = 0x0200;
 | 
						|
  DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
 | 
						|
  CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
 | 
						|
 | 
						|
  if (Payload != NULL) {
 | 
						|
    FreePool (Payload);
 | 
						|
  }
 | 
						|
 | 
						|
  *DataSize = DescriptorSize + PayloadSize;
 | 
						|
  *Data     = NewData;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a counter based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION
 | 
						|
  descriptor with the input data. NO authentication is required in this function.
 | 
						|
 | 
						|
  @param[in, out] DataSize          On input, the size of Data buffer in bytes.
 | 
						|
                                    On output, the size of data returned in Data
 | 
						|
                                    buffer in bytes.
 | 
						|
  @param[in, out] Data              On input, Pointer to data buffer to be wrapped or
 | 
						|
                                    pointer to NULL to wrap an empty payload.
 | 
						|
                                    On output, Pointer to the new payload date buffer allocated from pool,
 | 
						|
                                    it's caller's responsibility to free the memory after using it.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               Create counter based payload successfully.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES      There are not enough memory resourses to create time based payload.
 | 
						|
  @retval EFI_INVALID_PARAMETER     The parameter is invalid.
 | 
						|
  @retval Others                    Unexpected error happens.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CreateCounterBasedPayload (
 | 
						|
  IN OUT UINTN      *DataSize,
 | 
						|
  IN OUT UINT8      **Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  UINT8                             *NewData;
 | 
						|
  UINT8                             *Payload;
 | 
						|
  UINTN                             PayloadSize;
 | 
						|
  EFI_VARIABLE_AUTHENTICATION       *DescriptorData;
 | 
						|
  UINTN                             DescriptorSize;
 | 
						|
  UINT64                            MonotonicCount;
 | 
						|
 | 
						|
  if (Data == NULL || DataSize == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // At user physical presence, the variable does not need to be signed but the
 | 
						|
  // parameters to the SetVariable() call still need to be prepared as authenticated
 | 
						|
  // variable. So we create EFI_VARIABLE_AUTHENTICATED descriptor without certificate
 | 
						|
  // data in it.
 | 
						|
  //
 | 
						|
  Payload     = *Data;
 | 
						|
  PayloadSize = *DataSize;
 | 
						|
 | 
						|
  DescriptorSize = (OFFSET_OF (EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \
 | 
						|
                   (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) + \
 | 
						|
                   sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256);
 | 
						|
  NewData = (UINT8 *) AllocateZeroPool (DescriptorSize + PayloadSize);
 | 
						|
  if (NewData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Payload != NULL) && (PayloadSize != 0)) {
 | 
						|
    CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
 | 
						|
  }
 | 
						|
 | 
						|
  DescriptorData = (EFI_VARIABLE_AUTHENTICATION *) (NewData);
 | 
						|
 | 
						|
  Status = gBS->GetNextMonotonicCount (&MonotonicCount);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (NewData);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  DescriptorData->MonotonicCount = MonotonicCount;
 | 
						|
 | 
						|
  DescriptorData->AuthInfo.Hdr.dwLength         = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256);
 | 
						|
  DescriptorData->AuthInfo.Hdr.wRevision        = 0x0200;
 | 
						|
  DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
 | 
						|
  CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid);
 | 
						|
 | 
						|
  if (Payload != NULL) {
 | 
						|
    FreePool (Payload);
 | 
						|
  }
 | 
						|
 | 
						|
  *DataSize = DescriptorSize + PayloadSize;
 | 
						|
  *Data     = NewData;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Delete user variable.
 | 
						|
 | 
						|
  @param[in] DeleteAll              Delete all user variables.
 | 
						|
  @param[in] VariableCleanupData    Pointer to variable cleanup data.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DeleteUserVariable (
 | 
						|
  IN BOOLEAN                DeleteAll,
 | 
						|
  IN VARIABLE_CLEANUP_DATA  *VariableCleanupData OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  USER_VARIABLE_NODE        *UserVariableNode;
 | 
						|
  LIST_ENTRY                *Link;
 | 
						|
  USER_VARIABLE_NAME_NODE   *UserVariableNameNode;
 | 
						|
  LIST_ENTRY                *NameLink;
 | 
						|
  UINTN                     DataSize;
 | 
						|
  UINT8                     *Data;
 | 
						|
 | 
						|
  for (Link = mUserVariableList.ForwardLink
 | 
						|
       ;Link != &mUserVariableList
 | 
						|
       ;Link = Link->ForwardLink) {
 | 
						|
    UserVariableNode = USER_VARIABLE_FROM_LINK (Link);
 | 
						|
 | 
						|
    for (NameLink = UserVariableNode->NameLink.ForwardLink
 | 
						|
        ;NameLink != &UserVariableNode->NameLink
 | 
						|
        ;NameLink = NameLink->ForwardLink) {
 | 
						|
      UserVariableNameNode = USER_VARIABLE_NAME_FROM_LINK (NameLink);
 | 
						|
 | 
						|
      if (!UserVariableNameNode->Deleted && (DeleteAll || ((VariableCleanupData != NULL) && (VariableCleanupData->UserVariable[UserVariableNameNode->Index] == TRUE)))) {
 | 
						|
        DEBUG ((EFI_D_INFO, "PlatformVarCleanup - Delete variable: %g:%s\n", &UserVariableNode->Guid, UserVariableNameNode->Name));
 | 
						|
        if ((UserVariableNameNode->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
 | 
						|
          DataSize = 0;
 | 
						|
          Data = NULL;
 | 
						|
          Status = CreateTimeBasedPayload (&DataSize, &Data);
 | 
						|
          if (!EFI_ERROR (Status)) {
 | 
						|
            Status = gRT->SetVariable (UserVariableNameNode->Name, &UserVariableNode->Guid, UserVariableNameNode->Attributes, DataSize, Data);
 | 
						|
            FreePool (Data);
 | 
						|
          }
 | 
						|
        } else if ((UserVariableNameNode->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
 | 
						|
          DataSize = 0;
 | 
						|
          Data = NULL;
 | 
						|
          Status = CreateCounterBasedPayload (&DataSize, &Data);
 | 
						|
          if (!EFI_ERROR (Status)) {
 | 
						|
            Status = gRT->SetVariable (UserVariableNameNode->Name, &UserVariableNode->Guid, UserVariableNameNode->Attributes, DataSize, Data);
 | 
						|
            FreePool (Data);
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          Status = gRT->SetVariable (UserVariableNameNode->Name, &UserVariableNode->Guid, 0, 0, NULL);
 | 
						|
        }
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          UserVariableNameNode->Deleted = TRUE;
 | 
						|
        } else {
 | 
						|
          DEBUG ((EFI_D_INFO, "PlatformVarCleanup - Delete variable fail: %g:%s\n", &UserVariableNode->Guid, UserVariableNameNode->Name));
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function allows a caller to extract the current configuration for one
 | 
						|
  or more named elements from the target driver.
 | 
						|
 | 
						|
  @param[in]  This          Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in]  Request       A null-terminated Unicode string in <ConfigRequest> format.
 | 
						|
  @param[out] Progress      On return, points to a character in the Request string.
 | 
						|
                            Points to the string's null terminator if request was successful.
 | 
						|
                            Points to the most recent '&' before the first failing name/value
 | 
						|
                            pair (or the beginning of the string if the failure is in the
 | 
						|
                            first name/value pair) if the request was not successful.
 | 
						|
  @param[out] Results       A null-terminated Unicode string in <ConfigAltResp> format which
 | 
						|
                            has all values filled in for the names in the Request string.
 | 
						|
                            String to be allocated by the called function.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               The Results is filled with the requested values.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES      Not enough memory to store the results.
 | 
						|
  @retval EFI_INVALID_PARAMETER     Request is illegal syntax, or unknown name.
 | 
						|
  @retval EFI_NOT_FOUND             Routing data doesn't match any storage in this driver.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
VariableCleanupHiiExtractConfig (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
 | 
						|
  IN  CONST EFI_STRING                          Request,
 | 
						|
  OUT EFI_STRING                                *Progress,
 | 
						|
  OUT EFI_STRING                                *Results
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  VARIABLE_CLEANUP_HII_PRIVATE_DATA *Private;
 | 
						|
  UINTN                             BufferSize;
 | 
						|
  EFI_STRING                        ConfigRequestHdr;
 | 
						|
  EFI_STRING                        ConfigRequest;
 | 
						|
  BOOLEAN                           AllocatedRequest;
 | 
						|
  UINTN                             Size;
 | 
						|
 | 
						|
  if (Progress == NULL || Results == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Progress = Request;
 | 
						|
  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mVariableCleanupHiiGuid, mVarStoreName)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  ConfigRequestHdr = NULL;
 | 
						|
  ConfigRequest    = NULL;
 | 
						|
  AllocatedRequest = FALSE;
 | 
						|
  Size             = 0;
 | 
						|
 | 
						|
  Private = VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS (This);
 | 
						|
  //
 | 
						|
  // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
 | 
						|
  //
 | 
						|
  BufferSize = sizeof (VARIABLE_CLEANUP_DATA);
 | 
						|
  ConfigRequest = Request;
 | 
						|
  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
 | 
						|
    //
 | 
						|
    // Request has no request element, construct full request string.
 | 
						|
    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
 | 
						|
    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator.
 | 
						|
    //
 | 
						|
    ConfigRequestHdr = HiiConstructConfigHdr (&mVariableCleanupHiiGuid, mVarStoreName, Private->HiiHandle);
 | 
						|
    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
 | 
						|
    ConfigRequest = AllocateZeroPool (Size);
 | 
						|
    ASSERT (ConfigRequest != NULL);
 | 
						|
    AllocatedRequest = TRUE;
 | 
						|
    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
 | 
						|
    FreePool (ConfigRequestHdr);
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Private->ConfigRouting->BlockToConfig (
 | 
						|
                                     Private->ConfigRouting,
 | 
						|
                                     ConfigRequest,
 | 
						|
                                     (UINT8 *) &Private->VariableCleanupData,
 | 
						|
                                     BufferSize,
 | 
						|
                                     Results,
 | 
						|
                                     Progress
 | 
						|
                                     );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the allocated config request string.
 | 
						|
  //
 | 
						|
  if (AllocatedRequest) {
 | 
						|
    FreePool (ConfigRequest);
 | 
						|
    ConfigRequest = NULL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Set Progress string to the original request string or the string's null terminator.
 | 
						|
  //
 | 
						|
  if (Request == NULL) {
 | 
						|
    *Progress = NULL;
 | 
						|
  } else if (StrStr (Request, L"OFFSET") == NULL) {
 | 
						|
    *Progress = Request + StrLen (Request);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update user variable form.
 | 
						|
 | 
						|
  @param[in] Private    Points to the VARIABLE_CLEANUP_HII_PRIVATE_DATA.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
UpdateUserVariableForm (
 | 
						|
  IN VARIABLE_CLEANUP_HII_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STRING_ID             PromptStringToken;
 | 
						|
  EFI_STRING_ID             HelpStringToken;
 | 
						|
  VOID                      *StartOpCodeHandle;
 | 
						|
  VOID                      *EndOpCodeHandle;
 | 
						|
  EFI_IFR_GUID_LABEL        *StartLabel;
 | 
						|
  EFI_IFR_GUID_LABEL        *EndLabel;
 | 
						|
  USER_VARIABLE_NODE        *UserVariableNode;
 | 
						|
  LIST_ENTRY                *Link;
 | 
						|
  USER_VARIABLE_NAME_NODE   *UserVariableNameNode;
 | 
						|
  LIST_ENTRY                *NameLink;
 | 
						|
  BOOLEAN                   Created;
 | 
						|
 | 
						|
  //
 | 
						|
  // Init OpCode Handle.
 | 
						|
  //
 | 
						|
  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
 | 
						|
  ASSERT (StartOpCodeHandle != NULL);
 | 
						|
 | 
						|
  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
 | 
						|
  ASSERT (EndOpCodeHandle != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Hii Extend Label OpCode as the start opcode.
 | 
						|
  //
 | 
						|
  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
 | 
						|
  StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | 
						|
  StartLabel->Number = LABEL_START;
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Hii Extend Label OpCode as the end opcode.
 | 
						|
  //
 | 
						|
  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
 | 
						|
  EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | 
						|
  EndLabel->Number = LABEL_END;
 | 
						|
 | 
						|
  HiiUpdateForm (
 | 
						|
    Private->HiiHandle,
 | 
						|
    &mVariableCleanupHiiGuid,
 | 
						|
    FORM_ID_VARIABLE_CLEANUP,
 | 
						|
    StartOpCodeHandle, // LABEL_START
 | 
						|
    EndOpCodeHandle    // LABEL_END
 | 
						|
    );
 | 
						|
 | 
						|
  for (Link = mUserVariableList.ForwardLink
 | 
						|
      ;Link != &mUserVariableList
 | 
						|
      ;Link = Link->ForwardLink) {
 | 
						|
    UserVariableNode = USER_VARIABLE_FROM_LINK (Link);
 | 
						|
 | 
						|
    //
 | 
						|
    // Create checkbox opcode for variables in the same variable GUID space.
 | 
						|
    //
 | 
						|
    Created = FALSE;
 | 
						|
    for (NameLink = UserVariableNode->NameLink.ForwardLink
 | 
						|
        ;NameLink != &UserVariableNode->NameLink
 | 
						|
        ;NameLink = NameLink->ForwardLink) {
 | 
						|
      UserVariableNameNode = USER_VARIABLE_NAME_FROM_LINK (NameLink);
 | 
						|
 | 
						|
      if (!UserVariableNameNode->Deleted) {
 | 
						|
        if (!Created) {
 | 
						|
          //
 | 
						|
          // Create subtitle opcode for variable GUID.
 | 
						|
          //
 | 
						|
          PromptStringToken = HiiSetString (Private->HiiHandle, 0, UserVariableNode->PromptString, NULL);
 | 
						|
          HiiCreateSubTitleOpCode (StartOpCodeHandle, PromptStringToken, 0, 0, 0);
 | 
						|
          Created = TRUE;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Only create opcode for the non-deleted variables.
 | 
						|
        //
 | 
						|
        PromptStringToken = HiiSetString (Private->HiiHandle, 0, UserVariableNameNode->PromptString, NULL);
 | 
						|
        HelpStringToken = HiiSetString (Private->HiiHandle, 0, UserVariableNameNode->HelpString, NULL);
 | 
						|
        HiiCreateCheckBoxOpCode (
 | 
						|
          StartOpCodeHandle,
 | 
						|
          UserVariableNameNode->QuestionId,
 | 
						|
          VARIABLE_CLEANUP_VARSTORE_ID,
 | 
						|
          (UINT16) (USER_VARIABLE_VAR_OFFSET + UserVariableNameNode->Index),
 | 
						|
          PromptStringToken,
 | 
						|
          HelpStringToken,
 | 
						|
          EFI_IFR_FLAG_CALLBACK,
 | 
						|
          Private->VariableCleanupData.UserVariable[UserVariableNameNode->Index],
 | 
						|
          NULL
 | 
						|
          );
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  HiiCreateSubTitleOpCode (
 | 
						|
    StartOpCodeHandle,
 | 
						|
    STRING_TOKEN (STR_NULL_STRING),
 | 
						|
    0,
 | 
						|
    0,
 | 
						|
    0
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Create the "Apply changes" and "Discard changes" tags.
 | 
						|
  //
 | 
						|
  HiiCreateActionOpCode (
 | 
						|
    StartOpCodeHandle,
 | 
						|
    SAVE_AND_EXIT_QUESTION_ID,
 | 
						|
    STRING_TOKEN (STR_SAVE_AND_EXIT),
 | 
						|
    STRING_TOKEN (STR_NULL_STRING),
 | 
						|
    EFI_IFR_FLAG_CALLBACK,
 | 
						|
    0
 | 
						|
    );
 | 
						|
  HiiCreateActionOpCode (
 | 
						|
    StartOpCodeHandle,
 | 
						|
    NO_SAVE_AND_EXIT_QUESTION_ID,
 | 
						|
    STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
 | 
						|
    STRING_TOKEN (STR_NULL_STRING),
 | 
						|
    EFI_IFR_FLAG_CALLBACK,
 | 
						|
    0
 | 
						|
    );
 | 
						|
 | 
						|
  HiiUpdateForm (
 | 
						|
    Private->HiiHandle,
 | 
						|
    &mVariableCleanupHiiGuid,
 | 
						|
    FORM_ID_VARIABLE_CLEANUP,
 | 
						|
    StartOpCodeHandle, // LABEL_START
 | 
						|
    EndOpCodeHandle    // LABEL_END
 | 
						|
    );
 | 
						|
 | 
						|
  HiiFreeOpCodeHandle (StartOpCodeHandle);
 | 
						|
  HiiFreeOpCodeHandle (EndOpCodeHandle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function applies changes in a driver's configuration.
 | 
						|
  Input is a Configuration, which has the routing data for this
 | 
						|
  driver followed by name / value configuration pairs. The driver
 | 
						|
  must apply those pairs to its configurable storage. If the
 | 
						|
  driver's configuration is stored in a linear block of data
 | 
						|
  and the driver's name / value pairs are in <BlockConfig>
 | 
						|
  format, it may use the ConfigToBlock helper function (above) to
 | 
						|
  simplify the job. Currently not implemented.
 | 
						|
 | 
						|
  @param[in]  This                  Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in]  Configuration         A null-terminated Unicode string in
 | 
						|
                                    <ConfigString> format.
 | 
						|
  @param[out] Progress              A pointer to a string filled in with the
 | 
						|
                                    offset of the most recent '&' before the
 | 
						|
                                    first failing name / value pair (or the
 | 
						|
                                    beginn ing of the string if the failure
 | 
						|
                                    is in the first name / value pair) or
 | 
						|
                                    the terminating NULL if all was
 | 
						|
                                    successful.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               The results have been distributed or are
 | 
						|
                                    awaiting distribution.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES      Not enough memory to store the
 | 
						|
                                    parts of the results that must be
 | 
						|
                                    stored awaiting possible future
 | 
						|
                                    protocols.
 | 
						|
  @retval EFI_INVALID_PARAMETERS    Passing in a NULL for the
 | 
						|
                                    Results parameter would result
 | 
						|
                                    in this type of error.
 | 
						|
  @retval EFI_NOT_FOUND             Target for the specified routing data
 | 
						|
                                    was not found.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
VariableCleanupHiiRouteConfig (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
 | 
						|
  IN  CONST EFI_STRING                          Configuration,
 | 
						|
  OUT EFI_STRING                                *Progress
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  VARIABLE_CLEANUP_HII_PRIVATE_DATA *Private;
 | 
						|
  UINTN                             BufferSize;
 | 
						|
 | 
						|
  if (Progress == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  *Progress = Configuration;
 | 
						|
 | 
						|
  if (Configuration == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check routing data in <ConfigHdr>.
 | 
						|
  // Note: there is no name for Name/Value storage, only GUID will be checked.
 | 
						|
  //
 | 
						|
  if (!HiiIsConfigHdrMatch (Configuration, &mVariableCleanupHiiGuid, mVarStoreName)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS (This);
 | 
						|
  //
 | 
						|
  // Get Buffer Storage data.
 | 
						|
  //
 | 
						|
  BufferSize = sizeof (VARIABLE_CLEANUP_DATA);
 | 
						|
  //
 | 
						|
  // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
 | 
						|
  //
 | 
						|
  Status = Private->ConfigRouting->ConfigToBlock (
 | 
						|
                            Private->ConfigRouting,
 | 
						|
                            Configuration,
 | 
						|
                            (UINT8 *) &Private->VariableCleanupData,
 | 
						|
                            &BufferSize,
 | 
						|
                            Progress
 | 
						|
                            );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  DeleteUserVariable (FALSE, &Private->VariableCleanupData);
 | 
						|
  //
 | 
						|
  // For "F10" hotkey to refresh the form.
 | 
						|
  //
 | 
						|
//  UpdateUserVariableForm (Private);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is called to provide results data to the driver.
 | 
						|
  This data consists of a unique key that is used to identify
 | 
						|
  which data is either being passed back or being asked for.
 | 
						|
 | 
						|
  @param[in]  This                  Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in]  Action                Specifies the type of action taken by the browser.
 | 
						|
  @param[in]  QuestionId            A unique value which is sent to the original
 | 
						|
                                    exporting driver so that it can identify the type
 | 
						|
                                    of data to expect. The format of the data tends to
 | 
						|
                                    vary based on the opcode that generated the callback.
 | 
						|
  @param[in]  Type                  The type of value for the question.
 | 
						|
  @param[in]  Value                 A pointer to the data being sent to the original
 | 
						|
                                    exporting driver.
 | 
						|
  @param[out] ActionRequest         On return, points to the action requested by the
 | 
						|
                                    callback function.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               The callback successfully handled the action.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES      Not enough storage is available to hold the
 | 
						|
                                    variable and its data.
 | 
						|
  @retval EFI_DEVICE_ERROR          The variable could not be saved.
 | 
						|
  @retval EFI_UNSUPPORTED           The specified Action is not supported by the
 | 
						|
                                    callback.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
VariableCleanupHiiCallback (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | 
						|
  IN  EFI_BROWSER_ACTION                     Action,
 | 
						|
  IN  EFI_QUESTION_ID                        QuestionId,
 | 
						|
  IN  UINT8                                  Type,
 | 
						|
  IN  EFI_IFR_TYPE_VALUE                     *Value,
 | 
						|
  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
 | 
						|
  )
 | 
						|
{
 | 
						|
  VARIABLE_CLEANUP_HII_PRIVATE_DATA *Private;
 | 
						|
  VARIABLE_CLEANUP_DATA             *VariableCleanupData;
 | 
						|
 | 
						|
  Private = VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS (This);
 | 
						|
 | 
						|
  if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
 | 
						|
    //
 | 
						|
    // All other action return unsupported.
 | 
						|
    //
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve uncommitted data from Form Browser.
 | 
						|
  //
 | 
						|
  VariableCleanupData = &Private->VariableCleanupData;
 | 
						|
  HiiGetBrowserData (&mVariableCleanupHiiGuid, mVarStoreName, sizeof (VARIABLE_CLEANUP_DATA), (UINT8 *) VariableCleanupData);
 | 
						|
  if (Action == EFI_BROWSER_ACTION_CHANGING) {
 | 
						|
    if (Value == NULL) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
 | 
						|
    if ((Value == NULL) || (ActionRequest == NULL)) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
    if ((QuestionId >= USER_VARIABLE_QUESTION_ID) && (QuestionId < USER_VARIABLE_QUESTION_ID + MAX_USER_VARIABLE_COUNT)) {
 | 
						|
      if (Value->b){
 | 
						|
        //
 | 
						|
        // Means one user variable checkbox is marked to delete but not press F10 or "Commit Changes and Exit" menu.
 | 
						|
        //
 | 
						|
        mMarkedUserVariableCount++;
 | 
						|
        ASSERT (mMarkedUserVariableCount <= mUserVariableCount);
 | 
						|
        if (mMarkedUserVariableCount == mUserVariableCount) {
 | 
						|
          //
 | 
						|
          // All user variables have been marked, then also mark the SelectAll checkbox.
 | 
						|
          //
 | 
						|
          VariableCleanupData->SelectAll = TRUE;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Means one user variable checkbox is unmarked.
 | 
						|
        //
 | 
						|
        mMarkedUserVariableCount--;
 | 
						|
        //
 | 
						|
        // Also unmark the SelectAll checkbox.
 | 
						|
        //
 | 
						|
        VariableCleanupData->SelectAll = FALSE;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      switch (QuestionId) {
 | 
						|
        case SELECT_ALL_QUESTION_ID:
 | 
						|
         if (Value->b){
 | 
						|
            //
 | 
						|
            // Means the SelectAll checkbox is marked to delete all user variables but not press F10 or "Commit Changes and Exit" menu.
 | 
						|
            //
 | 
						|
            SetMem (VariableCleanupData->UserVariable, sizeof (VariableCleanupData->UserVariable), TRUE);
 | 
						|
            mMarkedUserVariableCount = mUserVariableCount;
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // Means the SelectAll checkbox is unmarked.
 | 
						|
            //
 | 
						|
            SetMem (VariableCleanupData->UserVariable, sizeof (VariableCleanupData->UserVariable), FALSE);
 | 
						|
            mMarkedUserVariableCount = 0;
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        case SAVE_AND_EXIT_QUESTION_ID:
 | 
						|
          DeleteUserVariable (FALSE, VariableCleanupData);
 | 
						|
          *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
 | 
						|
          break;
 | 
						|
 | 
						|
        case NO_SAVE_AND_EXIT_QUESTION_ID:
 | 
						|
          //
 | 
						|
          // Restore local maintain data.
 | 
						|
          //
 | 
						|
          *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
 | 
						|
          break;
 | 
						|
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Pass changed uncommitted data back to Form Browser.
 | 
						|
  //
 | 
						|
  HiiSetBrowserData (&mVariableCleanupHiiGuid, mVarStoreName, sizeof (VARIABLE_CLEANUP_DATA), (UINT8 *) VariableCleanupData, NULL);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Platform variable cleanup.
 | 
						|
 | 
						|
  @param[in] Flag                   Variable error flag.
 | 
						|
  @param[in] Type                   Variable cleanup type.
 | 
						|
                                    If it is VarCleanupManually, the interface must be called after console connected.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               No error or error processed.
 | 
						|
  @retval EFI_UNSUPPORTED           The specified Flag or Type is not supported.
 | 
						|
                                    For example, system error may be not supported to process and Platform should have mechanism to reset system to manufacture mode.
 | 
						|
                                    Another, if system and user variables are wanted to be distinguished to process, the interface must be called after EndOfDxe.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES      Not enough resource to process the error.
 | 
						|
  @retval EFI_INVALID_PARAMETER     The specified Flag or Type is an invalid value.
 | 
						|
  @retval Others                    Other failure occurs.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PlatformVarCleanup (
 | 
						|
  IN VAR_ERROR_FLAG     Flag,
 | 
						|
  IN VAR_CLEANUP_TYPE   Type
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  EFI_FORM_BROWSER2_PROTOCOL            *FormBrowser2;
 | 
						|
  VARIABLE_CLEANUP_HII_PRIVATE_DATA     *Private;
 | 
						|
 | 
						|
  if (!mEndOfDxe) {
 | 
						|
    //
 | 
						|
    // This implementation must be called after EndOfDxe.
 | 
						|
    //
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Type >= VarCleanupMax) || ((Flag & ((VAR_ERROR_FLAG) (VAR_ERROR_FLAG_SYSTEM_ERROR & VAR_ERROR_FLAG_USER_ERROR))) == 0)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Flag == VAR_ERROR_FLAG_NO_ERROR) {
 | 
						|
    //
 | 
						|
    // Just return success if no error.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Flag & (~((VAR_ERROR_FLAG) VAR_ERROR_FLAG_SYSTEM_ERROR))) == 0) {
 | 
						|
    //
 | 
						|
    // This sample does not support system variables cleanup.
 | 
						|
    //
 | 
						|
    DEBUG ((EFI_D_ERROR, "NOTICE - VAR_ERROR_FLAG_SYSTEM_ERROR\n"));
 | 
						|
    DEBUG ((EFI_D_ERROR, "Platform should have mechanism to reset system to manufacture mode\n"));
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Continue to process VAR_ERROR_FLAG_USER_ERROR.
 | 
						|
  //
 | 
						|
 | 
						|
  //
 | 
						|
  // Create user variable nodes for the following processing.
 | 
						|
  //
 | 
						|
  CreateUserVariableNode ();
 | 
						|
 | 
						|
  switch (Type) {
 | 
						|
    case VarCleanupAll:
 | 
						|
      DeleteUserVariable (TRUE, NULL);
 | 
						|
      //
 | 
						|
      // Destroyed the created user variable nodes
 | 
						|
      //
 | 
						|
      DestroyUserVariableNode ();
 | 
						|
      return EFI_SUCCESS;
 | 
						|
      break;
 | 
						|
 | 
						|
    case VarCleanupManually:
 | 
						|
      //
 | 
						|
      // Locate FormBrowser2 protocol.
 | 
						|
      //
 | 
						|
      Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
 | 
						|
      Private = AllocateZeroPool (sizeof (VARIABLE_CLEANUP_HII_PRIVATE_DATA));
 | 
						|
      if (Private == NULL) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      Private->Signature = VARIABLE_CLEANUP_HII_PRIVATE_SIGNATURE;
 | 
						|
      Private->ConfigAccess.ExtractConfig = VariableCleanupHiiExtractConfig;
 | 
						|
      Private->ConfigAccess.RouteConfig   = VariableCleanupHiiRouteConfig;
 | 
						|
      Private->ConfigAccess.Callback      = VariableCleanupHiiCallback;
 | 
						|
 | 
						|
      Status = gBS->LocateProtocol (
 | 
						|
                      &gEfiHiiConfigRoutingProtocolGuid,
 | 
						|
                      NULL,
 | 
						|
                      (VOID **) &Private->ConfigRouting
 | 
						|
                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Install Device Path Protocol and Config Access protocol to driver handle.
 | 
						|
      //
 | 
						|
      Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                      &Private->DriverHandle,
 | 
						|
                      &gEfiDevicePathProtocolGuid,
 | 
						|
                      &mVarCleanupHiiVendorDevicePath,
 | 
						|
                      &gEfiHiiConfigAccessProtocolGuid,
 | 
						|
                      &Private->ConfigAccess,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Publish our HII data.
 | 
						|
      //
 | 
						|
      Private->HiiHandle = HiiAddPackages (
 | 
						|
                             &mVariableCleanupHiiGuid,
 | 
						|
                             Private->DriverHandle,
 | 
						|
                             PlatformVarCleanupLibStrings,
 | 
						|
                             PlatVarCleanupBin,
 | 
						|
                             NULL
 | 
						|
                             );
 | 
						|
      if (Private->HiiHandle == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      UpdateUserVariableForm (Private);
 | 
						|
 | 
						|
      Status = FormBrowser2->SendForm (
 | 
						|
                               FormBrowser2,
 | 
						|
                               &Private->HiiHandle,
 | 
						|
                               1,
 | 
						|
                               NULL,
 | 
						|
                               0,
 | 
						|
                               NULL,
 | 
						|
                               NULL
 | 
						|
                               );
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  if (Private->DriverHandle != NULL) {
 | 
						|
    gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
           Private->DriverHandle,
 | 
						|
           &gEfiDevicePathProtocolGuid,
 | 
						|
           &mVarCleanupHiiVendorDevicePath,
 | 
						|
           &gEfiHiiConfigAccessProtocolGuid,
 | 
						|
           &Private->ConfigAccess,
 | 
						|
           NULL
 | 
						|
           );
 | 
						|
  }
 | 
						|
  if (Private->HiiHandle != NULL) {
 | 
						|
    HiiRemovePackages (Private->HiiHandle);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Private);
 | 
						|
 | 
						|
  //
 | 
						|
  // Destroyed the created user variable nodes
 | 
						|
  //
 | 
						|
  DestroyUserVariableNode ();
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get last boot variable error flag.
 | 
						|
 | 
						|
  @return   Last boot variable error flag.
 | 
						|
 | 
						|
**/
 | 
						|
VAR_ERROR_FLAG
 | 
						|
EFIAPI
 | 
						|
GetLastBootVarErrorFlag (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return mLastVarErrorFlag;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Notification function of END_OF_DXE.
 | 
						|
 | 
						|
  This is a notification function registered on END_OF_DXE event.
 | 
						|
 | 
						|
  @param[in] Event      Event whose notification function is being invoked.
 | 
						|
  @param[in] Context    Pointer to the notification function's context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformVarCleanupEndOfDxeEvent (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  mEndOfDxe = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The constructor function caches the pointer to VarCheck protocol and last boot variable error flag.
 | 
						|
 | 
						|
  The constructor function locates VarCheck protocol from protocol database.
 | 
						|
  It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
 | 
						|
 | 
						|
  @param  ImageHandle   The firmware allocated handle for the EFI image.
 | 
						|
  @param  SystemTable   A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PlatformVarCleanupLibConstructor (
 | 
						|
  IN EFI_HANDLE         ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE   *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS    Status;
 | 
						|
 | 
						|
  mLastVarErrorFlag = InternalGetVarErrorFlag ();
 | 
						|
  DEBUG ((EFI_D_INFO, "mLastVarErrorFlag - 0x%02x\n", mLastVarErrorFlag));
 | 
						|
 | 
						|
  //
 | 
						|
  // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
 | 
						|
  //
 | 
						|
  Status = gBS->CreateEventEx (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  PlatformVarCleanupEndOfDxeEvent,
 | 
						|
                  NULL,
 | 
						|
                  &gEfiEndOfDxeEventGroupGuid,
 | 
						|
                  &mPlatVarCleanupLibEndOfDxeEvent
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The destructor function closes the End of DXE event.
 | 
						|
 | 
						|
  @param  ImageHandle   The firmware allocated handle for the EFI image.
 | 
						|
  @param  SystemTable   A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   The destructor completed successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PlatformVarCleanupLibDestructor (
 | 
						|
  IN EFI_HANDLE         ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE   *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS    Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Close the End of DXE event.
 | 
						|
  //
 | 
						|
  Status = gBS->CloseEvent (mPlatVarCleanupLibEndOfDxeEvent);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |