git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2313 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			489 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			489 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2006, 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.             
 | |
| 
 | |
| Module Name:
 | |
|   IfrVariable.c
 | |
| 
 | |
| Abstract:
 | |
|   Variable/Map manipulations routines
 | |
| 
 | |
| --*/
 | |
| 
 | |
| VOID
 | |
| EfiLibHiiVariablePackGetMap (
 | |
|   IN    EFI_HII_VARIABLE_PACK       *Pack,  
 | |
|   OUT   CHAR16                      **Name,  OPTIONAL
 | |
|   OUT   EFI_GUID                    **Guid,  OPTIONAL
 | |
|   OUT   UINT16                      *Id,     OPTIONAL
 | |
|   OUT   VOID                        **Var,   OPTIONAL
 | |
|   OUT   UINTN                       *Size    OPTIONAL
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Extracts a variable form a Pack.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Pack - List of variables
 | |
|   Name - Name of the variable/map
 | |
|   Guid - GUID of the variable/map
 | |
|   Var  - Pointer to the variable/map
 | |
|   Size - Size of the variable/map in bytes
 | |
| 
 | |
| Returns: 
 | |
| 
 | |
|   VOID
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   if (NULL != Name) {
 | |
|     *Name = (VOID *) (Pack + 1);
 | |
|   }
 | |
|     
 | |
|   if (NULL != Guid) { 
 | |
|     *Guid = (EFI_GUID *)(UINTN)&Pack->VariableGuid;
 | |
|   }
 | |
|     
 | |
|     
 | |
|   if (NULL != Id) {
 | |
|     *Id   = Pack->VariableId;
 | |
|   }
 | |
|     
 | |
|   if (NULL != Var) {
 | |
|     *Var  = (VOID *) ((CHAR8 *) (Pack + 1) + Pack->VariableNameLength);
 | |
|   }
 | |
|     
 | |
|   if (NULL != Size) {
 | |
|     *Size = Pack->Header.Length - sizeof (*Pack) - Pack->VariableNameLength;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| UINTN
 | |
| EfiLibHiiVariablePackListGetMapCnt (
 | |
|   IN    EFI_HII_VARIABLE_PACK_LIST   *List
 | |
|   )
 | |
|   
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Finds a count of the variables/maps in the List.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   List - List of variables
 | |
| 
 | |
| Returns: 
 | |
| 
 | |
|   UINTN - The number of map count.
 | |
| 
 | |
| --*/
 | |
| 
 | |
| {
 | |
|   UINTN   Cnt = 0;
 | |
|   while (NULL != List) {
 | |
|     Cnt++;
 | |
|     List = List->NextVariablePack;
 | |
|   }
 | |
|   return Cnt;
 | |
| }
 | |
| 
 | |
| 
 | |
| VOID
 | |
| EfiLibHiiVariablePackListForEachVar (
 | |
|   IN    EFI_HII_VARIABLE_PACK_LIST               *List,
 | |
|   IN    EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK  *Callback
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Will iterate all variable/maps as appearing 
 | |
|   in List and for each, it will call the Callback.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   List     - List of variables
 | |
|   Callback - Routine to be called for each iterated variable.
 | |
| 
 | |
| Returns: 
 | |
| 
 | |
|   VOID
 | |
|   
 | |
| --*/
 | |
| 
 | |
| {
 | |
|   CHAR16    *MapName;
 | |
|   EFI_GUID  *MapGuid;
 | |
|   UINT16    MapId;
 | |
|   VOID      *Map;
 | |
|   UINTN     MapSize;
 | |
| 
 | |
|   while (NULL != List) {
 | |
|     EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
 | |
|     //
 | |
|     // call the callback
 | |
|     //
 | |
|     Callback (MapName, MapGuid, MapId, Map, MapSize); 
 | |
|     List = List->NextVariablePack;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| EFI_STATUS
 | |
| EfiLibHiiVariablePackListGetMapByIdx (
 | |
|   IN    UINTN                       Idx,  
 | |
|   IN    EFI_HII_VARIABLE_PACK_LIST  *List,  
 | |
|   OUT   CHAR16                      **Name,  OPTIONAL
 | |
|   OUT   EFI_GUID                    **Guid,  OPTIONAL
 | |
|   OUT   UINT16                      *Id,     OPTIONAL
 | |
|   OUT   VOID                        **Var,
 | |
|   OUT   UINTN                       *Size
 | |
|   )
 | |
| 
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Finds a variable form List given 
 | |
|   the order number as appears in the List.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Idx  - The index of the variable/map to retrieve
 | |
|   List - List of variables
 | |
|   Name - Name of the variable/map
 | |
|   Guid - GUID of the variable/map
 | |
|   Var  - Pointer to the variable/map
 | |
|   Size - Size of the variable/map in bytes
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS   - Variable is found, OUT parameters are valid
 | |
|   EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   CHAR16     *MapName;
 | |
|   EFI_GUID   *MapGuid;
 | |
|   UINT16     MapId;
 | |
|   VOID       *Map;
 | |
|   UINTN      MapSize;
 | |
| 
 | |
|   while (NULL != List) {
 | |
|     EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
 | |
|     if (0 == Idx--) {
 | |
|       *Var  = Map;
 | |
|       *Size = MapSize;
 | |
| 
 | |
|       if (NULL != Name) {
 | |
|         *Name = MapName;
 | |
|       }
 | |
| 
 | |
|       if (NULL != Guid) {
 | |
|         *Guid = MapGuid;
 | |
|       }
 | |
|         
 | |
|       if (NULL != Id) {
 | |
|         *Id   = MapId;
 | |
|       }
 | |
|         
 | |
|       return EFI_SUCCESS; // Map found
 | |
|     }
 | |
|     List = List->NextVariablePack;
 | |
|   }
 | |
|   //
 | |
|   // If here, the map is not found
 | |
|   //
 | |
|   return EFI_NOT_FOUND; 
 | |
| }
 | |
| 
 | |
| 
 | |
| EFI_STATUS
 | |
| EfiLibHiiVariablePackListGetMapById (
 | |
|   IN    UINT16                        Id,  
 | |
|   IN    EFI_HII_VARIABLE_PACK_LIST    *List,
 | |
|   OUT   CHAR16                        **Name,  OPTIONAL
 | |
|   OUT   EFI_GUID                      **Guid,  OPTIONAL
 | |
|   OUT   VOID                          **Var,
 | |
|   OUT   UINTN                         *Size
 | |
|   )
 | |
|   
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Finds a variable form List given the 
 | |
|   order number as appears in the List.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Id   - The ID of the variable/map to retrieve
 | |
|   List - List of variables
 | |
|   Name - Name of the variable/map
 | |
|   Guid - GUID of the variable/map
 | |
|   Var  - Pointer to the variable/map
 | |
|   Size - Size of the variable/map in bytes
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS   - Variable is found, OUT parameters are valid
 | |
|   EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid
 | |
| 
 | |
| --*/
 | |
| 
 | |
| { 
 | |
|   CHAR16    *MapName;
 | |
|   EFI_GUID  *MapGuid;
 | |
|   UINT16    MapId;
 | |
|   VOID      *Map;
 | |
|   UINTN     MapSize;
 | |
| 
 | |
|   while (NULL != List) {
 | |
|     EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
 | |
|     if (MapId == Id) {
 | |
|       *Var  = Map;
 | |
|       *Size = MapSize;
 | |
|       if (NULL != Name) {
 | |
|          *Name = MapName;
 | |
|       }
 | |
|       if (NULL != Guid) {
 | |
|         *Guid = MapGuid;
 | |
|       }
 | |
|       //
 | |
|       // Map found
 | |
|       //
 | |
|       return EFI_SUCCESS; 
 | |
|     }
 | |
|     List = List->NextVariablePack;
 | |
|   }
 | |
|   //
 | |
|   // If here, the map is not found
 | |
|   //
 | |
|   return EFI_NOT_FOUND; 
 | |
| }
 | |
| 
 | |
| 
 | |
| EFI_STATUS
 | |
| EfiLibHiiVariablePackListGetMap (
 | |
|   IN    EFI_HII_VARIABLE_PACK_LIST   *List,
 | |
|   IN    CHAR16                       *Name,
 | |
|   IN    EFI_GUID                     *Guid,
 | |
|   OUT   UINT16                       *Id,
 | |
|   OUT   VOID                         **Var, 
 | |
|   OUT   UINTN                        *Size
 | |
|   )
 | |
| 
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Finds a variable form EFI_HII_VARIABLE_PACK_LIST given name and GUID.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   List - List of variables
 | |
|   Name - Name of the variable/map to be found
 | |
|   Guid - GUID of the variable/map to be found
 | |
|   Var  - Pointer to the variable/map found
 | |
|   Size - Size of the variable/map in bytes found
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS   - variable is found, OUT parameters are valid
 | |
|   EFI_NOT_FOUND - variable is not found, OUT parameters are not valid
 | |
| 
 | |
| --*/
 | |
| 
 | |
| { 
 | |
|   VOID      *Map;
 | |
|   UINTN     MapSize;
 | |
|   UINT16    MapId;
 | |
|   CHAR16    *MapName;
 | |
|   EFI_GUID  *MapGuid;
 | |
| 
 | |
|   while (NULL != List) {
 | |
|     EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
 | |
|     if ((0 == StrCmp (Name, MapName)) && CompareGuid (Guid, MapGuid)) {
 | |
|       *Id   = MapId;
 | |
|       *Var  = Map;
 | |
|       *Size = MapSize;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|     List = List->NextVariablePack;
 | |
|   }
 | |
|   //
 | |
|   // If here, the map is not found
 | |
|   //
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EfiLibHiiVariableRetrieveFromNv (
 | |
|   IN  CHAR16                 *Name,
 | |
|   IN  EFI_GUID               *Guid,
 | |
|   IN  UINTN                   Size,
 | |
|   OUT VOID                  **Var
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Finds out if a variable of specific Name/Guid/Size exists in NV. 
 | |
|   If it does, it will retrieve it into the Var. 
 | |
| 
 | |
| Arguments:
 | |
|   Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
 | |
|   Var              - Variable will be retrieved into buffer pointed by this pointer.
 | |
|                      If pointing to NULL, the buffer will be allocated. Caller is responsible for releasing the buffer.
 | |
| Returns:
 | |
|   EFI_SUCCESS    - The variable of exact Name/Guid/Size parameters was retrieved and written to Var.
 | |
|   EFI_NOT_FOUND  - The variable of this Name/Guid was not found in the NV.
 | |
|   EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   UINTN                       SizeNv;
 | |
| 
 | |
|   //
 | |
|   // Test for existence of the variable.
 | |
|   //
 | |
|   SizeNv = 0;
 | |
|   Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, NULL);
 | |
|   if (EFI_BUFFER_TOO_SMALL != Status) {
 | |
|     ASSERT (EFI_SUCCESS != Status);
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
|   if (SizeNv != Size) {
 | |
|     //
 | |
|     // The variable is considered corrupt, as it has different size from expected.
 | |
|     //
 | |
|     return EFI_LOAD_ERROR; 
 | |
|   }
 | |
| 
 | |
|   if (NULL == *Var) {
 | |
|     *Var = AllocatePool (Size);
 | |
|     ASSERT (NULL != *Var);
 | |
|   }
 | |
|   SizeNv = Size;
 | |
|   //
 | |
|   // Final read into the Var
 | |
|   //
 | |
|   Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, *Var); 
 | |
|   //
 | |
|   // No tolerance for random failures. Such behavior is undetermined and not validated.
 | |
|   //
 | |
|   ASSERT_EFI_ERROR (Status); 
 | |
|   ASSERT (SizeNv == Size);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| EFI_STATUS
 | |
| EfiLibHiiVariableOverrideIfSuffix (
 | |
|   IN  CHAR16                 *Suffix,
 | |
|   IN  CHAR16                 *Name,
 | |
|   IN  EFI_GUID               *Guid,
 | |
|   IN  UINTN                   Size,
 | |
|   OUT VOID                   *Var
 | |
|   )  
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Overrrides the variable with NV data if found.
 | |
|   But it only does it if the Name ends with specified Suffix.
 | |
|   For example, if Suffix="MyOverride" and the Name="XyzSetupMyOverride",
 | |
|   the Suffix matches the end of Name, so the variable will be loaded from NV
 | |
|   provided the variable exists and the GUID and Size matches.
 | |
| 
 | |
| Arguments:
 | |
|   Suffix           - Suffix the Name should end with.
 | |
|   Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
 | |
|   Var              - Variable will be retrieved into this buffer.
 | |
|                      Caller is responsible for providing storage of exactly Size size in bytes.
 | |
| Returns:
 | |
|   EFI_SUCCESS           - The variable was overriden with NV variable of same Name/Guid/Size.
 | |
|   EFI_INVALID_PARAMETER - The name of the variable does not end with <Suffix>.
 | |
|   EFI_NOT_FOUND         - The variable of this Name/Guid was not found in the NV.
 | |
|   EFI_LOAD_ERROR        - The variable in the NV was of different size, or NV API returned error.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN         StrLength;
 | |
|   UINTN         StrLenSuffix;
 | |
| 
 | |
|   StrLength       = StrLen (Name);
 | |
|   StrLenSuffix    = StrLen (Suffix);
 | |
|   if ((StrLength <= StrLenSuffix) || (0 != StrCmp (Suffix, &Name[StrLength - StrLenSuffix]))) {
 | |
|     //
 | |
|     // Not ending with <Suffix>.
 | |
|     //
 | |
|     return EFI_INVALID_PARAMETER; 
 | |
|   }
 | |
|   return EfiLibHiiVariableRetrieveFromNv (Name, Guid, Size, &Var);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EfiLibHiiVariableOverrideBySuffix (
 | |
|   IN  CHAR16                 *Suffix,
 | |
|   IN  CHAR16                 *Name,
 | |
|   IN  EFI_GUID               *Guid,
 | |
|   IN  UINTN                   Size,
 | |
|   OUT VOID                   *Var
 | |
|   ) 
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Overrrides the variable with NV data if found.
 | |
|   But it only does it if the NV contains the same variable with Name is appended with Suffix.  
 | |
|   For example, if Suffix="MyOverride" and the Name="XyzSetup",
 | |
|   the Suffix will be appended to the end of Name, and the variable with Name="XyzSetupMyOverride"
 | |
|   will be loaded from NV provided the variable exists and the GUID and Size matches.
 | |
| 
 | |
| Arguments:
 | |
|   Suffix           - Suffix the variable will be appended with.
 | |
|   Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
 | |
|   Var              - Variable will be retrieved into this buffer.
 | |
|                      Caller is responsible for providing storage of exactly Size size in bytes.
 | |
| 
 | |
| Returns:
 | |
|   EFI_SUCCESS    - The variable was overriden with NV variable of same Name/Guid/Size.
 | |
|   EFI_NOT_FOUND  - The variable of this Name/Guid was not found in the NV.
 | |
|   EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
|   CHAR16       *NameSuffixed;
 | |
|   UINTN         NameLength;
 | |
|   UINTN         SuffixLength;
 | |
| 
 | |
|   //
 | |
|   // enough to concatenate both strings.
 | |
|   //
 | |
|   NameLength   = StrLen (Name);
 | |
|   SuffixLength = StrLen (Suffix);
 | |
|   NameSuffixed = AllocateZeroPool ((NameLength + SuffixLength + 1) * sizeof (CHAR16)); 
 | |
|   
 | |
|   StrCpy (NameSuffixed, Name);
 | |
|   StrCat (NameSuffixed, Suffix);
 | |
|   
 | |
|   Status = EfiLibHiiVariableRetrieveFromNv (NameSuffixed, Guid, Size, &Var);
 | |
|   gBS->FreePool (NameSuffixed);
 | |
|   
 | |
|   return Status;
 | |
| }
 | |
| 
 |