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