Revision: 18295
          http://sourceforge.net/p/edk2/code/18295
Author:   lzeng14
Date:     2015-08-25 03:11:06 +0000 (Tue, 25 Aug 2015)
Log Message:
-----------
MdeModulePkg: Add PlatformVarCleanupLib library

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <[email protected]>
Reviewed-by: Jiewen Yao <[email protected]>

Modified Paths:
--------------
    trunk/edk2/MdeModulePkg/MdeModulePkg.dec
    trunk/edk2/MdeModulePkg/MdeModulePkg.dsc

Added Paths:
-----------
    trunk/edk2/MdeModulePkg/Include/Library/PlatformVarCleanupLib.h
    trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/
    trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.h
    trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.vfr
    trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupHii.h
    trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c
    
trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf
    
trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.uni
    trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/VfrStrings.uni

Added: trunk/edk2/MdeModulePkg/Include/Library/PlatformVarCleanupLib.h
===================================================================
--- trunk/edk2/MdeModulePkg/Include/Library/PlatformVarCleanupLib.h             
                (rev 0)
+++ trunk/edk2/MdeModulePkg/Include/Library/PlatformVarCleanupLib.h     
2015-08-25 03:11:06 UTC (rev 18295)
@@ -0,0 +1,61 @@
+/** @file
+  The library class provides platform variable cleanup services.
+
+Copyright (c) 2015, 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.
+
+**/
+
+#ifndef _PLATFORM_VARIABLE_CLEANUP_LIB_
+#define _PLATFORM_VARIABLE_CLEANUP_LIB_
+
+#include <Guid/VarErrorFlag.h>
+
+typedef enum {
+  VarCleanupAll,
+  VarCleanupManually,
+  VarCleanupMax,
+} VAR_CLEANUP_TYPE;
+
+/**
+  Get last boot variable error flag.
+
+  @return   Last boot variable error flag.
+
+**/
+VAR_ERROR_FLAG
+EFIAPI
+GetLastBootVarErrorFlag (
+  );
+
+/**
+  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
+  );
+
+#endif
+

Added: trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.h
===================================================================
--- trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.h      
                        (rev 0)
+++ trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.h      
2015-08-25 03:11:06 UTC (rev 18295)
@@ -0,0 +1,108 @@
+/** @file
+  Include file for platform variable cleanup.
+
+Copyright (c) 2015, 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.
+
+**/
+
+#ifndef _PLAT_VAR_CLEANUP_
+#define _PLAT_VAR_CLEANUP_
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PrintLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PlatformVarCleanupLib.h>
+
+#include <Protocol/Variable.h>
+#include <Protocol/VarCheck.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/DevicePath.h>
+
+#include <Guid/EventGroup.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/VarErrorFlag.h>
+
+#include "PlatVarCleanupHii.h"
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 PlatVarCleanupBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 PlatformVarCleanupLibStrings[];
+
+#define USER_VARIABLE_NODE_SIGNATURE SIGNATURE_32 ('U', 'V', 'N', 'S')
+
+typedef struct {
+  UINTN             Signature;
+  LIST_ENTRY        Link;
+  EFI_GUID          Guid;
+  CHAR16            *PromptString;
+  LIST_ENTRY        NameLink;
+} USER_VARIABLE_NODE;
+
+#define USER_VARIABLE_FROM_LINK(a) CR (a, USER_VARIABLE_NODE, Link, 
USER_VARIABLE_NODE_SIGNATURE)
+
+#define USER_VARIABLE_NAME_NODE_SIGNATURE SIGNATURE_32 ('U', 'V', 'N', 'N')
+
+typedef struct {
+  UINTN             Signature;
+  LIST_ENTRY        Link;
+  CHAR16            *Name;
+  UINTN             DataSize;
+  UINT32            Attributes;
+  UINT16            Index;
+  EFI_QUESTION_ID   QuestionId;
+  CHAR16            *PromptString;
+  CHAR16            *HelpString;
+  BOOLEAN           Deleted;
+} USER_VARIABLE_NAME_NODE;
+
+#define USER_VARIABLE_NAME_FROM_LINK(a) CR (a, USER_VARIABLE_NAME_NODE, Link, 
USER_VARIABLE_NAME_NODE_SIGNATURE)
+
+#pragma pack(1)
+//
+// HII specific Vendor Device Path definition.
+//
+typedef struct {
+  VENDOR_DEVICE_PATH            VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL      End;
+} HII_VENDOR_DEVICE_PATH;
+#pragma pack()
+
+#define VARIABLE_CLEANUP_HII_PRIVATE_SIGNATURE SIGNATURE_32 ('V', 'C', 'H', 
'P')
+
+typedef struct {
+  UINTN                             Signature;
+  EFI_HANDLE                        DriverHandle;
+  EFI_HII_HANDLE                    HiiHandle;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL   *ConfigRouting;
+  VARIABLE_CLEANUP_DATA             VariableCleanupData;
+} VARIABLE_CLEANUP_HII_PRIVATE_DATA;
+
+#define VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS(a) CR (a, 
VARIABLE_CLEANUP_HII_PRIVATE_DATA, ConfigAccess, 
VARIABLE_CLEANUP_HII_PRIVATE_SIGNATURE)
+
+#endif

Added: trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.vfr
===================================================================
--- trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.vfr    
                        (rev 0)
+++ trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.vfr    
2015-08-25 03:11:06 UTC (rev 18295)
@@ -0,0 +1,41 @@
+/** @file
+ Platform variable cleanup Formset.
+
+Copyright (c) 2015, 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 "PlatVarCleanupHii.h"
+
+formset
+  guid     = VARIABLE_CLEANUP_HII_GUID,
+  title    = STRING_TOKEN(STR_ENTRY_TITLE),
+  help     = STRING_TOKEN(STR_TITLE_HELP),
+
+  varstore VARIABLE_CLEANUP_DATA,
+    varid = VARIABLE_CLEANUP_VARSTORE_ID,
+    name  = VariableCleanup,
+    guid  = VARIABLE_CLEANUP_HII_GUID;
+
+  form formid = FORM_ID_VARIABLE_CLEANUP,
+    title = STRING_TOKEN(STR_TITLE);
+
+    checkbox varid = VARIABLE_CLEANUP_DATA.SelectAll,
+      prompt   = STRING_TOKEN(STR_SELECT_ALL_PROMPT),
+      help     = STRING_TOKEN(STR_SELECT_ALL_HELP),
+      flags    = INTERACTIVE,
+      key      = SELECT_ALL_QUESTION_ID,
+    endcheckbox;
+
+    label LABEL_START;
+    label LABEL_END;
+
+  endform;
+endformset;

Added: trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupHii.h
===================================================================
--- trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupHii.h   
                        (rev 0)
+++ trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupHii.h   
2015-08-25 03:11:06 UTC (rev 18295)
@@ -0,0 +1,59 @@
+/** @file
+  Include file for platform variable cleanup HII.
+
+Copyright (c) 2015, 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.
+
+**/
+
+#ifndef _PLAT_VAR_CLEANUP_HII_
+#define _PLAT_VAR_CLEANUP_HII_
+
+//
+// {24F14D8A-D7A8-4991-91E0-96C3B7DB8456}
+//
+#define VARIABLE_CLEANUP_HII_GUID \
+  { \
+    0x24f14d8a, 0xd7a8, 0x4991, { 0x91, 0xe0, 0x96, 0xc3, 0xb7, 0xdb, 0x84, 
0x56 } \
+  }
+
+#define MAX_USER_VARIABLE_COUNT         0x1000
+
+typedef struct {
+  UINT8   SelectAll;
+  //
+  // FALSE is to not delete, TRUE is to delete.
+  //
+  UINT8   UserVariable[MAX_USER_VARIABLE_COUNT];
+} VARIABLE_CLEANUP_DATA;
+
+#define VARIABLE_CLEANUP_VARSTORE_ID    0x8000
+
+//
+// Field offset of structure VARIABLE_CLEANUP_DATA
+//
+#define VAR_OFFSET(Field)               ((UINTN) &(((VARIABLE_CLEANUP_DATA *) 
0)->Field))
+#define USER_VARIABLE_VAR_OFFSET        (VAR_OFFSET (UserVariable))
+
+#define FORM_ID_VARIABLE_CLEANUP        0x8000
+
+#define LABEL_START                     0x0000
+#define LABEL_END                       0xFFFF
+
+#define SELECT_ALL_QUESTION_ID          0x7FFD
+#define SAVE_AND_EXIT_QUESTION_ID       0x7FFE
+#define NO_SAVE_AND_EXIT_QUESTION_ID    0x7FFF
+
+//
+// Tool automatic generated Question Id start from 1.
+// In order to avoid to conflict them, the user variable QuestionID offset is 
defined from 0x8000.
+//
+#define USER_VARIABLE_QUESTION_ID       0x8000
+
+#endif

Added: trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c
===================================================================
--- trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c   
                        (rev 0)
+++ trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c   
2015-08-25 03:11:06 UTC (rev 18295)
@@ -0,0 +1,1250 @@
+/** @file
+  Sample platform variable cleanup library implementation.
+
+Copyright (c) 2015, 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;
+
+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;
+
+  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;
+  }
+
+  //
+  // Retrive 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 (
+  )
+{
+  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;
+  EFI_EVENT     Event;
+
+  mLastVarErrorFlag = InternalGetVarErrorFlag ();
+  DEBUG ((EFI_D_INFO, "mLastVarErrorFlag - 0x%02x\n", mLastVarErrorFlag));
+
+  Status = gBS->LocateProtocol (
+                  &gEdkiiVarCheckProtocolGuid,
+                  NULL,
+                  (VOID **) &mVarCheck
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  PlatformVarCleanupEndOfDxeEvent,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+

Added: 
trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf
===================================================================
--- 
trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf 
                            (rev 0)
+++ 
trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf 
    2015-08-25 03:11:06 UTC (rev 18295)
@@ -0,0 +1,73 @@
+## @file
+#  Sample platform variable cleanup library instance.
+#
+#  Copyright (c) 2015, 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.
+#
+##
+
+[Defines]
+  INF_VERSION                   = 0x00010005
+  BASE_NAME                     = PlatformVarCleanupLib
+  MODULE_UNI_FILE               = PlatformVarCleanupLib.uni
+  FILE_GUID                     = 9C9623EB-4EF3-44e0-A931-F3A340D1A0F9
+  MODULE_TYPE                   = DXE_DRIVER
+  VERSION_STRING                = 1.0
+  LIBRARY_CLASS                 = PlatformVarCleanupLib|DXE_DRIVER 
DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+  CONSTRUCTOR                   = PlatformVarCleanupLibConstructor
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES          = IA32 X64
+#
+
+[Sources.common]
+  PlatVarCleanupLib.c
+  PlatVarCleanup.h
+  PlatVarCleanupHii.h
+  PlatVarCleanup.vfr
+  VfrStrings.uni
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  BaseLib
+  DebugLib
+  BaseMemoryLib
+  PrintLib
+  MemoryAllocationLib
+  HiiLib
+
+[Guids]
+  gEfiIfrTianoGuid                  ## SOMETIMES_PRODUCES   ## GUID
+  gEdkiiVarErrorFlagGuid            ## CONSUMES             ## 
Variable:L"VarErrorFlag"
+  gEfiEndOfDxeEventGroupGuid        ## CONSUMES             ## Event
+  gEfiCertPkcs7Guid                 ## SOMETIMES_CONSUMES   ## GUID
+  gEfiCertTypeRsa2048Sha256Guid     ## SOMETIMES_CONSUMES   ## GUID
+
+[Protocols]
+  gEfiVariableArchProtocolGuid      ## CONSUMES
+  gEdkiiVarCheckProtocolGuid        ## CONSUMES
+  gEfiDevicePathProtocolGuid        ## SOMETIMES_PRODUCES
+  gEfiFormBrowser2ProtocolGuid      ## SOMETIMES_CONSUMES
+  gEfiHiiConfigAccessProtocolGuid   ## SOMETIMES_PRODUCES
+  gEfiHiiConfigRoutingProtocolGuid  ## SOMETIMES_CONSUMES
+
+[Depex]
+  gEdkiiVarCheckProtocolGuid AND
+  gEfiVariableArchProtocolGuid
+

Added: 
trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.uni
===================================================================
--- 
trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.uni 
                            (rev 0)
+++ 
trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.uni 
    2015-08-25 03:11:06 UTC (rev 18295)
@@ -0,0 +1,43 @@
+\xFF\xFE/+++++++++++++++++++++\ No newline at end of file

Added: trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/VfrStrings.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/VfrStrings.uni        
                        (rev 0)
+++ trunk/edk2/MdeModulePkg/Library/PlatformVarCleanupLib/VfrStrings.uni        
2015-08-25 03:11:06 UTC (rev 18295)
@@ -0,0 +1,69 @@
+\xFF\xFE/++++++++++++++++++++++++++++++++++\ No newline at end of file

Modified: trunk/edk2/MdeModulePkg/MdeModulePkg.dec
===================================================================
--- trunk/edk2/MdeModulePkg/MdeModulePkg.dec    2015-08-25 03:10:32 UTC (rev 
18294)
+++ trunk/edk2/MdeModulePkg/MdeModulePkg.dec    2015-08-25 03:11:06 UTC (rev 
18295)
@@ -127,6 +127,10 @@
   #
   VarCheckLib|Include/Library/VarCheckLib.h
 
+  ## @libraryclass  Provides services to get variable error flag and do 
platform variable cleanup.
+  #
+  PlatformVarCleanupLib|Include/Library/PlatformVarCleanupLib.h
+
 [Guids]
   ## MdeModule package token space guid
   # Include/Guid/MdeModulePkgTokenSpace.h

Modified: trunk/edk2/MdeModulePkg/MdeModulePkg.dsc
===================================================================
--- trunk/edk2/MdeModulePkg/MdeModulePkg.dsc    2015-08-25 03:10:32 UTC (rev 
18294)
+++ trunk/edk2/MdeModulePkg/MdeModulePkg.dsc    2015-08-25 03:11:06 UTC (rev 
18295)
@@ -282,6 +282,7 @@
   MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
   MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
   MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
+  MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf
 
   MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
   MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf


------------------------------------------------------------------------------
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to