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