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
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)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
EfiLibHiiVariablePackListGetMapCnt(IN EFI_HII_VARIABLE_PACK_LIST * List)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
EfiLibHiiVariablePackListForEachVar(IN EFI_HII_VARIABLE_PACK_LIST * List,IN EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK * Callback)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
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)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
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)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
EfiLibHiiVariablePackListGetMap(IN EFI_HII_VARIABLE_PACK_LIST * List,IN CHAR16 * Name,IN EFI_GUID * Guid,OUT UINT16 * Id,OUT VOID ** Var,OUT UINTN * Size)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
EfiLibHiiVariableRetrieveFromNv(IN CHAR16 * Name,IN EFI_GUID * Guid,IN UINTN Size,OUT VOID ** Var)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
EfiLibHiiVariableOverrideIfSuffix(IN CHAR16 * Suffix,IN CHAR16 * Name,IN EFI_GUID * Guid,IN UINTN Size,OUT VOID * Var)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
EfiLibHiiVariableOverrideBySuffix(IN CHAR16 * Suffix,IN CHAR16 * Name,IN EFI_GUID * Guid,IN UINTN Size,OUT VOID * Var)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