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