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
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.
17 Framework PEIM to provide the Variable functionality
27 static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi
= {
29 PeiGetNextVariableName
32 static EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariable2Ppi
= {
34 PeiGetNextVariableName2
37 static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
[] = {
39 (EFI_PEI_PPI_DESCRIPTOR_PPI
),
40 &gEfiPeiReadOnlyVariable2PpiGuid
,
44 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
45 &gEfiPeiReadOnlyVariablePpiGuid
,
50 EFI_GUID mEfiVariableIndexTableGuid
= EFI_VARIABLE_INDEX_TABLE_GUID
;
54 PeimInitializeVariableServices (
55 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
56 IN EFI_PEI_SERVICES
**PeiServices
62 Provide the functionality of the variable services.
66 FfsHeadher - The FFS file header
67 PeiServices - General purpose services available to every PEIM.
71 Status - EFI_SUCCESS if the interface could be successfully
77 // Publish the variable capability to other modules
79 return (**PeiServices
).InstallPpi ((CONST EFI_PEI_SERVICES
**) PeiServices
, &mPpiListVariable
[0]);
85 IN VARIABLE_STORE_HEADER
*VarStoreHeader
91 This code gets the pointer to the first variable memory pointer byte
95 VarStoreHeader Pointer to the Variable Store Header.
99 VARIABLE_HEADER* Pointer to last unavailable Variable Header
104 // The end of variable store
106 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
111 IN VARIABLE_STORE_HEADER
*VarStoreHeader
117 This code gets the pointer to the last variable memory pointer byte
121 VarStoreHeader Pointer to the Variable Store Header.
125 VARIABLE_HEADER* Pointer to last unavailable Variable Header
130 // The end of variable store
132 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
138 IsValidVariableHeader (
139 IN VARIABLE_HEADER
*Variable
145 This code checks if variable header is valid or not.
148 Variable Pointer to the Variable Header.
151 TRUE Variable header is valid.
152 FALSE Variable header is not valid.
156 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
166 IN VARIABLE_HEADER
*Variable
172 This code gets the size of name of variable.
176 Variable Pointer to the Variable Header.
180 UINTN Size of variable in bytes
184 if (Variable
->State
== (UINT8
) (-1) ||
185 Variable
->DataSize
== (UINT32
) -1 ||
186 Variable
->NameSize
== (UINT32
) -1 ||
187 Variable
->Attributes
== (UINT32
) -1) {
190 return (UINTN
) Variable
->NameSize
;
195 IN VARIABLE_HEADER
*Variable
201 This code gets the size of name of variable.
205 Variable Pointer to the Variable Header.
209 UINTN Size of variable in bytes
213 if (Variable
->State
== (UINT8
) -1 ||
214 Variable
->DataSize
== (UINT32
) -1 ||
215 Variable
->NameSize
== (UINT32
) -1 ||
216 Variable
->Attributes
== (UINT32
) -1) {
219 return (UINTN
) Variable
->DataSize
;
224 IN VARIABLE_HEADER
*Variable
230 This code gets the pointer to the variable name.
234 Variable Pointer to the Variable Header.
238 CHAR16* Pointer to Variable Name
243 return (CHAR16
*) (Variable
+ 1);
249 IN VARIABLE_HEADER
*Variable
255 This code gets the pointer to the variable data.
259 Variable Pointer to the Variable Header.
263 UINT8* Pointer to Variable Data
270 // Be careful about pad size for alignment
272 Value
= (UINTN
) GetVariableNamePtr (Variable
);
273 Value
+= NameSizeOfVariable (Variable
);
274 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
276 return (UINT8
*) Value
;
281 IN VARIABLE_HEADER
*Variable
287 This code gets the pointer to the next variable header.
291 Variable Pointer to the Variable Header.
295 VARIABLE_HEADER* Pointer to next variable header.
301 if (!IsValidVariableHeader (Variable
)) {
305 Value
= (UINTN
) GetVariableDataPtr (Variable
);
306 Value
+= DataSizeOfVariable (Variable
);
307 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
310 // Be careful about pad size for alignment
312 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
317 VARIABLE_STORE_STATUS
319 GetVariableStoreStatus (
320 IN VARIABLE_STORE_HEADER
*VarStoreHeader
326 This code gets the pointer to the variable name.
330 VarStoreHeader Pointer to the Variable Store Header.
334 EfiRaw Variable store is raw
335 EfiValid Variable store is valid
336 EfiInvalid Variable store is invalid
340 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
341 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
342 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
348 if (VarStoreHeader
->Signature
== 0xffffffff &&
349 VarStoreHeader
->Size
== 0xffffffff &&
350 VarStoreHeader
->Format
== 0xff &&
351 VarStoreHeader
->State
== 0xff
362 CompareWithValidVariable (
363 IN VARIABLE_HEADER
*Variable
,
364 IN CONST CHAR16
*VariableName
,
365 IN CONST EFI_GUID
*VendorGuid
,
366 OUT VARIABLE_POINTER_TRACK
*PtrTrack
372 This function compares a variable with variable entries in database
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.
384 EFI_SUCCESS - Found match variable
385 EFI_NOT_FOUND - Variable not found
391 if (VariableName
[0] == 0) {
392 PtrTrack
->CurrPtr
= Variable
;
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.
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])
405 ASSERT (NameSizeOfVariable (Variable
) != 0);
406 Point
= (VOID
*) GetVariableNamePtr (Variable
);
407 if (!CompareMem (VariableName
, Point
, NameSizeOfVariable (Variable
))) {
408 PtrTrack
->CurrPtr
= Variable
;
414 return EFI_NOT_FOUND
;
421 IN EFI_PEI_SERVICES
**PeiServices
,
422 IN CONST CHAR16
*VariableName
,
423 IN CONST EFI_GUID
*VendorGuid
,
424 OUT VARIABLE_POINTER_TRACK
*PtrTrack
430 This code finds variable in storage blocks (Non-Volatile)
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.
442 EFI_SUCCESS - Variable found successfully
443 EFI_NOT_FOUND - Variable not found
444 EFI_INVALID_PARAMETER - Invalid variable name
448 EFI_HOB_GUID_TYPE
*GuidHob
;
449 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
450 VARIABLE_HEADER
*Variable
;
451 VARIABLE_HEADER
*MaxIndex
;
452 VARIABLE_INDEX_TABLE
*IndexTable
;
456 if (VariableName
!= 0 && VendorGuid
== NULL
) {
457 return EFI_INVALID_PARAMETER
;
460 // No Variable Address equals zero, so 0 as initial value is safe.
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;
472 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
473 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
475 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
477 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
478 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
479 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
485 if (IndexTable
->GoneThrough
) {
486 return EFI_NOT_FOUND
;
490 // If not found in HOB, then let's start from the MaxIndex we've found.
492 if (MaxIndex
!= NULL
) {
493 Variable
= GetNextVariablePtr (MaxIndex
);
495 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
496 Variable
= IndexTable
->StartPtr
;
498 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
499 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
500 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
502 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
503 return EFI_UNSUPPORTED
;
506 if (~VariableStoreHeader
->Size
== 0) {
507 return EFI_NOT_FOUND
;
510 // Find the variable by walk through non-volatile variable store
512 IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
513 IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
516 // Start Pointers for the variable.
517 // Actual Data Pointer where data can be written.
519 Variable
= IndexTable
->StartPtr
;
523 // Find the variable by walk through non-volatile variable store
525 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
526 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
528 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
529 if (Variable
->State
== VAR_ADDED
) {
531 // Record Variable in VariableIndex HOB
533 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
535 VariableIndexTableUpdate (IndexTable
, Variable
);
538 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
543 Variable
= GetNextVariablePtr (Variable
);
546 // If gone through the VariableStore, that means we never find in Firmware any more.
548 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
549 IndexTable
->GoneThrough
= 1;
552 PtrTrack
->CurrPtr
= NULL
;
554 return EFI_NOT_FOUND
;
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
,
571 Provide the read variable functionality of the variable services.
575 PeiServices - General purpose services available to every PEIM.
577 VariableName - The variable name
579 VendorGuid - The vendor's GUID
581 Attributes - Pointer to the attribute
583 DataSize - Size of data
585 Data - Pointer to data
589 EFI_SUCCESS - The interface could be successfully installed
591 EFI_NOT_FOUND - The variable could not be discovered
593 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
597 VARIABLE_POINTER_TRACK Variable
;
601 if (VariableName
== NULL
|| VendorGuid
== NULL
) {
602 return EFI_INVALID_PARAMETER
;
605 // Find existing variable
607 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
609 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
615 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
616 if (*DataSize
>= VarDataSize
) {
618 // PO-TKW: Address one checking in this place
621 return EFI_INVALID_PARAMETER
;
624 (*PeiServices
)->CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
626 if (Attributes
!= NULL
) {
627 *Attributes
= Variable
.CurrPtr
->Attributes
;
630 *DataSize
= VarDataSize
;
633 *DataSize
= VarDataSize
;
634 return EFI_BUFFER_TOO_SMALL
;
642 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
643 IN CONST CHAR16
*VariableName
,
644 IN CONST EFI_GUID
*VariableGuid
,
645 OUT UINT32
*Attributes
,
646 IN OUT UINTN
*DataSize
,
653 Provide the read variable functionality of the variable services.
657 PeiServices - General purpose services available to every PEIM.
659 VariableName - The variable name
661 VendorGuid - The vendor's GUID
663 Attributes - Pointer to the attribute
665 DataSize - Size of data
667 Data - Pointer to data
671 EFI_SUCCESS - The interface could be successfully installed
673 EFI_NOT_FOUND - The variable could not be discovered
675 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
679 return PeiGetVariable (
680 GetPeiServicesTablePointer (),
681 (CHAR16
*)VariableName
,
682 (EFI_GUID
*)VariableGuid
,
691 PeiGetNextVariableName (
692 IN EFI_PEI_SERVICES
**PeiServices
,
693 IN OUT UINTN
*VariableNameSize
,
694 IN OUT CHAR16
*VariableName
,
695 IN OUT EFI_GUID
*VendorGuid
701 Provide the get next variable functionality of the variable services.
705 PeiServices - General purpose services available to every PEIM.
706 VariabvleNameSize - The variable name's size.
707 VariableName - A pointer to the variable's name.
708 VendorGuid - A pointer to the EFI_GUID structure.
710 VariableNameSize - Size of the variable name
712 VariableName - The variable name
714 VendorGuid - The vendor's GUID
718 EFI_SUCCESS - The interface could be successfully installed
720 EFI_NOT_FOUND - The variable could not be discovered
724 VARIABLE_POINTER_TRACK Variable
;
728 if (VariableName
== NULL
) {
729 return EFI_INVALID_PARAMETER
;
732 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
734 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
738 if (VariableName
[0] != 0) {
740 // If variable name is not NULL, get next variable
742 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
745 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
746 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
747 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
748 ASSERT (NameSizeOfVariable (Variable
.CurrPtr
) != 0);
750 VarNameSize
= (UINTN
) NameSizeOfVariable (Variable
.CurrPtr
);
751 if (VarNameSize
<= *VariableNameSize
) {
752 (*PeiServices
)->CopyMem (VariableName
, GetVariableNamePtr (Variable
.CurrPtr
), VarNameSize
);
754 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
756 Status
= EFI_SUCCESS
;
758 Status
= EFI_BUFFER_TOO_SMALL
;
761 *VariableNameSize
= VarNameSize
;
767 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
774 return EFI_NOT_FOUND
;
779 PeiGetNextVariableName2 (
780 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
781 IN OUT UINTN
*VariableNameSize
,
782 IN OUT CHAR16
*VariableName
,
783 IN OUT EFI_GUID
*VariableGuid
789 Provide the get next variable functionality of the variable services.
793 PeiServices - General purpose services available to every PEIM.
794 VariabvleNameSize - The variable name's size.
795 VariableName - A pointer to the variable's name.
796 VariableGuid - A pointer to the EFI_GUID structure.
798 VariableNameSize - Size of the variable name
800 VariableName - The variable name
802 VendorGuid - The vendor's GUID
806 EFI_SUCCESS - The interface could be successfully installed
808 EFI_NOT_FOUND - The variable could not be discovered
812 return PeiGetNextVariableName (
813 GetPeiServicesTablePointer (),