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