From c95d9ab81a1382b11989c691c3934306417fc019 Mon Sep 17 00:00:00 2001 From: Star Zeng Date: Tue, 25 Aug 2015 03:11:06 +0000 Subject: [PATCH] MdeModulePkg: Add PlatformVarCleanupLib library Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng Reviewed-by: Jiewen Yao git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18295 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Include/Library/PlatformVarCleanupLib.h | 61 + .../PlatformVarCleanupLib/PlatVarCleanup.h | 108 ++ .../PlatformVarCleanupLib/PlatVarCleanup.vfr | 41 + .../PlatformVarCleanupLib/PlatVarCleanupHii.h | 59 + .../PlatformVarCleanupLib/PlatVarCleanupLib.c | 1250 +++++++++++++++++ .../PlatformVarCleanupLib.inf | 73 + .../PlatformVarCleanupLib.uni | Bin 0 -> 1766 bytes .../PlatformVarCleanupLib/VfrStrings.uni | Bin 0 -> 4528 bytes MdeModulePkg/MdeModulePkg.dec | 4 + MdeModulePkg/MdeModulePkg.dsc | 1 + 10 files changed, 1597 insertions(+) create mode 100644 MdeModulePkg/Include/Library/PlatformVarCleanupLib.h create mode 100644 MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.h create mode 100644 MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.vfr create mode 100644 MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupHii.h create mode 100644 MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c create mode 100644 MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf create mode 100644 MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.uni create mode 100644 MdeModulePkg/Library/PlatformVarCleanupLib/VfrStrings.uni diff --git a/MdeModulePkg/Include/Library/PlatformVarCleanupLib.h b/MdeModulePkg/Include/Library/PlatformVarCleanupLib.h new file mode 100644 index 0000000000..a4691f0e65 --- /dev/null +++ b/MdeModulePkg/Include/Library/PlatformVarCleanupLib.h @@ -0,0 +1,61 @@ +/** @file + The library class provides platform variable cleanup services. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+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 + +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 + diff --git a/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.h b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.h new file mode 100644 index 0000000000..5290aae158 --- /dev/null +++ b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.h @@ -0,0 +1,108 @@ +/** @file + Include file for platform variable cleanup. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 diff --git a/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.vfr b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.vfr new file mode 100644 index 0000000000..7dfeafa2c4 --- /dev/null +++ b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanup.vfr @@ -0,0 +1,41 @@ +/** @file + Platform variable cleanup Formset. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+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; diff --git a/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupHii.h b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupHii.h new file mode 100644 index 0000000000..02af877b44 --- /dev/null +++ b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupHii.h @@ -0,0 +1,59 @@ +/** @file + Include file for platform variable cleanup HII. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+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 diff --git a/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c new file mode 100644 index 0000000000..d99174c4b9 --- /dev/null +++ b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c @@ -0,0 +1,1250 @@ +/** @file + Sample platform variable cleanup library implementation. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+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 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 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 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 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 + 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 + 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 . + // 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 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; +} + diff --git a/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf new file mode 100644 index 0000000000..c56a17584a --- /dev/null +++ b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf @@ -0,0 +1,73 @@ +## @file +# Sample platform variable cleanup library instance. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# +# 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 + diff --git a/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.uni b/MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.uni new file mode 100644 index 0000000000000000000000000000000000000000..e4a0debafa7e603b2d2a64f9a92d070114027deb GIT binary patch literal 1766 zcmd6nPjAye5XI+=#CKSw7eH+SNL&y?B*cJ4siVYE;Z!+sn_A=#azabLJnir8CUzQv z#0ga^@9xab&b)au>)YQgYnkJF#&Gt|F08Pro!eu3gjQ!KHnd}gvoR-`Eg6noVIwP% zOS?f{*@C&`=7f_a@;Q>TD{rB@muSZJ9o;9384gWmbIX0a(wbGwhY|Zd8T}x)l6)p$ zU4i%s89ZfuY0vG2y|P30F*zvPDSO>1xurQnTdbXvS%?1;zY`y0h8$Q_4aBkJF=JsfEOmCny*c&{jZmpF1-mKUYOYmD-BxAC z?B*U>zU5!H^K}H(Rh^R21?m@PKe?e(Reggb#F}~38eJfceu-uT^4yMgPMUbR zADP?s1v!RE2bWq?v@!iPWEXjUhrI4C`#v@s4>k8O{TyL2@SYQP>SN6fR{53J25ZO5 zk`A{popLU(iI3>)6sx{Rc7i^}t9&FrdLK#HrBlolTiGaTu=;?lqJLxk%!!ce{YC32 zA&bbqR(@*lFna?wD;oA?{(AX6`#mHS=%nHV=a4b&wM{(w`L=Y+3(pot20hT)#E$j+h;ap zzs)RW9Ke6VNmzH;`N>-RCwA(xBWwD20_Pa|;zV0kYYBM+yLQfVyFg-OFW`L1_|{(A z8+&J~%qvJ4fvLk>JTYAQ6^4MW$jK(>q7aTCO_*c&hJ0f%wy>;d?`_Kt?BfKH?60H! z(rp|-*@s`!Wtl8EV;n)z@^ur0ea;4cb`4+fTG#PNll;&@TGm$iNBkX5o6O`<;Yl@! zU!K>F{HZ9V{v10FNl&rJCoxE5XM$7Mgm^k~ePWgJZ4vKn*1J}YhG(?0DtK5NvHQD-u9&qQFz&MD~6Y;ESGh?EPyiJoK(`SQieAloOCs`i=R zP5Z{Wf@dRqtFg{*geR(BFNMlhUx64q}Tym9}a$3IyM#+`b0^^pi zwOXB^6RPh}NN&}2YQ2drVcTQBf?P?dy8Z)JLa#k(twSXm=?zpn(2Da1<5y0EUDa5= z(Gu(^+wnwBD!qa?_Q@~l+@4eYx{KBwd+_Q9TbZm@JnvOg;U0=SmTTA~`2{5EOt~^7 zJ_YBy&C@2@YqsOI78q5}Ju*RcHN4@H?v+XAhAIwmYuxzc0P7p>mpaxc;(0$QvN5{P zJ(HE2i9NDt-!0DGr$^9E-=`<5f~x(+G={&)pkK@}kO1KhKJ+hh;^&-T>e7Hr*8& zW$B{P$l5*6rsX3O@-eIDf6V7$PyH{A%f}NveDiRC##jS#W0R{FS$pjndfE-v=7O`$5XrazdAMUwIk|K_nZ1r^=Zf659IU9LwurtnrRi3s1Ch6 z>fnY%A$f(${F70gJRT3GZ;$%0MXb0xBdd6P`4~LJ``g~9t6z`(o_nhP&u_