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