1. Removed #ifdef SNP_DEBUG and used debug lib to output information
[mirror_edk2.git] / EdkModulePkg / Universal / Variable / Pei / Variable.c
CommitLineData
878ddf1f 1/*++\r
2\r
bb60dd97 3Copyright (c) 2006 - 2007 Intel Corporation. <BR>\r
878ddf1f 4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
878ddf1f 11Module Name:\r
12\r
13 Variable.c\r
14\r
15Abstract:\r
16\r
17 Framework PEIM to provide the Variable functionality\r
18\r
19--*/\r
20\r
878ddf1f 21#include <Variable.h>\r
878ddf1f 22\r
23//\r
24// Module globals\r
25//\r
26static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi = {\r
27 PeiGetVariable,\r
28 PeiGetNextVariableName\r
29};\r
30\r
31static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {\r
32 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
33 &gEfiPeiReadOnlyVariablePpiGuid,\r
34 &mVariablePpi\r
35};\r
36\r
37EFI_GUID gEfiVariableIndexTableGuid = EFI_VARIABLE_INDEX_TABLE_GUID;\r
38\r
39EFI_STATUS\r
40EFIAPI\r
41PeimInitializeVariableServices (\r
42 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
43 IN EFI_PEI_SERVICES **PeiServices\r
44 )\r
45/*++\r
46\r
47Routine Description:\r
48\r
49 Provide the functionality of the variable services.\r
50\r
51Arguments:\r
3aaddf92 52\r
878ddf1f 53 FfsHeadher - The FFS file header\r
54 PeiServices - General purpose services available to every PEIM.\r
55\r
56Returns:\r
57\r
58 Status - EFI_SUCCESS if the interface could be successfully\r
59 installed\r
60\r
61--*/\r
62{\r
63 //\r
64 // Publish the variable capability to other modules\r
65 //\r
66 return (**PeiServices).InstallPpi (PeiServices, &mPpiListVariable);\r
67\r
68}\r
69\r
1cc8ee78 70STATIC\r
878ddf1f 71VARIABLE_HEADER *\r
72GetNextVariablePtr (\r
73 IN VARIABLE_HEADER *Variable\r
74 )\r
75/*++\r
76\r
77Routine Description:\r
78\r
79 This code checks if variable header is valid or not.\r
80\r
81Arguments:\r
82 Variable Pointer to the Variable Header.\r
83\r
84Returns:\r
85 TRUE Variable header is valid.\r
86 FALSE Variable header is not valid.\r
87\r
88--*/\r
89{\r
90 return (VARIABLE_HEADER *) ((UINTN) GET_VARIABLE_DATA_PTR (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
91}\r
92\r
1cc8ee78 93STATIC\r
878ddf1f 94BOOLEAN\r
95EFIAPI\r
96IsValidVariableHeader (\r
97 IN VARIABLE_HEADER *Variable\r
98 )\r
99/*++\r
100\r
101Routine Description:\r
102\r
103 This code checks if variable header is valid or not.\r
104\r
105Arguments:\r
106 Variable Pointer to the Variable Header.\r
107\r
108Returns:\r
109 TRUE Variable header is valid.\r
110 FALSE Variable header is not valid.\r
111\r
112--*/\r
113{\r
114 if (Variable == NULL ||\r
115 Variable->StartId != VARIABLE_DATA ||\r
116 (sizeof (VARIABLE_HEADER) + Variable->DataSize + Variable->NameSize) > MAX_VARIABLE_SIZE\r
117 ) {\r
118 return FALSE;\r
119 }\r
120\r
121 return TRUE;\r
122}\r
123\r
1cc8ee78 124STATIC\r
878ddf1f 125VARIABLE_STORE_STATUS\r
126EFIAPI\r
127GetVariableStoreStatus (\r
128 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
129 )\r
130/*++\r
131\r
132Routine Description:\r
133\r
134 This code gets the pointer to the variable name.\r
135\r
136Arguments:\r
137\r
138 VarStoreHeader Pointer to the Variable Store Header.\r
139\r
140Returns:\r
141\r
142 EfiRaw Variable store is raw\r
143 EfiValid Variable store is valid\r
144 EfiInvalid Variable store is invalid\r
145\r
146--*/\r
147{\r
148 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
149 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
150 VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
151 ) {\r
152\r
153 return EfiValid;\r
154 }\r
155\r
156 if (VarStoreHeader->Signature == 0xffffffff &&\r
157 VarStoreHeader->Size == 0xffffffff &&\r
158 VarStoreHeader->Format == 0xff &&\r
159 VarStoreHeader->State == 0xff\r
160 ) {\r
161\r
162 return EfiRaw;\r
163 } else {\r
164 return EfiInvalid;\r
165 }\r
166}\r
167\r
1cc8ee78 168STATIC\r
878ddf1f 169EFI_STATUS\r
170CompareWithValidVariable (\r
171 IN VARIABLE_HEADER *Variable,\r
172 IN CHAR16 *VariableName,\r
173 IN EFI_GUID *VendorGuid,\r
174 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
175 )\r
176/*++\r
177\r
178Routine Description:\r
179\r
180 This function compares a variable with variable entries in database\r
181\r
182Arguments:\r
183\r
184 Variable - Pointer to the variable in our database\r
185 VariableName - Name of the variable to compare to 'Variable'\r
186 VendorGuid - GUID of the variable to compare to 'Variable'\r
187 PtrTrack - Variable Track Pointer structure that contains\r
188 Variable Information.\r
189\r
190Returns:\r
191\r
192 EFI_SUCCESS - Found match variable\r
193 EFI_NOT_FOUND - Variable not found\r
3aaddf92 194\r
878ddf1f 195--*/\r
196{\r
197 if (VariableName[0] == 0) {\r
198 PtrTrack->CurrPtr = Variable;\r
199 return EFI_SUCCESS;\r
200 } else {\r
201 //\r
202 // Don't use CompareGuid function here for performance reasons.\r
203 // Instead we compare the GUID a UINT32 at a time and branch\r
204 // on the first failed comparison.\r
205 //\r
206 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&\r
207 (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&\r
208 (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&\r
209 (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])\r
210 ) {\r
bb60dd97 211 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), Variable->NameSize)) {\r
878ddf1f 212 PtrTrack->CurrPtr = Variable;\r
213 return EFI_SUCCESS;\r
214 }\r
215 }\r
216 }\r
217\r
218 return EFI_NOT_FOUND;\r
219}\r
220\r
1cc8ee78 221STATIC\r
878ddf1f 222EFI_STATUS\r
223EFIAPI\r
224FindVariable (\r
225 IN EFI_PEI_SERVICES **PeiServices,\r
226 IN CHAR16 *VariableName,\r
227 IN EFI_GUID *VendorGuid,\r
228 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
229 )\r
230/*++\r
231\r
232Routine Description:\r
233\r
234 This code finds variable in storage blocks (Non-Volatile)\r
235\r
236Arguments:\r
237\r
238 PeiServices - General purpose services available to every PEIM.\r
239 VariableName - Name of the variable to be found\r
240 VendorGuid - Vendor GUID to be found.\r
241 PtrTrack - Variable Track Pointer structure that contains\r
242 Variable Information.\r
243\r
244Returns:\r
245\r
246 EFI_SUCCESS - Variable found successfully\r
247 EFI_NOT_FOUND - Variable not found\r
248 EFI_INVALID_PARAMETER - Invalid variable name\r
249\r
250--*/\r
251{\r
878ddf1f 252 EFI_HOB_GUID_TYPE *GuidHob;\r
253 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
254 VARIABLE_HEADER *Variable;\r
878ddf1f 255 VARIABLE_HEADER *MaxIndex;\r
256 VARIABLE_INDEX_TABLE *IndexTable;\r
257 UINT32 Count;\r
5dd2d779 258 UINT8 *VariableBase;\r
878ddf1f 259\r
260 if (VariableName != 0 && VendorGuid == NULL) {\r
261 return EFI_INVALID_PARAMETER;\r
262 }\r
263 //\r
264 // No Variable Address equals zero, so 0 as initial value is safe.\r
265 //\r
266 MaxIndex = 0;\r
3aaddf92 267\r
878ddf1f 268 GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);\r
269 if (GuidHob == NULL) {\r
270 IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
271 IndexTable->Length = 0;\r
272 IndexTable->StartPtr = NULL;\r
273 IndexTable->EndPtr = NULL;\r
274 IndexTable->GoneThrough = 0;\r
275 } else {\r
276 IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
277 for (Count = 0; Count < IndexTable->Length; Count++)\r
278 {\r
3aaddf92 279 MaxIndex = GetVariableByIndex (IndexTable, Count);\r
280\r
878ddf1f 281 if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
282 PtrTrack->StartPtr = IndexTable->StartPtr;\r
283 PtrTrack->EndPtr = IndexTable->EndPtr;\r
284\r
285 return EFI_SUCCESS;\r
286 }\r
287 }\r
288\r
289 if (IndexTable->GoneThrough) {\r
290 return EFI_NOT_FOUND;\r
291 }\r
292 }\r
293 //\r
294 // If not found in HOB, then let's start from the MaxIndex we've found.\r
295 //\r
296 if (MaxIndex != NULL) {\r
297 Variable = GetNextVariablePtr (MaxIndex);\r
298 } else {\r
299 if (IndexTable->StartPtr || IndexTable->EndPtr) {\r
300 Variable = IndexTable->StartPtr;\r
301 } else {\r
5dd2d779 302 VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);\r
303 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \\r
304 ((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);\r
3aaddf92 305\r
878ddf1f 306 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
307 return EFI_UNSUPPORTED;\r
308 }\r
309\r
310 if (~VariableStoreHeader->Size == 0) {\r
311 return EFI_NOT_FOUND;\r
312 }\r
313 //\r
314 // Find the variable by walk through non-volatile variable store\r
315 //\r
316 IndexTable->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
317 IndexTable->EndPtr = (VARIABLE_HEADER *) ((UINTN) VariableStoreHeader + VariableStoreHeader->Size);\r
318\r
319 //\r
320 // Start Pointers for the variable.\r
321 // Actual Data Pointer where data can be written.\r
322 //\r
323 Variable = IndexTable->StartPtr;\r
324 }\r
325 }\r
326 //\r
327 // Find the variable by walk through non-volatile variable store\r
328 //\r
329 PtrTrack->StartPtr = IndexTable->StartPtr;\r
330 PtrTrack->EndPtr = IndexTable->EndPtr;\r
331\r
332 while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) {\r
333 if (Variable->State == VAR_ADDED) {\r
334 //\r
335 // Record Variable in VariableIndex HOB\r
336 //\r
337 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME)\r
338 {\r
3aaddf92 339 VariableIndexTableUpdate (IndexTable, Variable);\r
878ddf1f 340 }\r
341\r
342 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
343 return EFI_SUCCESS;\r
344 }\r
345 }\r
346\r
347 Variable = GetNextVariablePtr (Variable);\r
348 }\r
349 //\r
350 // If gone through the VariableStore, that means we never find in Firmware any more.\r
351 //\r
352 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) {\r
353 IndexTable->GoneThrough = 1;\r
354 }\r
355\r
356 PtrTrack->CurrPtr = NULL;\r
357\r
358 return EFI_NOT_FOUND;\r
359}\r
360\r
361EFI_STATUS\r
362EFIAPI\r
363PeiGetVariable (\r
364 IN EFI_PEI_SERVICES **PeiServices,\r
365 IN CHAR16 *VariableName,\r
366 IN EFI_GUID * VendorGuid,\r
367 OUT UINT32 *Attributes OPTIONAL,\r
368 IN OUT UINTN *DataSize,\r
369 OUT VOID *Data\r
370 )\r
371/*++\r
372\r
373Routine Description:\r
374\r
375 Provide the read variable functionality of the variable services.\r
376\r
377Arguments:\r
378\r
379 PeiServices - General purpose services available to every PEIM.\r
380\r
381 VariableName - The variable name\r
382\r
383 VendorGuid - The vendor's GUID\r
384\r
385 Attributes - Pointer to the attribute\r
386\r
387 DataSize - Size of data\r
388\r
389 Data - Pointer to data\r
390\r
391Returns:\r
392\r
393 EFI_SUCCESS - The interface could be successfully installed\r
394\r
395 EFI_NOT_FOUND - The variable could not be discovered\r
396\r
397 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough\r
398\r
399--*/\r
400{\r
401 VARIABLE_POINTER_TRACK Variable;\r
402 UINTN VarDataSize;\r
403 EFI_STATUS Status;\r
404\r
405 if (VariableName == NULL || VendorGuid == NULL) {\r
406 return EFI_INVALID_PARAMETER;\r
407 }\r
408 //\r
409 // Find existing variable\r
410 //\r
411 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
412\r
413 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
414 return Status;\r
415 }\r
416 //\r
417 // Get data size\r
418 //\r
419 VarDataSize = Variable.CurrPtr->DataSize;\r
420 if (*DataSize >= VarDataSize) {\r
421 (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize);\r
422\r
423 if (Attributes != NULL) {\r
424 *Attributes = Variable.CurrPtr->Attributes;\r
425 }\r
426\r
427 *DataSize = VarDataSize;\r
428 return EFI_SUCCESS;\r
429 } else {\r
430 *DataSize = VarDataSize;\r
431 return EFI_BUFFER_TOO_SMALL;\r
432 }\r
433}\r
434\r
435EFI_STATUS\r
436EFIAPI\r
437PeiGetNextVariableName (\r
438 IN EFI_PEI_SERVICES **PeiServices,\r
439 IN OUT UINTN *VariableNameSize,\r
440 IN OUT CHAR16 *VariableName,\r
441 IN OUT EFI_GUID *VendorGuid\r
442 )\r
443/*++\r
444\r
445Routine Description:\r
446\r
447 Provide the get next variable functionality of the variable services.\r
448\r
449Arguments:\r
450\r
451 PeiServices - General purpose services available to every PEIM.\r
452 VariabvleNameSize - The variable name's size.\r
453 VariableName - A pointer to the variable's name.\r
454 VendorGuid - A pointer to the EFI_GUID structure.\r
455\r
456 VariableNameSize - Size of the variable name\r
457\r
458 VariableName - The variable name\r
459\r
460 VendorGuid - The vendor's GUID\r
461\r
462Returns:\r
463\r
464 EFI_SUCCESS - The interface could be successfully installed\r
465\r
466 EFI_NOT_FOUND - The variable could not be discovered\r
467\r
468--*/\r
469{\r
470 VARIABLE_POINTER_TRACK Variable;\r
471 UINTN VarNameSize;\r
472 EFI_STATUS Status;\r
473\r
474 if (VariableName == NULL) {\r
475 return EFI_INVALID_PARAMETER;\r
476 }\r
477\r
478 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
479\r
480 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
481 return Status;\r
482 }\r
483\r
484 if (VariableName[0] != 0) {\r
485 //\r
486 // If variable name is not NULL, get next variable\r
487 //\r
488 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
489 }\r
490\r
491 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {\r
492 if (IsValidVariableHeader (Variable.CurrPtr)) {\r
493 if (Variable.CurrPtr->State == VAR_ADDED) {\r
494 VarNameSize = (UINTN) Variable.CurrPtr->NameSize;\r
495 if (VarNameSize <= *VariableNameSize) {\r
496 (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);\r
497\r
498 (*PeiServices)->CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
499\r
500 Status = EFI_SUCCESS;\r
501 } else {\r
502 Status = EFI_BUFFER_TOO_SMALL;\r
503 }\r
504\r
505 *VariableNameSize = VarNameSize;\r
506 return Status;\r
507 //\r
508 // Variable is found\r
509 //\r
510 } else {\r
511 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
512 }\r
513 } else {\r
514 break;\r
515 }\r
516 }\r
517\r
518 return EFI_NOT_FOUND;\r
519}\r