mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 19:23:54 +01:00 
			
		
		
		
	REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1295 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1295 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Sample platform variable cleanup library implementation.
 | |
| 
 | |
| Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "PlatVarCleanup.h"
 | |
| 
 | |
| VAR_ERROR_FLAG            mLastVarErrorFlag = VAR_ERROR_FLAG_NO_ERROR;
 | |
| EDKII_VAR_CHECK_PROTOCOL  *mVarCheck        = NULL;
 | |
| 
 | |
| ///
 | |
| /// The flag to indicate whether the platform has left the DXE phase of execution.
 | |
| ///
 | |
| BOOLEAN  mEndOfDxe = FALSE;
 | |
| 
 | |
| EFI_EVENT  mPlatVarCleanupLibEndOfDxeEvent = NULL;
 | |
| 
 | |
| LIST_ENTRY  mUserVariableList        = INITIALIZE_LIST_HEAD_VARIABLE (mUserVariableList);
 | |
| UINT16      mUserVariableCount       = 0;
 | |
| UINT16      mMarkedUserVariableCount = 0;
 | |
| 
 | |
| EFI_GUID  mVariableCleanupHiiGuid = VARIABLE_CLEANUP_HII_GUID;
 | |
| CHAR16    mVarStoreName[]         = L"VariableCleanup";
 | |
| 
 | |
| HII_VENDOR_DEVICE_PATH  mVarCleanupHiiVendorDevicePath = {
 | |
|   {
 | |
|     {
 | |
|       HARDWARE_DEVICE_PATH,
 | |
|       HW_VENDOR_DP,
 | |
|       {
 | |
|         (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
 | |
|         (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
 | |
|       }
 | |
|     },
 | |
|     VARIABLE_CLEANUP_HII_GUID
 | |
|   },
 | |
|   {
 | |
|     END_DEVICE_PATH_TYPE,
 | |
|     END_ENTIRE_DEVICE_PATH_SUBTYPE,
 | |
|     {
 | |
|       (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)),
 | |
|       (UINT8)((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Internal get variable error flag.
 | |
| 
 | |
|   @return   Variable error flag.
 | |
| 
 | |
| **/
 | |
| VAR_ERROR_FLAG
 | |
| InternalGetVarErrorFlag (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS      Status;
 | |
|   UINTN           Size;
 | |
|   VAR_ERROR_FLAG  ErrorFlag;
 | |
| 
 | |
|   Size   = sizeof (ErrorFlag);
 | |
|   Status = gRT->GetVariable (
 | |
|                   VAR_ERROR_FLAG_NAME,
 | |
|                   &gEdkiiVarErrorFlagGuid,
 | |
|                   NULL,
 | |
|                   &Size,
 | |
|                   &ErrorFlag
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_INFO, "%s - not found\n", VAR_ERROR_FLAG_NAME));
 | |
|     return VAR_ERROR_FLAG_NO_ERROR;
 | |
|   }
 | |
| 
 | |
|   return ErrorFlag;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Is user variable?
 | |
| 
 | |
|   @param[in] Name   Pointer to variable name.
 | |
|   @param[in] Guid   Pointer to vendor guid.
 | |
| 
 | |
|   @retval TRUE      User variable.
 | |
|   @retval FALSE     System variable.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsUserVariable (
 | |
|   IN CHAR16    *Name,
 | |
|   IN EFI_GUID  *Guid
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   VAR_CHECK_VARIABLE_PROPERTY  Property;
 | |
| 
 | |
|   if (mVarCheck == NULL) {
 | |
|     gBS->LocateProtocol (
 | |
|            &gEdkiiVarCheckProtocolGuid,
 | |
|            NULL,
 | |
|            (VOID **)&mVarCheck
 | |
|            );
 | |
|   }
 | |
| 
 | |
|   ASSERT (mVarCheck != NULL);
 | |
| 
 | |
|   ZeroMem (&Property, sizeof (Property));
 | |
|   Status = mVarCheck->VariablePropertyGet (
 | |
|                         Name,
 | |
|                         Guid,
 | |
|                         &Property
 | |
|                         );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // No property, it is user variable.
 | |
|     //
 | |
|     DEBUG ((DEBUG_INFO, "PlatformVarCleanup - User variable: %g:%s\n", Guid, Name));
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   //  DEBUG ((DEBUG_INFO, "PlatformVarCleanup - Variable Property: %g:%s\n", Guid, Name));
 | |
|   //  DEBUG ((DEBUG_INFO, "  Revision  - 0x%04x\n", Property.Revision));
 | |
|   //  DEBUG ((DEBUG_INFO, "  Property  - 0x%04x\n", Property.Property));
 | |
|   //  DEBUG ((DEBUG_INFO, "  Attribute - 0x%08x\n", Property.Attributes));
 | |
|   //  DEBUG ((DEBUG_INFO, "  MinSize   - 0x%x\n", Property.MinSize));
 | |
|   //  DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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->DriverHandle
 | |
|                          );
 | |
|     Size          = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
 | |
|     ConfigRequest = AllocateZeroPool (Size);
 | |
|     ASSERT (ConfigRequest != NULL);
 | |
|     AllocatedRequest = TRUE;
 | |
|     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
 | |
|     FreePool (ConfigRequestHdr);
 | |
|   }
 | |
| 
 | |
|   Status = Private->ConfigRouting->BlockToConfig (
 | |
|                                      Private->ConfigRouting,
 | |
|                                      ConfigRequest,
 | |
|                                      (UINT8 *)&Private->VariableCleanupData,
 | |
|                                      BufferSize,
 | |
|                                      Results,
 | |
|                                      Progress
 | |
|                                      );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Free the allocated config request string.
 | |
|   //
 | |
|   if (AllocatedRequest) {
 | |
|     FreePool (ConfigRequest);
 | |
|     ConfigRequest = NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set Progress string to the original request string or the string's null terminator.
 | |
|   //
 | |
|   if (Request == NULL) {
 | |
|     *Progress = NULL;
 | |
|   } else if (StrStr (Request, L"OFFSET") == NULL) {
 | |
|     *Progress = Request + StrLen (Request);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update user variable form.
 | |
| 
 | |
|   @param[in] Private    Points to the VARIABLE_CLEANUP_HII_PRIVATE_DATA.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateUserVariableForm (
 | |
|   IN VARIABLE_CLEANUP_HII_PRIVATE_DATA  *Private
 | |
|   )
 | |
| {
 | |
|   EFI_STRING_ID            PromptStringToken;
 | |
|   EFI_STRING_ID            HelpStringToken;
 | |
|   VOID                     *StartOpCodeHandle;
 | |
|   VOID                     *EndOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL       *StartLabel;
 | |
|   EFI_IFR_GUID_LABEL       *EndLabel;
 | |
|   USER_VARIABLE_NODE       *UserVariableNode;
 | |
|   LIST_ENTRY               *Link;
 | |
|   USER_VARIABLE_NAME_NODE  *UserVariableNameNode;
 | |
|   LIST_ENTRY               *NameLink;
 | |
|   BOOLEAN                  Created;
 | |
| 
 | |
|   //
 | |
|   // Init OpCode Handle.
 | |
|   //
 | |
|   StartOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
|   ASSERT (StartOpCodeHandle != NULL);
 | |
| 
 | |
|   EndOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
|   ASSERT (EndOpCodeHandle != NULL);
 | |
| 
 | |
|   //
 | |
|   // Create Hii Extend Label OpCode as the start opcode.
 | |
|   //
 | |
|   StartLabel               = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
 | |
|   StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | |
|   StartLabel->Number       = LABEL_START;
 | |
| 
 | |
|   //
 | |
|   // Create Hii Extend Label OpCode as the end opcode.
 | |
|   //
 | |
|   EndLabel               = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
 | |
|   EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | |
|   EndLabel->Number       = LABEL_END;
 | |
| 
 | |
|   HiiUpdateForm (
 | |
|     Private->HiiHandle,
 | |
|     &mVariableCleanupHiiGuid,
 | |
|     FORM_ID_VARIABLE_CLEANUP,
 | |
|     StartOpCodeHandle, // LABEL_START
 | |
|     EndOpCodeHandle    // LABEL_END
 | |
|     );
 | |
| 
 | |
|   for (Link = mUserVariableList.ForwardLink
 | |
|        ; Link != &mUserVariableList
 | |
|        ; Link = Link->ForwardLink)
 | |
|   {
 | |
|     UserVariableNode = USER_VARIABLE_FROM_LINK (Link);
 | |
| 
 | |
|     //
 | |
|     // Create checkbox opcode for variables in the same variable GUID space.
 | |
|     //
 | |
|     Created = FALSE;
 | |
|     for (NameLink = UserVariableNode->NameLink.ForwardLink
 | |
|          ; NameLink != &UserVariableNode->NameLink
 | |
|          ; NameLink = NameLink->ForwardLink)
 | |
|     {
 | |
|       UserVariableNameNode = USER_VARIABLE_NAME_FROM_LINK (NameLink);
 | |
| 
 | |
|       if (!UserVariableNameNode->Deleted) {
 | |
|         if (!Created) {
 | |
|           //
 | |
|           // Create subtitle opcode for variable GUID.
 | |
|           //
 | |
|           PromptStringToken = HiiSetString (Private->HiiHandle, 0, UserVariableNode->PromptString, NULL);
 | |
|           HiiCreateSubTitleOpCode (StartOpCodeHandle, PromptStringToken, 0, 0, 0);
 | |
|           Created = TRUE;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Only create opcode for the non-deleted variables.
 | |
|         //
 | |
|         PromptStringToken = HiiSetString (Private->HiiHandle, 0, UserVariableNameNode->PromptString, NULL);
 | |
|         HelpStringToken   = HiiSetString (Private->HiiHandle, 0, UserVariableNameNode->HelpString, NULL);
 | |
|         HiiCreateCheckBoxOpCode (
 | |
|           StartOpCodeHandle,
 | |
|           UserVariableNameNode->QuestionId,
 | |
|           VARIABLE_CLEANUP_VARSTORE_ID,
 | |
|           (UINT16)(USER_VARIABLE_VAR_OFFSET + UserVariableNameNode->Index),
 | |
|           PromptStringToken,
 | |
|           HelpStringToken,
 | |
|           EFI_IFR_FLAG_CALLBACK,
 | |
|           Private->VariableCleanupData.UserVariable[UserVariableNameNode->Index],
 | |
|           NULL
 | |
|           );
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   HiiCreateSubTitleOpCode (
 | |
|     StartOpCodeHandle,
 | |
|     STRING_TOKEN (STR_NULL_STRING),
 | |
|     0,
 | |
|     0,
 | |
|     0
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Create the "Apply changes" and "Discard changes" tags.
 | |
|   //
 | |
|   HiiCreateActionOpCode (
 | |
|     StartOpCodeHandle,
 | |
|     SAVE_AND_EXIT_QUESTION_ID,
 | |
|     STRING_TOKEN (STR_SAVE_AND_EXIT),
 | |
|     STRING_TOKEN (STR_NULL_STRING),
 | |
|     EFI_IFR_FLAG_CALLBACK,
 | |
|     0
 | |
|     );
 | |
|   HiiCreateActionOpCode (
 | |
|     StartOpCodeHandle,
 | |
|     NO_SAVE_AND_EXIT_QUESTION_ID,
 | |
|     STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
 | |
|     STRING_TOKEN (STR_NULL_STRING),
 | |
|     EFI_IFR_FLAG_CALLBACK,
 | |
|     0
 | |
|     );
 | |
| 
 | |
|   HiiUpdateForm (
 | |
|     Private->HiiHandle,
 | |
|     &mVariableCleanupHiiGuid,
 | |
|     FORM_ID_VARIABLE_CLEANUP,
 | |
|     StartOpCodeHandle, // LABEL_START
 | |
|     EndOpCodeHandle    // LABEL_END
 | |
|     );
 | |
| 
 | |
|   HiiFreeOpCodeHandle (StartOpCodeHandle);
 | |
|   HiiFreeOpCodeHandle (EndOpCodeHandle);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function applies changes in a driver's configuration.
 | |
|   Input is a Configuration, which has the routing data for this
 | |
|   driver followed by name / value configuration pairs. The driver
 | |
|   must apply those pairs to its configurable storage. If the
 | |
|   driver's configuration is stored in a linear block of data
 | |
|   and the driver's name / value pairs are in <BlockConfig>
 | |
|   format, it may use the ConfigToBlock helper function (above) to
 | |
|   simplify the job. Currently not implemented.
 | |
| 
 | |
|   @param[in]  This                  Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | |
|   @param[in]  Configuration         A null-terminated Unicode string in
 | |
|                                     <ConfigString> format.
 | |
|   @param[out] Progress              A pointer to a string filled in with the
 | |
|                                     offset of the most recent '&' before the
 | |
|                                     first failing name / value pair (or the
 | |
|                                     beginn ing of the string if the failure
 | |
|                                     is in the first name / value pair) or
 | |
|                                     the terminating NULL if all was
 | |
|                                     successful.
 | |
| 
 | |
|   @retval EFI_SUCCESS               The results have been distributed or are
 | |
|                                     awaiting distribution.
 | |
|   @retval EFI_OUT_OF_RESOURCES      Not enough memory to store the
 | |
|                                     parts of the results that must be
 | |
|                                     stored awaiting possible future
 | |
|                                     protocols.
 | |
|   @retval EFI_INVALID_PARAMETERS    Passing in a NULL for the
 | |
|                                     Results parameter would result
 | |
|                                     in this type of error.
 | |
|   @retval EFI_NOT_FOUND             Target for the specified routing data
 | |
|                                     was not found.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VariableCleanupHiiRouteConfig (
 | |
|   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
 | |
|   IN  CONST EFI_STRING                      Configuration,
 | |
|   OUT EFI_STRING                            *Progress
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                         Status;
 | |
|   VARIABLE_CLEANUP_HII_PRIVATE_DATA  *Private;
 | |
|   UINTN                              BufferSize;
 | |
| 
 | |
|   if (Progress == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *Progress = Configuration;
 | |
| 
 | |
|   if (Configuration == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check routing data in <ConfigHdr>.
 | |
|   // Note: there is no name for Name/Value storage, only GUID will be checked.
 | |
|   //
 | |
|   if (!HiiIsConfigHdrMatch (Configuration, &mVariableCleanupHiiGuid, mVarStoreName)) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   Private = VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS (This);
 | |
|   //
 | |
|   // Get Buffer Storage data.
 | |
|   //
 | |
|   BufferSize = sizeof (VARIABLE_CLEANUP_DATA);
 | |
|   //
 | |
|   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
 | |
|   //
 | |
|   Status = Private->ConfigRouting->ConfigToBlock (
 | |
|                                      Private->ConfigRouting,
 | |
|                                      Configuration,
 | |
|                                      (UINT8 *)&Private->VariableCleanupData,
 | |
|                                      &BufferSize,
 | |
|                                      Progress
 | |
|                                      );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   DeleteUserVariable (FALSE, &Private->VariableCleanupData);
 | |
|   //
 | |
|   // For "F10" hotkey to refresh the form.
 | |
|   //
 | |
|   //  UpdateUserVariableForm (Private);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function is called to provide results data to the driver.
 | |
|   This data consists of a unique key that is used to identify
 | |
|   which data is either being passed back or being asked for.
 | |
| 
 | |
|   @param[in]  This                  Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | |
|   @param[in]  Action                Specifies the type of action taken by the browser.
 | |
|   @param[in]  QuestionId            A unique value which is sent to the original
 | |
|                                     exporting driver so that it can identify the type
 | |
|                                     of data to expect. The format of the data tends to
 | |
|                                     vary based on the opcode that generated the callback.
 | |
|   @param[in]  Type                  The type of value for the question.
 | |
|   @param[in]  Value                 A pointer to the data being sent to the original
 | |
|                                     exporting driver.
 | |
|   @param[out] ActionRequest         On return, points to the action requested by the
 | |
|                                     callback function.
 | |
| 
 | |
|   @retval EFI_SUCCESS               The callback successfully handled the action.
 | |
|   @retval EFI_OUT_OF_RESOURCES      Not enough storage is available to hold the
 | |
|                                     variable and its data.
 | |
|   @retval EFI_DEVICE_ERROR          The variable could not be saved.
 | |
|   @retval EFI_UNSUPPORTED           The specified Action is not supported by the
 | |
|                                     callback.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VariableCleanupHiiCallback (
 | |
|   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
 | |
|   IN  EFI_BROWSER_ACTION                    Action,
 | |
|   IN  EFI_QUESTION_ID                       QuestionId,
 | |
|   IN  UINT8                                 Type,
 | |
|   IN  EFI_IFR_TYPE_VALUE                    *Value,
 | |
|   OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest
 | |
|   )
 | |
| {
 | |
|   VARIABLE_CLEANUP_HII_PRIVATE_DATA  *Private;
 | |
|   VARIABLE_CLEANUP_DATA              *VariableCleanupData;
 | |
| 
 | |
|   Private = VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS (This);
 | |
| 
 | |
|   if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
 | |
|     //
 | |
|     // All other action return unsupported.
 | |
|     //
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve uncommitted data from Form Browser.
 | |
|   //
 | |
|   VariableCleanupData = &Private->VariableCleanupData;
 | |
|   HiiGetBrowserData (&mVariableCleanupHiiGuid, mVarStoreName, sizeof (VARIABLE_CLEANUP_DATA), (UINT8 *)VariableCleanupData);
 | |
|   if (Action == EFI_BROWSER_ACTION_CHANGING) {
 | |
|     if (Value == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
 | |
|     if ((Value == NULL) || (ActionRequest == NULL)) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     if ((QuestionId >= USER_VARIABLE_QUESTION_ID) && (QuestionId < USER_VARIABLE_QUESTION_ID + MAX_USER_VARIABLE_COUNT)) {
 | |
|       if (Value->b) {
 | |
|         //
 | |
|         // Means one user variable checkbox is marked to delete but not press F10 or "Commit Changes and Exit" menu.
 | |
|         //
 | |
|         mMarkedUserVariableCount++;
 | |
|         ASSERT (mMarkedUserVariableCount <= mUserVariableCount);
 | |
|         if (mMarkedUserVariableCount == mUserVariableCount) {
 | |
|           //
 | |
|           // All user variables have been marked, then also mark the SelectAll checkbox.
 | |
|           //
 | |
|           VariableCleanupData->SelectAll = TRUE;
 | |
|         }
 | |
|       } else {
 | |
|         //
 | |
|         // Means one user variable checkbox is unmarked.
 | |
|         //
 | |
|         mMarkedUserVariableCount--;
 | |
|         //
 | |
|         // Also unmark the SelectAll checkbox.
 | |
|         //
 | |
|         VariableCleanupData->SelectAll = FALSE;
 | |
|       }
 | |
|     } else {
 | |
|       switch (QuestionId) {
 | |
|         case SELECT_ALL_QUESTION_ID:
 | |
|           if (Value->b) {
 | |
|             //
 | |
|             // Means the SelectAll checkbox is marked to delete all user variables but not press F10 or "Commit Changes and Exit" menu.
 | |
|             //
 | |
|             SetMem (VariableCleanupData->UserVariable, sizeof (VariableCleanupData->UserVariable), TRUE);
 | |
|             mMarkedUserVariableCount = mUserVariableCount;
 | |
|           } else {
 | |
|             //
 | |
|             // Means the SelectAll checkbox is unmarked.
 | |
|             //
 | |
|             SetMem (VariableCleanupData->UserVariable, sizeof (VariableCleanupData->UserVariable), FALSE);
 | |
|             mMarkedUserVariableCount = 0;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         case SAVE_AND_EXIT_QUESTION_ID:
 | |
|           DeleteUserVariable (FALSE, VariableCleanupData);
 | |
|           *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
 | |
|           break;
 | |
| 
 | |
|         case NO_SAVE_AND_EXIT_QUESTION_ID:
 | |
|           //
 | |
|           // Restore local maintain data.
 | |
|           //
 | |
|           *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
 | |
|           break;
 | |
| 
 | |
|         default:
 | |
|           break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Pass changed uncommitted data back to Form Browser.
 | |
|   //
 | |
|   HiiSetBrowserData (&mVariableCleanupHiiGuid, mVarStoreName, sizeof (VARIABLE_CLEANUP_DATA), (UINT8 *)VariableCleanupData, NULL);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Platform variable cleanup.
 | |
| 
 | |
|   @param[in] Flag                   Variable error flag.
 | |
|   @param[in] Type                   Variable cleanup type.
 | |
|                                     If it is VarCleanupManually, the interface must be called after console connected.
 | |
| 
 | |
|   @retval EFI_SUCCESS               No error or error processed.
 | |
|   @retval EFI_UNSUPPORTED           The specified Flag or Type is not supported.
 | |
|                                     For example, system error may be not supported to process and Platform should have mechanism to reset system to manufacture mode.
 | |
|                                     Another, if system and user variables are wanted to be distinguished to process, the interface must be called after EndOfDxe.
 | |
|   @retval EFI_OUT_OF_RESOURCES      Not enough resource to process the error.
 | |
|   @retval EFI_INVALID_PARAMETER     The specified Flag or Type is an invalid value.
 | |
|   @retval Others                    Other failure occurs.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| PlatformVarCleanup (
 | |
|   IN VAR_ERROR_FLAG    Flag,
 | |
|   IN VAR_CLEANUP_TYPE  Type
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                         Status;
 | |
|   EFI_FORM_BROWSER2_PROTOCOL         *FormBrowser2;
 | |
|   VARIABLE_CLEANUP_HII_PRIVATE_DATA  *Private;
 | |
| 
 | |
|   if (!mEndOfDxe) {
 | |
|     //
 | |
|     // This implementation must be called after EndOfDxe.
 | |
|     //
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if ((Type >= VarCleanupMax) || ((Flag & ((VAR_ERROR_FLAG)(VAR_ERROR_FLAG_SYSTEM_ERROR & VAR_ERROR_FLAG_USER_ERROR))) == 0)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Flag == VAR_ERROR_FLAG_NO_ERROR) {
 | |
|     //
 | |
|     // Just return success if no error.
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if ((Flag & (~((VAR_ERROR_FLAG)VAR_ERROR_FLAG_SYSTEM_ERROR))) == 0) {
 | |
|     //
 | |
|     // This sample does not support system variables cleanup.
 | |
|     //
 | |
|     DEBUG ((DEBUG_ERROR, "NOTICE - VAR_ERROR_FLAG_SYSTEM_ERROR\n"));
 | |
|     DEBUG ((DEBUG_ERROR, "Platform should have mechanism to reset system to manufacture mode\n"));
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Continue to process VAR_ERROR_FLAG_USER_ERROR.
 | |
|   //
 | |
| 
 | |
|   //
 | |
|   // Create user variable nodes for the following processing.
 | |
|   //
 | |
|   CreateUserVariableNode ();
 | |
| 
 | |
|   switch (Type) {
 | |
|     case VarCleanupAll:
 | |
|       DeleteUserVariable (TRUE, NULL);
 | |
|       //
 | |
|       // Destroyed the created user variable nodes
 | |
|       //
 | |
|       DestroyUserVariableNode ();
 | |
|       return EFI_SUCCESS;
 | |
|       break;
 | |
| 
 | |
|     case VarCleanupManually:
 | |
|       //
 | |
|       // Locate FormBrowser2 protocol.
 | |
|       //
 | |
|       Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **)&FormBrowser2);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         return Status;
 | |
|       }
 | |
| 
 | |
|       Private = AllocateZeroPool (sizeof (VARIABLE_CLEANUP_HII_PRIVATE_DATA));
 | |
|       if (Private == NULL) {
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       Private->Signature                  = VARIABLE_CLEANUP_HII_PRIVATE_SIGNATURE;
 | |
|       Private->ConfigAccess.ExtractConfig = VariableCleanupHiiExtractConfig;
 | |
|       Private->ConfigAccess.RouteConfig   = VariableCleanupHiiRouteConfig;
 | |
|       Private->ConfigAccess.Callback      = VariableCleanupHiiCallback;
 | |
| 
 | |
|       Status = gBS->LocateProtocol (
 | |
|                       &gEfiHiiConfigRoutingProtocolGuid,
 | |
|                       NULL,
 | |
|                       (VOID **)&Private->ConfigRouting
 | |
|                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto Done;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Install Device Path Protocol and Config Access protocol to driver handle.
 | |
|       //
 | |
|       Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                       &Private->DriverHandle,
 | |
|                       &gEfiDevicePathProtocolGuid,
 | |
|                       &mVarCleanupHiiVendorDevicePath,
 | |
|                       &gEfiHiiConfigAccessProtocolGuid,
 | |
|                       &Private->ConfigAccess,
 | |
|                       NULL
 | |
|                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto Done;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Publish our HII data.
 | |
|       //
 | |
|       Private->HiiHandle = HiiAddPackages (
 | |
|                              &mVariableCleanupHiiGuid,
 | |
|                              Private->DriverHandle,
 | |
|                              PlatformVarCleanupLibStrings,
 | |
|                              PlatVarCleanupBin,
 | |
|                              NULL
 | |
|                              );
 | |
|       if (Private->HiiHandle == NULL) {
 | |
|         Status = EFI_OUT_OF_RESOURCES;
 | |
|         goto Done;
 | |
|       }
 | |
| 
 | |
|       UpdateUserVariableForm (Private);
 | |
| 
 | |
|       Status = FormBrowser2->SendForm (
 | |
|                                FormBrowser2,
 | |
|                                &Private->HiiHandle,
 | |
|                                1,
 | |
|                                NULL,
 | |
|                                0,
 | |
|                                NULL,
 | |
|                                NULL
 | |
|                                );
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return EFI_UNSUPPORTED;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (Private->DriverHandle != NULL) {
 | |
|     gBS->UninstallMultipleProtocolInterfaces (
 | |
|            Private->DriverHandle,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            &mVarCleanupHiiVendorDevicePath,
 | |
|            &gEfiHiiConfigAccessProtocolGuid,
 | |
|            &Private->ConfigAccess,
 | |
|            NULL
 | |
|            );
 | |
|   }
 | |
| 
 | |
|   if (Private->HiiHandle != NULL) {
 | |
|     HiiRemovePackages (Private->HiiHandle);
 | |
|   }
 | |
| 
 | |
|   FreePool (Private);
 | |
| 
 | |
|   //
 | |
|   // Destroyed the created user variable nodes
 | |
|   //
 | |
|   DestroyUserVariableNode ();
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get last boot variable error flag.
 | |
| 
 | |
|   @return   Last boot variable error flag.
 | |
| 
 | |
| **/
 | |
| VAR_ERROR_FLAG
 | |
| EFIAPI
 | |
| GetLastBootVarErrorFlag (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   return mLastVarErrorFlag;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Notification function of END_OF_DXE.
 | |
| 
 | |
|   This is a notification function registered on END_OF_DXE event.
 | |
| 
 | |
|   @param[in] Event      Event whose notification function is being invoked.
 | |
|   @param[in] Context    Pointer to the notification function's context.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| PlatformVarCleanupEndOfDxeEvent (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   )
 | |
| {
 | |
|   mEndOfDxe = TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The constructor function caches the pointer to VarCheck protocol and last boot variable error flag.
 | |
| 
 | |
|   The constructor function locates VarCheck protocol from protocol database.
 | |
|   It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
 | |
| 
 | |
|   @param  ImageHandle   The firmware allocated handle for the EFI image.
 | |
|   @param  SystemTable   A pointer to the EFI System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| PlatformVarCleanupLibConstructor (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   mLastVarErrorFlag = InternalGetVarErrorFlag ();
 | |
|   DEBUG ((DEBUG_INFO, "mLastVarErrorFlag - 0x%02x\n", mLastVarErrorFlag));
 | |
| 
 | |
|   //
 | |
|   // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
 | |
|   //
 | |
|   Status = gBS->CreateEventEx (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_CALLBACK,
 | |
|                   PlatformVarCleanupEndOfDxeEvent,
 | |
|                   NULL,
 | |
|                   &gEfiEndOfDxeEventGroupGuid,
 | |
|                   &mPlatVarCleanupLibEndOfDxeEvent
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The destructor function closes the End of DXE event.
 | |
| 
 | |
|   @param  ImageHandle   The firmware allocated handle for the EFI image.
 | |
|   @param  SystemTable   A pointer to the EFI System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The destructor completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| PlatformVarCleanupLibDestructor (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // Close the End of DXE event.
 | |
|   //
 | |
|   Status = gBS->CloseEvent (mPlatVarCleanupLibEndOfDxeEvent);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |