mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-28 09:43:50 +01:00 
			
		
		
		
	UEFI spec: Each load option entry resides in a Boot####, Driver####, SysPrep####, OsRecovery#### or PlatformRecovery#### variable where #### is replaced by a unique option number in printable hexadecimal representation using the digits 0-9, and the upper case versions of the characters A-F (0000-FFFF). The patch also makes L"HwErrRec####" follow this rule. Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
		
			
				
	
	
		
			671 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			671 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Implementation functions and structures for var check services.
 | |
| 
 | |
| Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <Library/VarCheckLib.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| 
 | |
| #include <Guid/GlobalVariable.h>
 | |
| #include <Guid/HardwareErrorVariable.h>
 | |
| 
 | |
| BOOLEAN mVarCheckLibEndOfDxe    = FALSE;
 | |
| 
 | |
| #define VAR_CHECK_TABLE_SIZE    0x8
 | |
| 
 | |
| UINTN                                   mVarCheckLibEndOfDxeCallbackCount = 0;
 | |
| UINTN                                   mVarCheckLibEndOfDxeCallbackMaxCount = 0;
 | |
| VAR_CHECK_END_OF_DXE_CALLBACK           *mVarCheckLibEndOfDxeCallback = NULL;
 | |
| 
 | |
| UINTN                                   mVarCheckLibAddressPointerCount = 0;
 | |
| UINTN                                   mVarCheckLibAddressPointerMaxCount = 0;
 | |
| VOID                                    ***mVarCheckLibAddressPointer = NULL;
 | |
| 
 | |
| UINTN                                   mNumberOfVarCheckHandler = 0;
 | |
| UINTN                                   mMaxNumberOfVarCheckHandler = 0;
 | |
| VAR_CHECK_SET_VARIABLE_CHECK_HANDLER    *mVarCheckHandlerTable = NULL;
 | |
| 
 | |
| typedef struct {
 | |
|   EFI_GUID                      Guid;
 | |
|   VAR_CHECK_VARIABLE_PROPERTY   VariableProperty;
 | |
|   //CHAR16                        *Name;
 | |
| } VAR_CHECK_VARIABLE_ENTRY;
 | |
| 
 | |
| UINTN                                   mNumberOfVarCheckVariable = 0;
 | |
| UINTN                                   mMaxNumberOfVarCheckVariable = 0;
 | |
| VARIABLE_ENTRY_PROPERTY                 **mVarCheckVariableTable = NULL;
 | |
| 
 | |
| //
 | |
| // Handle variables with wildcard name specially.
 | |
| //
 | |
| VARIABLE_ENTRY_PROPERTY mVarCheckVariableWithWildcardName[] = {
 | |
|   {
 | |
|     &gEfiGlobalVariableGuid,
 | |
|     L"Boot####",
 | |
|     {
 | |
|       0
 | |
|     },
 | |
|   },
 | |
|   {
 | |
|     &gEfiGlobalVariableGuid,
 | |
|     L"Driver####",
 | |
|     {
 | |
|       0
 | |
|     },
 | |
|   },
 | |
|   {
 | |
|     &gEfiGlobalVariableGuid,
 | |
|     L"SysPrep####",
 | |
|     {
 | |
|       0
 | |
|     },
 | |
|   },
 | |
|   {
 | |
|     &gEfiGlobalVariableGuid,
 | |
|     L"Key####",
 | |
|     {
 | |
|       0
 | |
|     },
 | |
|   },
 | |
|   {
 | |
|     &gEfiGlobalVariableGuid,
 | |
|     L"PlatformRecovery####",
 | |
|     {
 | |
|       0
 | |
|     },
 | |
|   },
 | |
|   {
 | |
|     &gEfiHardwareErrorVariableGuid,
 | |
|     L"HwErrRec####",
 | |
|     {
 | |
|       0
 | |
|     },
 | |
|   },
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Check if a Unicode character is an upper case hexadecimal character.
 | |
| 
 | |
|   This function checks if a Unicode character is an upper case
 | |
|   hexadecimal character.  The valid upper case hexadecimal character is
 | |
|   L'0' to L'9', or L'A' to L'F'.
 | |
| 
 | |
| 
 | |
|   @param[in] Char       The character to check against.
 | |
| 
 | |
|   @retval TRUE          If the Char is an upper case hexadecmial character.
 | |
|   @retval FALSE         If the Char is not an upper case hexadecmial character.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| VarCheckInternalIsHexaDecimalDigitCharacter (
 | |
|   IN CHAR16             Char
 | |
|   )
 | |
| {
 | |
|   return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F'));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Variable property get with wildcard name.
 | |
| 
 | |
|   @param[in] VariableName       Pointer to variable name.
 | |
|   @param[in] VendorGuid         Pointer to variable vendor GUID.
 | |
|   @param[in] WildcardMatch      Try wildcard match or not.
 | |
| 
 | |
|   @return Pointer to variable property.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_VARIABLE_PROPERTY *
 | |
| VariablePropertyGetWithWildcardName (
 | |
|   IN CHAR16                         *VariableName,
 | |
|   IN EFI_GUID                       *VendorGuid,
 | |
|   IN BOOLEAN                        WildcardMatch
 | |
|   )
 | |
| {
 | |
|   UINTN     Index;
 | |
|   UINTN     NameLength;
 | |
| 
 | |
|   NameLength = StrLen (VariableName) - 4;
 | |
|   for (Index = 0; Index < sizeof (mVarCheckVariableWithWildcardName)/sizeof (mVarCheckVariableWithWildcardName[0]); Index++) {
 | |
|     if (CompareGuid (mVarCheckVariableWithWildcardName[Index].Guid, VendorGuid)){
 | |
|       if (WildcardMatch) {
 | |
|         if ((StrLen (VariableName) == StrLen (mVarCheckVariableWithWildcardName[Index].Name)) &&
 | |
|             (StrnCmp (VariableName, mVarCheckVariableWithWildcardName[Index].Name, NameLength) == 0) &&
 | |
|             VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
 | |
|             VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
 | |
|             VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
 | |
|             VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 3])) {
 | |
|           return &mVarCheckVariableWithWildcardName[Index].VariableProperty;
 | |
|         }
 | |
|       }
 | |
|       if (StrCmp (mVarCheckVariableWithWildcardName[Index].Name, VariableName) == 0) {
 | |
|         return  &mVarCheckVariableWithWildcardName[Index].VariableProperty;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Variable property get function.
 | |
| 
 | |
|   @param[in] Name           Pointer to the variable name.
 | |
|   @param[in] Guid           Pointer to the vendor GUID.
 | |
|   @param[in] WildcardMatch  Try wildcard match or not.
 | |
| 
 | |
|   @return Pointer to the property of variable specified by the Name and Guid.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_VARIABLE_PROPERTY *
 | |
| VariablePropertyGetFunction (
 | |
|   IN CHAR16                 *Name,
 | |
|   IN EFI_GUID               *Guid,
 | |
|   IN BOOLEAN                WildcardMatch
 | |
|   )
 | |
| {
 | |
|   UINTN                     Index;
 | |
|   VAR_CHECK_VARIABLE_ENTRY  *Entry;
 | |
|   CHAR16                    *VariableName;
 | |
| 
 | |
|   for (Index = 0; Index < mNumberOfVarCheckVariable; Index++) {
 | |
|     Entry = (VAR_CHECK_VARIABLE_ENTRY *) mVarCheckVariableTable[Index];
 | |
|     VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
 | |
|     if (CompareGuid (&Entry->Guid, Guid) && (StrCmp (VariableName, Name) == 0)) {
 | |
|       return &Entry->VariableProperty;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return VariablePropertyGetWithWildcardName (Name, Guid, WildcardMatch);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Var check add table entry.
 | |
| 
 | |
|   @param[in, out] Table         Pointer to table buffer.
 | |
|   @param[in, out] MaxNumber     Pointer to maximum number of entry in the table.
 | |
|   @param[in, out] CurrentNumber Pointer to current number of entry in the table.
 | |
|   @param[in]      Entry         Entry will be added to the table.
 | |
| 
 | |
|   @retval EFI_SUCCESS           Reallocate memory successfully.
 | |
|   @retval EFI_OUT_OF_RESOURCES  No enough memory to allocate.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| VarCheckAddTableEntry (
 | |
|   IN OUT UINTN      **Table,
 | |
|   IN OUT UINTN      *MaxNumber,
 | |
|   IN OUT UINTN      *CurrentNumber,
 | |
|   IN UINTN          Entry
 | |
|   )
 | |
| {
 | |
|   UINTN     *TempTable;
 | |
| 
 | |
|   //
 | |
|   // Check whether the table is enough to store new entry.
 | |
|   //
 | |
|   if (*CurrentNumber == *MaxNumber) {
 | |
|     //
 | |
|     // Reallocate memory for the table.
 | |
|     //
 | |
|     TempTable = ReallocateRuntimePool (
 | |
|                   *MaxNumber * sizeof (UINTN),
 | |
|                   (*MaxNumber + VAR_CHECK_TABLE_SIZE) * sizeof (UINTN),
 | |
|                   *Table
 | |
|                   );
 | |
| 
 | |
|     //
 | |
|     // No enough resource to allocate.
 | |
|     //
 | |
|     if (TempTable == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     *Table = TempTable;
 | |
|     //
 | |
|     // Increase max number.
 | |
|     //
 | |
|     *MaxNumber += VAR_CHECK_TABLE_SIZE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Add entry to the table.
 | |
|   //
 | |
|   (*Table)[*CurrentNumber] = Entry;
 | |
|   (*CurrentNumber)++;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Register END_OF_DXE callback.
 | |
|   The callback will be invoked by VarCheckLibInitializeAtEndOfDxe().
 | |
| 
 | |
|   @param[in] Callback           END_OF_DXE callback.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The callback was registered successfully.
 | |
|   @retval EFI_INVALID_PARAMETER Callback is NULL.
 | |
|   @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
 | |
|                                 already been signaled.
 | |
|   @retval EFI_OUT_OF_RESOURCES  There is not enough resource for the callback register request.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VarCheckLibRegisterEndOfDxeCallback (
 | |
|   IN VAR_CHECK_END_OF_DXE_CALLBACK  Callback
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   if (Callback == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (mVarCheckLibEndOfDxe) {
 | |
|     return EFI_ACCESS_DENIED;
 | |
|   }
 | |
| 
 | |
|   Status = VarCheckAddTableEntry (
 | |
|            (UINTN **) &mVarCheckLibEndOfDxeCallback,
 | |
|            &mVarCheckLibEndOfDxeCallbackMaxCount,
 | |
|            &mVarCheckLibEndOfDxeCallbackCount,
 | |
|            (UINTN) Callback
 | |
|            );
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "VarCheckLibRegisterEndOfDxeCallback - 0x%x %r\n", Callback, Status));
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Var check initialize at END_OF_DXE.
 | |
| 
 | |
|   This function needs to be called at END_OF_DXE.
 | |
|   Address pointers may be returned,
 | |
|   and caller needs to ConvertPointer() for the pointers.
 | |
| 
 | |
|   @param[in, out] AddressPointerCount   Output pointer to address pointer count.
 | |
| 
 | |
|   @return Address pointer buffer, NULL if input AddressPointerCount is NULL.
 | |
| 
 | |
| **/
 | |
| VOID ***
 | |
| EFIAPI
 | |
| VarCheckLibInitializeAtEndOfDxe (
 | |
|   IN OUT UINTN                  *AddressPointerCount OPTIONAL
 | |
|   )
 | |
| {
 | |
|   VOID                          *TempTable;
 | |
|   UINTN                         TotalCount;
 | |
|   UINTN                         Index;
 | |
| 
 | |
|   for (Index = 0; Index < mVarCheckLibEndOfDxeCallbackCount; Index++) {
 | |
|     //
 | |
|     // Invoke the callback registered by VarCheckLibRegisterEndOfDxeCallback().
 | |
|     //
 | |
|     mVarCheckLibEndOfDxeCallback[Index] ();
 | |
|   }
 | |
|   if (mVarCheckLibEndOfDxeCallback != NULL) {
 | |
|     //
 | |
|     // Free the callback buffer.
 | |
|     //
 | |
|     mVarCheckLibEndOfDxeCallbackCount = 0;
 | |
|     mVarCheckLibEndOfDxeCallbackMaxCount = 0;
 | |
|     FreePool ((VOID *) mVarCheckLibEndOfDxeCallback);
 | |
|     mVarCheckLibEndOfDxeCallback = NULL;
 | |
|   }
 | |
| 
 | |
|   mVarCheckLibEndOfDxe = TRUE;
 | |
| 
 | |
|   if (AddressPointerCount == NULL) {
 | |
|     if (mVarCheckLibAddressPointer != NULL) {
 | |
|       //
 | |
|       // Free the address pointer buffer.
 | |
|       //
 | |
|       mVarCheckLibAddressPointerCount = 0;
 | |
|       mVarCheckLibAddressPointerMaxCount = 0;
 | |
|       FreePool ((VOID *) mVarCheckLibAddressPointer);
 | |
|       mVarCheckLibAddressPointer = NULL;
 | |
|     }
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get the total count needed.
 | |
|   // Also cover VarCheckHandler and the entries, and VarCheckVariable and the entries.
 | |
|   //
 | |
|   TotalCount = mVarCheckLibAddressPointerCount + (mNumberOfVarCheckHandler + 1) + (mNumberOfVarCheckVariable + 1);
 | |
|   TempTable = ReallocateRuntimePool (
 | |
|                 mVarCheckLibAddressPointerMaxCount * sizeof (VOID **),
 | |
|                 TotalCount * sizeof (VOID **),
 | |
|                 (VOID *) mVarCheckLibAddressPointer
 | |
|                 );
 | |
| 
 | |
|   if (TempTable != NULL) {
 | |
|     mVarCheckLibAddressPointer = (VOID ***) TempTable;
 | |
| 
 | |
|     //
 | |
|     // Cover VarCheckHandler and the entries.
 | |
|     //
 | |
|     mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **) &mVarCheckHandlerTable;
 | |
|     for (Index = 0; Index < mNumberOfVarCheckHandler; Index++) {
 | |
|       mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **) &mVarCheckHandlerTable[Index];
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Cover VarCheckVariable and the entries.
 | |
|     //
 | |
|     mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **) &mVarCheckVariableTable;
 | |
|     for (Index = 0; Index < mNumberOfVarCheckVariable; Index++) {
 | |
|       mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **) &mVarCheckVariableTable[Index];
 | |
|     }
 | |
| 
 | |
|     ASSERT (mVarCheckLibAddressPointerCount == TotalCount);
 | |
|     mVarCheckLibAddressPointerMaxCount = mVarCheckLibAddressPointerCount;
 | |
|   }
 | |
| 
 | |
|   *AddressPointerCount = mVarCheckLibAddressPointerCount;
 | |
|   return mVarCheckLibAddressPointer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Register address pointer.
 | |
|   The AddressPointer may be returned by VarCheckLibInitializeAtEndOfDxe().
 | |
| 
 | |
|   @param[in] AddressPointer     Address pointer.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The address pointer was registered successfully.
 | |
|   @retval EFI_INVALID_PARAMETER AddressPointer is NULL.
 | |
|   @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
 | |
|                                 already been signaled.
 | |
|   @retval EFI_OUT_OF_RESOURCES  There is not enough resource for the address pointer register request.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VarCheckLibRegisterAddressPointer (
 | |
|   IN VOID                       **AddressPointer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   if (AddressPointer == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (mVarCheckLibEndOfDxe) {
 | |
|     return EFI_ACCESS_DENIED;
 | |
|   }
 | |
| 
 | |
|   Status = VarCheckAddTableEntry(
 | |
|            (UINTN **) &mVarCheckLibAddressPointer,
 | |
|            &mVarCheckLibAddressPointerMaxCount,
 | |
|            &mVarCheckLibAddressPointerCount,
 | |
|            (UINTN) AddressPointer
 | |
|            );
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "VarCheckLibRegisterAddressPointer - 0x%x %r\n", AddressPointer, Status));
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Register SetVariable check handler.
 | |
| 
 | |
|   @param[in] Handler            Pointer to check handler.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The SetVariable check handler was registered successfully.
 | |
|   @retval EFI_INVALID_PARAMETER Handler is NULL.
 | |
|   @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
 | |
|                                 already been signaled.
 | |
|   @retval EFI_OUT_OF_RESOURCES  There is not enough resource for the SetVariable check handler register request.
 | |
|   @retval EFI_UNSUPPORTED       This interface is not implemented.
 | |
|                                 For example, it is unsupported in VarCheck protocol if both VarCheck and SmmVarCheck protocols are present.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VarCheckLibRegisterSetVariableCheckHandler (
 | |
|   IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER   Handler
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   if (Handler == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (mVarCheckLibEndOfDxe) {
 | |
|     return EFI_ACCESS_DENIED;
 | |
|   }
 | |
| 
 | |
|   Status =  VarCheckAddTableEntry(
 | |
|              (UINTN **) &mVarCheckHandlerTable,
 | |
|              &mMaxNumberOfVarCheckHandler,
 | |
|              &mNumberOfVarCheckHandler,
 | |
|              (UINTN) Handler
 | |
|              );
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "VarCheckLibRegisterSetVariableCheckHandler - 0x%x %r\n", Handler, Status));
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Variable property set.
 | |
| 
 | |
|   @param[in] Name               Pointer to the variable name.
 | |
|   @param[in] Guid               Pointer to the vendor GUID.
 | |
|   @param[in] VariableProperty   Pointer to the input variable property.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was set successfully.
 | |
|   @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,
 | |
|                                 or the fields of VariableProperty are not valid.
 | |
|   @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
 | |
|                                 already been signaled.
 | |
|   @retval EFI_OUT_OF_RESOURCES  There is not enough resource for the variable property set request.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VarCheckLibVariablePropertySet (
 | |
|   IN CHAR16                         *Name,
 | |
|   IN EFI_GUID                       *Guid,
 | |
|   IN VAR_CHECK_VARIABLE_PROPERTY    *VariableProperty
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   VAR_CHECK_VARIABLE_ENTRY      *Entry;
 | |
|   CHAR16                        *VariableName;
 | |
|   VAR_CHECK_VARIABLE_PROPERTY   *Property;
 | |
| 
 | |
|   if (Name == NULL || Name[0] == 0 || Guid == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (VariableProperty == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (mVarCheckLibEndOfDxe) {
 | |
|     return EFI_ACCESS_DENIED;
 | |
|   }
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   // Get the pointer of property data for set.
 | |
|   //
 | |
|   Property = VariablePropertyGetFunction (Name, Guid, FALSE);
 | |
|   if (Property != NULL) {
 | |
|     CopyMem (Property, VariableProperty, sizeof (*VariableProperty));
 | |
|   } else {
 | |
|     Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));
 | |
|     if (Entry == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
 | |
|     StrCpyS (VariableName, StrSize (Name)/sizeof (CHAR16), Name);
 | |
|     CopyGuid (&Entry->Guid, Guid);
 | |
|     CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));
 | |
| 
 | |
|     Status = VarCheckAddTableEntry(
 | |
|                (UINTN **) &mVarCheckVariableTable,
 | |
|                &mMaxNumberOfVarCheckVariable,
 | |
|                &mNumberOfVarCheckVariable,
 | |
|                (UINTN) Entry
 | |
|                );
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreePool (Entry);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Variable property get.
 | |
| 
 | |
|   @param[in]  Name              Pointer to the variable name.
 | |
|   @param[in]  Guid              Pointer to the vendor GUID.
 | |
|   @param[out] VariableProperty  Pointer to the output variable property.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was got successfully.
 | |
|   @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.
 | |
|   @retval EFI_NOT_FOUND         The property of variable specified by the Name and Guid was not found.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VarCheckLibVariablePropertyGet (
 | |
|   IN CHAR16                         *Name,
 | |
|   IN EFI_GUID                       *Guid,
 | |
|   OUT VAR_CHECK_VARIABLE_PROPERTY   *VariableProperty
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_VARIABLE_PROPERTY   *Property;
 | |
| 
 | |
|   if (Name == NULL || Name[0] == 0 || Guid == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (VariableProperty == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Property = VariablePropertyGetFunction (Name, Guid, TRUE);
 | |
|   //
 | |
|   // Also check the property revision before using the property data.
 | |
|   // There is no property set to this variable(wildcard name)
 | |
|   // if the revision is not VAR_CHECK_VARIABLE_PROPERTY_REVISION.
 | |
|   //
 | |
|   if ((Property != NULL) && (Property->Revision == VAR_CHECK_VARIABLE_PROPERTY_REVISION)) {
 | |
|     CopyMem (VariableProperty, Property, sizeof (*VariableProperty));
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   SetVariable check.
 | |
| 
 | |
|   @param[in] VariableName       Name of Variable to set.
 | |
|   @param[in] VendorGuid         Variable vendor GUID.
 | |
|   @param[in] Attributes         Attribute value of the variable.
 | |
|   @param[in] DataSize           Size of Data to set.
 | |
|   @param[in] Data               Data pointer.
 | |
|   @param[in] RequestSource      Request source.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The SetVariable check result was success.
 | |
|   @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, GUID,
 | |
|                                 DataSize and Data value was supplied.
 | |
|   @retval EFI_WRITE_PROTECTED   The variable in question is read-only.
 | |
|   @retval Others                The other return status from check handler.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VarCheckLibSetVariableCheck (
 | |
|   IN CHAR16                     *VariableName,
 | |
|   IN EFI_GUID                   *VendorGuid,
 | |
|   IN UINT32                     Attributes,
 | |
|   IN UINTN                      DataSize,
 | |
|   IN VOID                       *Data,
 | |
|   IN VAR_CHECK_REQUEST_SOURCE   RequestSource
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   UINTN                         Index;
 | |
|   VAR_CHECK_VARIABLE_PROPERTY   *Property;
 | |
| 
 | |
|   if (!mVarCheckLibEndOfDxe) {
 | |
|     //
 | |
|     // Only do check after End Of Dxe.
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Property = VariablePropertyGetFunction (VariableName, VendorGuid, TRUE);
 | |
|   //
 | |
|   // Also check the property revision before using the property data.
 | |
|   // There is no property set to this variable(wildcard name)
 | |
|   // if the revision is not VAR_CHECK_VARIABLE_PROPERTY_REVISION.
 | |
|   //
 | |
|   if ((Property != NULL) && (Property->Revision == VAR_CHECK_VARIABLE_PROPERTY_REVISION)) {
 | |
|     if ((RequestSource != VarCheckFromTrusted) && ((Property->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0)) {
 | |
|       DEBUG ((EFI_D_INFO, "Variable Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));
 | |
|       return EFI_WRITE_PROTECTED;
 | |
|     }
 | |
|     if (!((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0))) {
 | |
|       //
 | |
|       // Not to delete variable.
 | |
|       //
 | |
|       if ((Property->Attributes != 0) && ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Property->Attributes)) {
 | |
|         DEBUG ((EFI_D_INFO, "Variable Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|       if (DataSize != 0) {
 | |
|         if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {
 | |
|           DEBUG ((EFI_D_INFO, "Variable Check DataSize fail(0x%x not in 0x%x - 0x%x) %r - %g:%s\n", DataSize, Property->MinSize, Property->MaxSize, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < mNumberOfVarCheckHandler; Index++) {
 | |
|     Status = mVarCheckHandlerTable[Index] (
 | |
|                VariableName,
 | |
|                VendorGuid,
 | |
|                Attributes,
 | |
|                DataSize,
 | |
|                Data
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((EFI_D_INFO, "Variable Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
|   return EFI_SUCCESS;
 | |
| }
 |