]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/VariablePei/Variable.c
Align the header of variable from 1 to 4, which can avoid the size of variable conten...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / VariablePei / Variable.c
CommitLineData
7ba905c9 1/*++\r
2\r
3Copyright (c) 2006 - 2007 Intel Corporation. <BR>\r
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
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
21\r
22#include "Variable.h"\r
23\r
24//\r
25// Module globals\r
26//\r
27static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi = {\r
28 PeiGetVariable,\r
29 PeiGetNextVariableName\r
30};\r
31\r
32static EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariable2Ppi = {\r
33 PeiGetVariable2,\r
34 PeiGetNextVariableName2\r
35};\r
36\r
37static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable[] = {\r
38 {\r
39 (EFI_PEI_PPI_DESCRIPTOR_PPI),\r
40 &gEfiPeiReadOnlyVariable2PpiGuid,\r
41 &mVariable2Ppi\r
42 },\r
43 {\r
44 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
45 &gEfiPeiReadOnlyVariablePpiGuid,\r
46 &mVariablePpi\r
47 }\r
48};\r
49\r
50EFI_GUID mEfiVariableIndexTableGuid = EFI_VARIABLE_INDEX_TABLE_GUID;\r
51\r
52EFI_STATUS\r
53EFIAPI\r
54PeimInitializeVariableServices (\r
55 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
56 IN EFI_PEI_SERVICES **PeiServices\r
57 )\r
58/*++\r
59\r
60Routine Description:\r
61\r
62 Provide the functionality of the variable services.\r
63\r
64Arguments:\r
65\r
66 FfsHeadher - The FFS file header\r
67 PeiServices - General purpose services available to every PEIM.\r
68\r
69Returns:\r
70\r
71 Status - EFI_SUCCESS if the interface could be successfully\r
72 installed\r
73\r
74--*/\r
75{\r
76 //\r
77 // Publish the variable capability to other modules\r
78 //\r
507b36ca 79 return (**PeiServices).InstallPpi ((CONST EFI_PEI_SERVICES **) PeiServices, &mPpiListVariable[0]);\r
7ba905c9 80\r
81}\r
82\r
9cad030b 83\r
84UINT32\r
85NameSizeOfVariable (\r
86 IN VARIABLE_HEADER *Variable\r
87 )\r
88{\r
89 //\r
90 // Check whether the header is valid fully;\r
91 // Tricky: The unprogramed data in FLASH equals 0xff.\r
92 // \r
93 if (Variable->DataSize == (UINT32) -1 || \r
94 Variable->Attributes == (UINT32) -1 || \r
95 Variable->NameSize == (UINT32) -1) {\r
96 return 0;\r
97 }\r
98 return Variable->NameSize;\r
99}\r
100\r
101UINT32\r
102DataSizeOfVariable (\r
103 IN VARIABLE_HEADER *Variable\r
104 )\r
105{\r
106 //\r
107 // Check whether the header is valid fully;\r
108 // Tricky: The unprogramed data in FLASH equals 0xff.\r
109 // \r
110 if (Variable->DataSize == (UINT32) -1 || \r
111 Variable->Attributes == (UINT32) -1 || \r
112 Variable->NameSize == (UINT32) -1) {\r
113 return 0;\r
114 }\r
115 return Variable->DataSize;\r
116}\r
117\r
118UINT32\r
119AttributesOfVariable (\r
120 IN VARIABLE_HEADER *Variable\r
121 )\r
122{\r
123\r
124 //\r
125 // Check whether the header is valid fully;\r
126 // Tricky: The unprogramed data in FLASH equals 0xff.\r
127 // \r
128 if (Variable->DataSize == (UINT32) -1 || \r
129 Variable->Attributes == (UINT32) -1 || \r
130 Variable->NameSize == (UINT32) -1) {\r
131 return 0;\r
132 }\r
133 return Variable->Attributes;\r
134}\r
135\r
7ba905c9 136STATIC\r
137VARIABLE_HEADER *\r
138GetNextVariablePtr (\r
139 IN VARIABLE_HEADER *Variable\r
140 )\r
141/*++\r
142\r
143Routine Description:\r
144\r
145 This code checks if variable header is valid or not.\r
146\r
147Arguments:\r
148 Variable Pointer to the Variable Header.\r
149\r
150Returns:\r
151 TRUE Variable header is valid.\r
152 FALSE Variable header is not valid.\r
153\r
154--*/\r
155{\r
9cad030b 156 return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) GET_VARIABLE_DATA_PTR (Variable) + DataSizeOfVariable (Variable) + GET_PAD_SIZE (DataSizeOfVariable (Variable)));\r
7ba905c9 157}\r
158\r
159STATIC\r
160BOOLEAN\r
161EFIAPI\r
162IsValidVariableHeader (\r
163 IN VARIABLE_HEADER *Variable\r
164 )\r
165/*++\r
166\r
167Routine Description:\r
168\r
169 This code checks if variable header is valid or not.\r
170\r
171Arguments:\r
172 Variable Pointer to the Variable Header.\r
173\r
174Returns:\r
175 TRUE Variable header is valid.\r
176 FALSE Variable header is not valid.\r
177\r
178--*/\r
179{\r
9cad030b 180 if (Variable == NULL || Variable->StartId != VARIABLE_DATA ) {\r
7ba905c9 181 return FALSE;\r
182 }\r
183\r
184 return TRUE;\r
185}\r
186\r
187STATIC\r
188VARIABLE_STORE_STATUS\r
189EFIAPI\r
190GetVariableStoreStatus (\r
191 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
192 )\r
193/*++\r
194\r
195Routine Description:\r
196\r
197 This code gets the pointer to the variable name.\r
198\r
199Arguments:\r
200\r
201 VarStoreHeader Pointer to the Variable Store Header.\r
202\r
203Returns:\r
204\r
205 EfiRaw Variable store is raw\r
206 EfiValid Variable store is valid\r
207 EfiInvalid Variable store is invalid\r
208\r
209--*/\r
210{\r
211 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
212 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
213 VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
214 ) {\r
215\r
216 return EfiValid;\r
217 }\r
218\r
219 if (VarStoreHeader->Signature == 0xffffffff &&\r
220 VarStoreHeader->Size == 0xffffffff &&\r
221 VarStoreHeader->Format == 0xff &&\r
222 VarStoreHeader->State == 0xff\r
223 ) {\r
224\r
225 return EfiRaw;\r
226 } else {\r
227 return EfiInvalid;\r
228 }\r
229}\r
230\r
231STATIC\r
232EFI_STATUS\r
233CompareWithValidVariable (\r
234 IN VARIABLE_HEADER *Variable,\r
235 IN CONST CHAR16 *VariableName,\r
236 IN CONST EFI_GUID *VendorGuid,\r
237 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
238 )\r
239/*++\r
240\r
241Routine Description:\r
242\r
243 This function compares a variable with variable entries in database\r
244\r
245Arguments:\r
246\r
247 Variable - Pointer to the variable in our database\r
248 VariableName - Name of the variable to compare to 'Variable'\r
249 VendorGuid - GUID of the variable to compare to 'Variable'\r
250 PtrTrack - Variable Track Pointer structure that contains\r
251 Variable Information.\r
252\r
253Returns:\r
254\r
255 EFI_SUCCESS - Found match variable\r
256 EFI_NOT_FOUND - Variable not found\r
257\r
258--*/\r
259{\r
260 if (VariableName[0] == 0) {\r
261 PtrTrack->CurrPtr = Variable;\r
262 return EFI_SUCCESS;\r
263 } else {\r
264 //\r
265 // Don't use CompareGuid function here for performance reasons.\r
266 // Instead we compare the GUID a UINT32 at a time and branch\r
267 // on the first failed comparison.\r
268 //\r
269 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&\r
270 (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&\r
271 (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&\r
272 (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])\r
273 ) {\r
9cad030b 274 ASSERT (NameSizeOfVariable (Variable) != 0);\r
275 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), NameSizeOfVariable (Variable))) {\r
7ba905c9 276 PtrTrack->CurrPtr = Variable;\r
277 return EFI_SUCCESS;\r
278 }\r
279 }\r
280 }\r
281\r
282 return EFI_NOT_FOUND;\r
283}\r
284\r
285STATIC\r
286EFI_STATUS\r
287EFIAPI\r
288FindVariable (\r
289 IN EFI_PEI_SERVICES **PeiServices,\r
290 IN CONST CHAR16 *VariableName,\r
291 IN CONST EFI_GUID *VendorGuid,\r
292 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
293 )\r
294/*++\r
295\r
296Routine Description:\r
297\r
298 This code finds variable in storage blocks (Non-Volatile)\r
299\r
300Arguments:\r
301\r
302 PeiServices - General purpose services available to every PEIM.\r
303 VariableName - Name of the variable to be found\r
304 VendorGuid - Vendor GUID to be found.\r
305 PtrTrack - Variable Track Pointer structure that contains\r
306 Variable Information.\r
307\r
308Returns:\r
309\r
310 EFI_SUCCESS - Variable found successfully\r
311 EFI_NOT_FOUND - Variable not found\r
312 EFI_INVALID_PARAMETER - Invalid variable name\r
313\r
314--*/\r
315{\r
316 EFI_HOB_GUID_TYPE *GuidHob;\r
317 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
318 VARIABLE_HEADER *Variable;\r
319 VARIABLE_HEADER *MaxIndex;\r
320 VARIABLE_INDEX_TABLE *IndexTable;\r
321 UINT32 Count;\r
322 UINT8 *VariableBase;\r
323\r
324 if (VariableName != 0 && VendorGuid == NULL) {\r
325 return EFI_INVALID_PARAMETER;\r
326 }\r
327 //\r
328 // No Variable Address equals zero, so 0 as initial value is safe.\r
329 //\r
330 MaxIndex = 0;\r
331\r
332 GuidHob = GetFirstGuidHob (&mEfiVariableIndexTableGuid);\r
333 if (GuidHob == NULL) {\r
334 IndexTable = BuildGuidHob (&mEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
335 IndexTable->Length = 0;\r
336 IndexTable->StartPtr = NULL;\r
337 IndexTable->EndPtr = NULL;\r
338 IndexTable->GoneThrough = 0;\r
339 } else {\r
340 IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
341 for (Count = 0; Count < IndexTable->Length; Count++)\r
342 {\r
343 MaxIndex = GetVariableByIndex (IndexTable, Count);\r
7ba905c9 344 if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
345 PtrTrack->StartPtr = IndexTable->StartPtr;\r
346 PtrTrack->EndPtr = IndexTable->EndPtr;\r
347\r
348 return EFI_SUCCESS;\r
349 }\r
350 }\r
351\r
352 if (IndexTable->GoneThrough) {\r
353 return EFI_NOT_FOUND;\r
354 }\r
355 }\r
356 //\r
357 // If not found in HOB, then let's start from the MaxIndex we've found.\r
358 //\r
359 if (MaxIndex != NULL) {\r
360 Variable = GetNextVariablePtr (MaxIndex);\r
361 } else {\r
362 if (IndexTable->StartPtr || IndexTable->EndPtr) {\r
363 Variable = IndexTable->StartPtr;\r
364 } else {\r
365 VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);\r
366 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \\r
367 ((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);\r
368\r
369 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
370 return EFI_UNSUPPORTED;\r
371 }\r
372\r
373 if (~VariableStoreHeader->Size == 0) {\r
374 return EFI_NOT_FOUND;\r
375 }\r
376 //\r
377 // Find the variable by walk through non-volatile variable store\r
378 //\r
379 IndexTable->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
380 IndexTable->EndPtr = (VARIABLE_HEADER *) ((UINTN) VariableStoreHeader + VariableStoreHeader->Size);\r
381\r
382 //\r
383 // Start Pointers for the variable.\r
384 // Actual Data Pointer where data can be written.\r
385 //\r
386 Variable = IndexTable->StartPtr;\r
387 }\r
388 }\r
389 //\r
390 // Find the variable by walk through non-volatile variable store\r
391 //\r
392 PtrTrack->StartPtr = IndexTable->StartPtr;\r
393 PtrTrack->EndPtr = IndexTable->EndPtr;\r
394\r
395 while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) {\r
396 if (Variable->State == VAR_ADDED) {\r
397 //\r
398 // Record Variable in VariableIndex HOB\r
399 //\r
400 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME)\r
401 {\r
402 VariableIndexTableUpdate (IndexTable, Variable);\r
403 }\r
404\r
405 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
406 return EFI_SUCCESS;\r
407 }\r
408 }\r
409\r
410 Variable = GetNextVariablePtr (Variable);\r
411 }\r
412 //\r
413 // If gone through the VariableStore, that means we never find in Firmware any more.\r
414 //\r
415 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) {\r
416 IndexTable->GoneThrough = 1;\r
417 }\r
418\r
419 PtrTrack->CurrPtr = NULL;\r
420\r
421 return EFI_NOT_FOUND;\r
422}\r
423\r
424EFI_STATUS\r
425EFIAPI\r
426PeiGetVariable (\r
427 IN EFI_PEI_SERVICES **PeiServices,\r
428 IN CHAR16 *VariableName,\r
429 IN EFI_GUID * VendorGuid,\r
430 OUT UINT32 *Attributes OPTIONAL,\r
431 IN OUT UINTN *DataSize,\r
432 OUT VOID *Data\r
433 )\r
434/*++\r
435\r
436Routine Description:\r
437\r
438 Provide the read variable functionality of the variable services.\r
439\r
440Arguments:\r
441\r
442 PeiServices - General purpose services available to every PEIM.\r
443\r
444 VariableName - The variable name\r
445\r
446 VendorGuid - The vendor's GUID\r
447\r
448 Attributes - Pointer to the attribute\r
449\r
450 DataSize - Size of data\r
451\r
452 Data - Pointer to data\r
453\r
454Returns:\r
455\r
456 EFI_SUCCESS - The interface could be successfully installed\r
457\r
458 EFI_NOT_FOUND - The variable could not be discovered\r
459\r
460 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough\r
461\r
462--*/\r
463{\r
464 VARIABLE_POINTER_TRACK Variable;\r
465 UINTN VarDataSize;\r
466 EFI_STATUS Status;\r
467\r
468 if (VariableName == NULL || VendorGuid == NULL) {\r
469 return EFI_INVALID_PARAMETER;\r
470 }\r
471 //\r
472 // Find existing variable\r
473 //\r
474 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
475\r
476 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
477 return Status;\r
478 }\r
479 //\r
480 // Get data size\r
481 //\r
9cad030b 482 VarDataSize = DataSizeOfVariable (Variable.CurrPtr);\r
7ba905c9 483 if (*DataSize >= VarDataSize) {\r
484 (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize);\r
485\r
486 if (Attributes != NULL) {\r
487 *Attributes = Variable.CurrPtr->Attributes;\r
488 }\r
489\r
490 *DataSize = VarDataSize;\r
491 return EFI_SUCCESS;\r
492 } else {\r
493 *DataSize = VarDataSize;\r
494 return EFI_BUFFER_TOO_SMALL;\r
495 }\r
496}\r
497\r
498\r
499EFI_STATUS\r
500EFIAPI\r
501PeiGetVariable2 (\r
502 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
503 IN CONST CHAR16 *VariableName,\r
504 IN CONST EFI_GUID *VariableGuid,\r
505 OUT UINT32 *Attributes,\r
506 IN OUT UINTN *DataSize,\r
507 OUT VOID *Data\r
508 )\r
509/*++\r
510\r
511Routine Description:\r
512\r
513 Provide the read variable functionality of the variable services.\r
514\r
515Arguments:\r
516\r
517 PeiServices - General purpose services available to every PEIM.\r
518\r
519 VariableName - The variable name\r
520\r
521 VendorGuid - The vendor's GUID\r
522\r
523 Attributes - Pointer to the attribute\r
524\r
525 DataSize - Size of data\r
526\r
527 Data - Pointer to data\r
528\r
529Returns:\r
530\r
531 EFI_SUCCESS - The interface could be successfully installed\r
532\r
533 EFI_NOT_FOUND - The variable could not be discovered\r
534\r
535 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough\r
536\r
537--*/\r
538{\r
539 return PeiGetVariable (\r
540 GetPeiServicesTablePointer (),\r
541 (CHAR16*)VariableName,\r
542 (EFI_GUID*)VariableGuid,\r
543 Attributes,\r
544 DataSize,\r
545 Data\r
546 );\r
547}\r
548\r
549EFI_STATUS\r
550EFIAPI\r
551PeiGetNextVariableName (\r
552 IN EFI_PEI_SERVICES **PeiServices,\r
553 IN OUT UINTN *VariableNameSize,\r
554 IN OUT CHAR16 *VariableName,\r
555 IN OUT EFI_GUID *VendorGuid\r
556 )\r
557/*++\r
558\r
559Routine Description:\r
560\r
561 Provide the get next variable functionality of the variable services.\r
562\r
563Arguments:\r
564\r
565 PeiServices - General purpose services available to every PEIM.\r
566 VariabvleNameSize - The variable name's size.\r
567 VariableName - A pointer to the variable's name.\r
568 VendorGuid - A pointer to the EFI_GUID structure.\r
569\r
570 VariableNameSize - Size of the variable name\r
571\r
572 VariableName - The variable name\r
573\r
574 VendorGuid - The vendor's GUID\r
575\r
576Returns:\r
577\r
578 EFI_SUCCESS - The interface could be successfully installed\r
579\r
580 EFI_NOT_FOUND - The variable could not be discovered\r
581\r
582--*/\r
583{\r
584 VARIABLE_POINTER_TRACK Variable;\r
585 UINTN VarNameSize;\r
586 EFI_STATUS Status;\r
587\r
588 if (VariableName == NULL) {\r
589 return EFI_INVALID_PARAMETER;\r
590 }\r
591\r
592 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
593\r
594 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
595 return Status;\r
596 }\r
597\r
598 if (VariableName[0] != 0) {\r
599 //\r
600 // If variable name is not NULL, get next variable\r
601 //\r
602 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
603 }\r
604\r
605 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {\r
606 if (IsValidVariableHeader (Variable.CurrPtr)) {\r
607 if (Variable.CurrPtr->State == VAR_ADDED) {\r
9cad030b 608 ASSERT (NameSizeOfVariable (Variable.CurrPtr) != 0);\r
609\r
610 VarNameSize = (UINTN) NameSizeOfVariable (Variable.CurrPtr);\r
7ba905c9 611 if (VarNameSize <= *VariableNameSize) {\r
612 (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);\r
613\r
614 (*PeiServices)->CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
615\r
616 Status = EFI_SUCCESS;\r
617 } else {\r
618 Status = EFI_BUFFER_TOO_SMALL;\r
619 }\r
620\r
621 *VariableNameSize = VarNameSize;\r
622 return Status;\r
623 //\r
624 // Variable is found\r
625 //\r
626 } else {\r
627 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
628 }\r
629 } else {\r
630 break;\r
631 }\r
632 }\r
633\r
634 return EFI_NOT_FOUND;\r
635}\r
636\r
637EFI_STATUS\r
638EFIAPI\r
639PeiGetNextVariableName2 (\r
640 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
641 IN OUT UINTN *VariableNameSize,\r
642 IN OUT CHAR16 *VariableName,\r
643 IN OUT EFI_GUID *VariableGuid\r
644 )\r
645/*++\r
646\r
647Routine Description:\r
648\r
649 Provide the get next variable functionality of the variable services.\r
650\r
651Arguments:\r
652\r
653 PeiServices - General purpose services available to every PEIM.\r
654 VariabvleNameSize - The variable name's size.\r
655 VariableName - A pointer to the variable's name.\r
656 VariableGuid - A pointer to the EFI_GUID structure.\r
657\r
658 VariableNameSize - Size of the variable name\r
659\r
660 VariableName - The variable name\r
661\r
662 VendorGuid - The vendor's GUID\r
663\r
664Returns:\r
665\r
666 EFI_SUCCESS - The interface could be successfully installed\r
667\r
668 EFI_NOT_FOUND - The variable could not be discovered\r
669\r
670--*/\r
671{\r
672 return PeiGetNextVariableName (\r
673 GetPeiServicesTablePointer (),\r
674 VariableNameSize,\r
675 VariableName,\r
676 VariableGuid\r
677 );\r
6bee1632 678}\r