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