Home | History | Annotate | Download | only in EfiIfrSupportLib
      1 /*++
      2 
      3 Copyright (c) 2005, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13   IfrVariable.c
     14 
     15 Abstract:
     16   Variable/Map manipulations routines
     17 
     18 --*/
     19 
     20 #include "IfrLibrary.h"
     21 
     22 VOID
     23 EfiLibHiiVariablePackGetMap (
     24   IN    EFI_HII_VARIABLE_PACK       *Pack,
     25   OUT   CHAR16                      **Name,  OPTIONAL
     26   OUT   EFI_GUID                    **Guid,  OPTIONAL
     27   OUT   UINT16                      *Id,     OPTIONAL
     28   OUT   VOID                        **Var,   OPTIONAL
     29   OUT   UINTN                       *Size    OPTIONAL
     30   )
     31 /*++
     32 
     33 Routine Description:
     34 
     35   Extracts a variable form a Pack.
     36 
     37 Arguments:
     38 
     39   Pack - List of variables
     40   Name - Name of the variable/map
     41   Guid - GUID of the variable/map
     42   Var  - Pointer to the variable/map
     43   Size - Size of the variable/map in bytes
     44 
     45 Returns:
     46 
     47   VOID
     48 
     49 --*/
     50 {
     51   if (NULL != Name) {
     52     *Name = (VOID *) (Pack + 1);
     53   }
     54 
     55   if (NULL != Guid) {
     56     *Guid = &Pack->VariableGuid;
     57   }
     58 
     59 
     60   if (NULL != Id) {
     61     *Id   = Pack->VariableId;
     62   }
     63 
     64   if (NULL != Var) {
     65     *Var  = (VOID *) ((CHAR8 *) (Pack + 1) + Pack->VariableNameLength);
     66   }
     67 
     68   if (NULL != Size) {
     69     *Size = Pack->Header.Length - sizeof (*Pack) - Pack->VariableNameLength;
     70   }
     71 }
     72 
     73 
     74 UINTN
     75 EfiLibHiiVariablePackListGetMapCnt (
     76   IN    EFI_HII_VARIABLE_PACK_LIST   *List
     77   )
     78 
     79 /*++
     80 
     81 Routine Description:
     82 
     83   Finds a count of the variables/maps in the List.
     84 
     85 Arguments:
     86 
     87   List - List of variables
     88 
     89 Returns:
     90 
     91   UINTN - The number of map count.
     92 
     93 --*/
     94 
     95 {
     96   UINTN   Cnt = 0;
     97   while (NULL != List) {
     98     Cnt++;
     99     List = List->NextVariablePack;
    100   }
    101   return Cnt;
    102 }
    103 
    104 
    105 VOID
    106 EfiLibHiiVariablePackListForEachVar (
    107   IN    EFI_HII_VARIABLE_PACK_LIST               *List,
    108   IN    EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK  *Callback
    109   )
    110 /*++
    111 
    112 Routine Description:
    113 
    114   Will iterate all variable/maps as appearing
    115   in List and for each, it will call the Callback.
    116 
    117 Arguments:
    118 
    119   List     - List of variables
    120   Callback - Routine to be called for each iterated variable.
    121 
    122 Returns:
    123 
    124   VOID
    125 
    126 --*/
    127 
    128 {
    129   CHAR16    *MapName;
    130   EFI_GUID  *MapGuid;
    131   UINT16    MapId;
    132   VOID      *Map;
    133   UINTN     MapSize;
    134 
    135   while (NULL != List) {
    136     EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
    137     //
    138     // call the callback
    139     //
    140     Callback (MapName, MapGuid, MapId, Map, MapSize);
    141     List = List->NextVariablePack;
    142   }
    143 }
    144 
    145 
    146 EFI_STATUS
    147 EfiLibHiiVariablePackListGetMapByIdx (
    148   IN    UINTN                       Idx,
    149   IN    EFI_HII_VARIABLE_PACK_LIST  *List,
    150   OUT   CHAR16                      **Name,  OPTIONAL
    151   OUT   EFI_GUID                    **Guid,  OPTIONAL
    152   OUT   UINT16                      *Id,     OPTIONAL
    153   OUT   VOID                        **Var,
    154   OUT   UINTN                       *Size
    155   )
    156 
    157 /*++
    158 
    159 Routine Description:
    160 
    161   Finds a variable form List given
    162   the order number as appears in the List.
    163 
    164 Arguments:
    165 
    166   Idx  - The index of the variable/map to retrieve
    167   List - List of variables
    168   Name - Name of the variable/map
    169   Guid - GUID of the variable/map
    170   Var  - Pointer to the variable/map
    171   Size - Size of the variable/map in bytes
    172 
    173 Returns:
    174 
    175   EFI_SUCCESS   - Variable is found, OUT parameters are valid
    176   EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid
    177 
    178 --*/
    179 {
    180   CHAR16     *MapName;
    181   EFI_GUID   *MapGuid;
    182   UINT16     MapId;
    183   VOID       *Map;
    184   UINTN      MapSize;
    185 
    186   while (NULL != List) {
    187     EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
    188     if (0 == Idx--) {
    189       *Var  = Map;
    190       *Size = MapSize;
    191 
    192       if (NULL != Name) {
    193         *Name = MapName;
    194       }
    195 
    196       if (NULL != Guid) {
    197         *Guid = MapGuid;
    198       }
    199 
    200       if (NULL != Id) {
    201         *Id   = MapId;
    202       }
    203 
    204       return EFI_SUCCESS; // Map found
    205     }
    206     List = List->NextVariablePack;
    207   }
    208   //
    209   // If here, the map is not found
    210   //
    211   return EFI_NOT_FOUND;
    212 }
    213 
    214 
    215 EFI_STATUS
    216 EfiLibHiiVariablePackListGetMapById (
    217   IN    UINT16                        Id,
    218   IN    EFI_HII_VARIABLE_PACK_LIST    *List,
    219   OUT   CHAR16                        **Name,  OPTIONAL
    220   OUT   EFI_GUID                      **Guid,  OPTIONAL
    221   OUT   VOID                          **Var,
    222   OUT   UINTN                         *Size
    223   )
    224 
    225 /*++
    226 
    227 Routine Description:
    228 
    229   Finds a variable form List given the
    230   order number as appears in the List.
    231 
    232 Arguments:
    233 
    234   Id   - The ID of the variable/map to retrieve
    235   List - List of variables
    236   Name - Name of the variable/map
    237   Guid - GUID of the variable/map
    238   Var  - Pointer to the variable/map
    239   Size - Size of the variable/map in bytes
    240 
    241 Returns:
    242 
    243   EFI_SUCCESS   - Variable is found, OUT parameters are valid
    244   EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid
    245 
    246 --*/
    247 
    248 {
    249   CHAR16    *MapName;
    250   EFI_GUID  *MapGuid;
    251   UINT16    MapId;
    252   VOID      *Map;
    253   UINTN     MapSize;
    254 
    255   while (NULL != List) {
    256     EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
    257     if (MapId == Id) {
    258       *Var  = Map;
    259       *Size = MapSize;
    260       if (NULL != Name) {
    261          *Name = MapName;
    262       }
    263       if (NULL != Guid) {
    264         *Guid = MapGuid;
    265       }
    266       //
    267       // Map found
    268       //
    269       return EFI_SUCCESS;
    270     }
    271     List = List->NextVariablePack;
    272   }
    273   //
    274   // If here, the map is not found
    275   //
    276   return EFI_NOT_FOUND;
    277 }
    278 
    279 
    280 EFI_STATUS
    281 EfiLibHiiVariablePackListGetMap (
    282   IN    EFI_HII_VARIABLE_PACK_LIST   *List,
    283   IN    CHAR16                       *Name,
    284   IN    EFI_GUID                     *Guid,
    285   OUT   UINT16                       *Id,
    286   OUT   VOID                         **Var,
    287   OUT   UINTN                        *Size
    288   )
    289 
    290 /*++
    291 
    292 Routine Description:
    293 
    294   Finds a variable form EFI_HII_VARIABLE_PACK_LIST given name and GUID.
    295 
    296 Arguments:
    297 
    298   List - List of variables
    299   Name - Name of the variable/map to be found
    300   Guid - GUID of the variable/map to be found
    301   Var  - Pointer to the variable/map found
    302   Size - Size of the variable/map in bytes found
    303 
    304 Returns:
    305 
    306   EFI_SUCCESS   - variable is found, OUT parameters are valid
    307   EFI_NOT_FOUND - variable is not found, OUT parameters are not valid
    308 
    309 --*/
    310 
    311 {
    312   VOID      *Map;
    313   UINTN     MapSize;
    314   UINT16    MapId;
    315   CHAR16    *MapName;
    316   EFI_GUID  *MapGuid;
    317 
    318   while (NULL != List) {
    319     EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
    320     if ((0 == EfiStrCmp (Name, MapName)) && EfiCompareGuid (Guid, MapGuid)) {
    321       *Id   = MapId;
    322       *Var  = Map;
    323       *Size = MapSize;
    324       return EFI_SUCCESS;
    325     }
    326     List = List->NextVariablePack;
    327   }
    328   //
    329   // If here, the map is not found
    330   //
    331   return EFI_NOT_FOUND;
    332 }
    333 
    334 EFI_STATUS
    335 EfiLibHiiVariableRetrieveFromNv (
    336   IN  CHAR16                 *Name,
    337   IN  EFI_GUID               *Guid,
    338   IN  UINTN                   Size,
    339   OUT VOID                  **Var
    340   )
    341 /*++
    342 
    343 Routine Description:
    344   Finds out if a variable of specific Name/Guid/Size exists in NV.
    345   If it does, it will retrieve it into the Var.
    346 
    347 Arguments:
    348   Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
    349   Var              - Variable will be retrieved into buffer pointed by this pointer.
    350                      If pointing to NULL, the buffer will be allocated. Caller is responsible for releasing the buffer.
    351 Returns:
    352   EFI_SUCCESS    - The variable of exact Name/Guid/Size parameters was retrieved and written to Var.
    353   EFI_NOT_FOUND  - The variable of this Name/Guid was not found in the NV.
    354   EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.
    355 
    356 --*/
    357 {
    358   EFI_STATUS                  Status;
    359   UINTN                       SizeNv;
    360 
    361   //
    362   // Test for existence of the variable.
    363   //
    364   SizeNv = 0;
    365   Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, NULL);
    366   if (EFI_BUFFER_TOO_SMALL != Status) {
    367     ASSERT (EFI_SUCCESS != Status);
    368     return EFI_NOT_FOUND;
    369   }
    370   if (SizeNv != Size) {
    371     //
    372     // The variable is considered corrupt, as it has different size from expected.
    373     //
    374     return EFI_LOAD_ERROR;
    375   }
    376 
    377   if (NULL == *Var) {
    378     *Var = EfiLibAllocatePool (Size);
    379     ASSERT (NULL != *Var);
    380   }
    381   SizeNv = Size;
    382   //
    383   // Final read into the Var
    384   //
    385   Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, *Var);
    386   //
    387   // No tolerance for random failures. Such behavior is undetermined and not validated.
    388   //
    389   ASSERT_EFI_ERROR (Status);
    390   ASSERT (SizeNv == Size);
    391   return EFI_SUCCESS;
    392 }
    393 
    394 
    395 
    396 EFI_STATUS
    397 EfiLibHiiVariableOverrideIfSuffix (
    398   IN  CHAR16                 *Suffix,
    399   IN  CHAR16                 *Name,
    400   IN  EFI_GUID               *Guid,
    401   IN  UINTN                   Size,
    402   OUT VOID                   *Var
    403   )
    404 /*++
    405 
    406 Routine Description:
    407   Overrrides the variable with NV data if found.
    408   But it only does it if the Name ends with specified Suffix.
    409   For example, if Suffix="MyOverride" and the Name="XyzSetupMyOverride",
    410   the Suffix matches the end of Name, so the variable will be loaded from NV
    411   provided the variable exists and the GUID and Size matches.
    412 
    413 Arguments:
    414   Suffix           - Suffix the Name should end with.
    415   Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
    416   Var              - Variable will be retrieved into this buffer.
    417                      Caller is responsible for providing storage of exactly Size size in bytes.
    418 Returns:
    419   EFI_SUCCESS           - The variable was overriden with NV variable of same Name/Guid/Size.
    420   EFI_INVALID_PARAMETER - The name of the variable does not end with <Suffix>.
    421   EFI_NOT_FOUND         - The variable of this Name/Guid was not found in the NV.
    422   EFI_LOAD_ERROR        - The variable in the NV was of different size, or NV API returned error.
    423 
    424 --*/
    425 {
    426   UINTN         StrLen;
    427   UINTN         StrLenSuffix;
    428 
    429   StrLen       = EfiStrLen (Name);
    430   StrLenSuffix = EfiStrLen (Suffix);
    431   if ((StrLen <= StrLenSuffix) || (0 != EfiStrCmp (Suffix, &Name[StrLen - StrLenSuffix]))) {
    432     //
    433     // Not ending with <Suffix>.
    434     //
    435     return EFI_INVALID_PARAMETER;
    436   }
    437   return EfiLibHiiVariableRetrieveFromNv (Name, Guid, Size, &Var);
    438 }
    439 
    440 
    441 
    442 EFI_STATUS
    443 EfiLibHiiVariableOverrideBySuffix (
    444   IN  CHAR16                 *Suffix,
    445   IN  CHAR16                 *Name,
    446   IN  EFI_GUID               *Guid,
    447   IN  UINTN                   Size,
    448   OUT VOID                   *Var
    449   )
    450 /*++
    451 
    452 Routine Description:
    453   Overrrides the variable with NV data if found.
    454   But it only does it if the NV contains the same variable with Name is appended with Suffix.
    455   For example, if Suffix="MyOverride" and the Name="XyzSetup",
    456   the Suffix will be appended to the end of Name, and the variable with Name="XyzSetupMyOverride"
    457   will be loaded from NV provided the variable exists and the GUID and Size matches.
    458 
    459 Arguments:
    460   Suffix           - Suffix the variable will be appended with.
    461   Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
    462   Var              - Variable will be retrieved into this buffer.
    463                      Caller is responsible for providing storage of exactly Size size in bytes.
    464 
    465 Returns:
    466   EFI_SUCCESS    - The variable was overriden with NV variable of same Name/Guid/Size.
    467   EFI_NOT_FOUND  - The variable of this Name/Guid was not found in the NV.
    468   EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.
    469 
    470 --*/
    471 {
    472   EFI_STATUS    Status;
    473   CHAR16       *NameSuffixed;
    474   UINTN         NameLength;
    475   UINTN         SuffixLength;
    476 
    477   //
    478   // enough to concatenate both strings.
    479   //
    480   NameLength   = EfiStrLen (Name);
    481   SuffixLength = EfiStrLen (Suffix);
    482   NameSuffixed = EfiLibAllocateZeroPool ((NameLength + SuffixLength + 1) * sizeof (CHAR16));
    483 
    484   EfiStrCpy (NameSuffixed, Name);
    485   EfiStrCat (NameSuffixed, Suffix);
    486 
    487   Status = EfiLibHiiVariableRetrieveFromNv (NameSuffixed, Guid, Size, &Var);
    488   gBS->FreePool (NameSuffixed);
    489 
    490   return Status;
    491 }
    492 
    493