3 Copyright (c) 2006 - 2008 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 PEIM to provide the Variable functionality
27 static EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi
= {
29 PeiGetNextVariableName
32 static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
= {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
34 &gEfiPeiReadOnlyVariable2PpiGuid
,
38 EFI_GUID mEfiVariableIndexTableGuid
= EFI_VARIABLE_INDEX_TABLE_GUID
;
42 PeimInitializeVariableServices (
43 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
44 IN EFI_PEI_SERVICES
**PeiServices
50 Provide the functionality of the variable services.
54 FfsHeadher - The FFS file header
55 PeiServices - General purpose services available to every PEIM.
59 Status - EFI_SUCCESS if the interface could be successfully
65 // Publish the variable capability to other modules
67 return (**PeiServices
).InstallPpi ((CONST EFI_PEI_SERVICES
**)PeiServices
, &mPpiListVariable
);
73 IN VARIABLE_STORE_HEADER
*VarStoreHeader
79 This code gets the pointer to the first variable memory pointer byte
83 VarStoreHeader Pointer to the Variable Store Header.
87 VARIABLE_HEADER* Pointer to last unavailable Variable Header
92 // The end of variable store
94 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
99 IN VARIABLE_STORE_HEADER
*VarStoreHeader
105 This code gets the pointer to the last variable memory pointer byte
109 VarStoreHeader Pointer to the Variable Store Header.
113 VARIABLE_HEADER* Pointer to last unavailable Variable Header
118 // The end of variable store
120 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
126 IsValidVariableHeader (
127 IN VARIABLE_HEADER
*Variable
133 This code checks if variable header is valid or not.
136 Variable Pointer to the Variable Header.
139 TRUE Variable header is valid.
140 FALSE Variable header is not valid.
144 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
154 IN VARIABLE_HEADER
*Variable
160 This code gets the size of name of variable.
164 Variable Pointer to the Variable Header.
168 UINTN Size of variable in bytes
172 if (Variable
->State
== (UINT8
) (-1) ||
173 Variable
->DataSize
== (UINT32
) -1 ||
174 Variable
->NameSize
== (UINT32
) -1 ||
175 Variable
->Attributes
== (UINT32
) -1) {
178 return (UINTN
) Variable
->NameSize
;
183 IN VARIABLE_HEADER
*Variable
189 This code gets the size of name of variable.
193 Variable Pointer to the Variable Header.
197 UINTN Size of variable in bytes
201 if (Variable
->State
== (UINT8
) -1 ||
202 Variable
->DataSize
== (UINT32
) -1 ||
203 Variable
->NameSize
== (UINT32
) -1 ||
204 Variable
->Attributes
== (UINT32
) -1) {
207 return (UINTN
) Variable
->DataSize
;
212 IN VARIABLE_HEADER
*Variable
218 This code gets the pointer to the variable name.
222 Variable Pointer to the Variable Header.
226 CHAR16* Pointer to Variable Name
231 return (CHAR16
*) (Variable
+ 1);
237 IN VARIABLE_HEADER
*Variable
243 This code gets the pointer to the variable data.
247 Variable Pointer to the Variable Header.
251 UINT8* Pointer to Variable Data
258 // Be careful about pad size for alignment
260 Value
= (UINTN
) GetVariableNamePtr (Variable
);
261 Value
+= NameSizeOfVariable (Variable
);
262 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
264 return (UINT8
*) Value
;
269 IN VARIABLE_HEADER
*Variable
275 This code gets the pointer to the next variable header.
279 Variable Pointer to the Variable Header.
283 VARIABLE_HEADER* Pointer to next variable header.
289 if (!IsValidVariableHeader (Variable
)) {
293 Value
= (UINTN
) GetVariableDataPtr (Variable
);
294 Value
+= DataSizeOfVariable (Variable
);
295 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
298 // Be careful about pad size for alignment
300 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
305 VARIABLE_STORE_STATUS
307 GetVariableStoreStatus (
308 IN VARIABLE_STORE_HEADER
*VarStoreHeader
314 This code gets the pointer to the variable name.
318 VarStoreHeader Pointer to the Variable Store Header.
322 EfiRaw Variable store is raw
323 EfiValid Variable store is valid
324 EfiInvalid Variable store is invalid
328 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
329 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
330 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
336 if (VarStoreHeader
->Signature
== 0xffffffff &&
337 VarStoreHeader
->Size
== 0xffffffff &&
338 VarStoreHeader
->Format
== 0xff &&
339 VarStoreHeader
->State
== 0xff
350 CompareWithValidVariable (
351 IN VARIABLE_HEADER
*Variable
,
352 IN CONST CHAR16
*VariableName
,
353 IN CONST EFI_GUID
*VendorGuid
,
354 OUT VARIABLE_POINTER_TRACK
*PtrTrack
360 This function compares a variable with variable entries in database
364 Variable - Pointer to the variable in our database
365 VariableName - Name of the variable to compare to 'Variable'
366 VendorGuid - GUID of the variable to compare to 'Variable'
367 PtrTrack - Variable Track Pointer structure that contains
368 Variable Information.
372 EFI_SUCCESS - Found match variable
373 EFI_NOT_FOUND - Variable not found
379 if (VariableName
[0] == 0) {
380 PtrTrack
->CurrPtr
= Variable
;
384 // Don't use CompareGuid function here for performance reasons.
385 // Instead we compare the GUID a UINT32 at a time and branch
386 // on the first failed comparison.
388 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
389 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
390 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
391 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
393 ASSERT (NameSizeOfVariable (Variable
) != 0);
394 Point
= (VOID
*) GetVariableNamePtr (Variable
);
395 if (!CompareMem (VariableName
, Point
, NameSizeOfVariable (Variable
))) {
396 PtrTrack
->CurrPtr
= Variable
;
402 return EFI_NOT_FOUND
;
409 IN EFI_PEI_SERVICES
**PeiServices
,
410 IN CONST CHAR16
*VariableName
,
411 IN CONST EFI_GUID
*VendorGuid
,
412 OUT VARIABLE_POINTER_TRACK
*PtrTrack
418 This code finds variable in storage blocks (Non-Volatile)
422 PeiServices - General purpose services available to every PEIM.
423 VariableName - Name of the variable to be found
424 VendorGuid - Vendor GUID to be found.
425 PtrTrack - Variable Track Pointer structure that contains
426 Variable Information.
430 EFI_SUCCESS - Variable found successfully
431 EFI_NOT_FOUND - Variable not found
432 EFI_INVALID_PARAMETER - Invalid variable name
436 EFI_HOB_GUID_TYPE
*GuidHob
;
437 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
438 VARIABLE_HEADER
*Variable
;
439 VARIABLE_HEADER
*MaxIndex
;
440 VARIABLE_INDEX_TABLE
*IndexTable
;
444 if (VariableName
!= 0 && VendorGuid
== NULL
) {
445 return EFI_INVALID_PARAMETER
;
448 // No Variable Address equals zero, so 0 as initial value is safe.
452 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
453 if (GuidHob
== NULL
) {
454 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
455 IndexTable
->Length
= 0;
456 IndexTable
->StartPtr
= NULL
;
457 IndexTable
->EndPtr
= NULL
;
458 IndexTable
->GoneThrough
= 0;
460 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
461 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
463 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
465 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
466 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
467 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
473 if (IndexTable
->GoneThrough
) {
474 return EFI_NOT_FOUND
;
478 // If not found in HOB, then let's start from the MaxIndex we've found.
480 if (MaxIndex
!= NULL
) {
481 Variable
= GetNextVariablePtr (MaxIndex
);
483 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
484 Variable
= IndexTable
->StartPtr
;
486 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
487 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
488 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
490 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
491 return EFI_UNSUPPORTED
;
494 if (~VariableStoreHeader
->Size
== 0) {
495 return EFI_NOT_FOUND
;
498 // Find the variable by walk through non-volatile variable store
500 IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
501 IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
504 // Start Pointers for the variable.
505 // Actual Data Pointer where data can be written.
507 Variable
= IndexTable
->StartPtr
;
511 // Find the variable by walk through non-volatile variable store
513 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
514 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
516 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
517 if (Variable
->State
== VAR_ADDED
) {
519 // Record Variable in VariableIndex HOB
521 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
523 VariableIndexTableUpdate (IndexTable
, Variable
);
526 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
531 Variable
= GetNextVariablePtr (Variable
);
534 // If gone through the VariableStore, that means we never find in Firmware any more.
536 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
537 IndexTable
->GoneThrough
= 1;
540 PtrTrack
->CurrPtr
= NULL
;
542 return EFI_NOT_FOUND
;
548 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
549 IN CONST CHAR16
*VariableName
,
550 IN CONST EFI_GUID
*VariableGuid
,
551 OUT UINT32
*Attributes
,
552 IN OUT UINTN
*DataSize
,
559 Provide the read variable functionality of the variable services.
563 PeiServices - General purpose services available to every PEIM.
565 VariableName - The variable name
567 VendorGuid - The vendor's GUID
569 Attributes - Pointer to the attribute
571 DataSize - Size of data
573 Data - Pointer to data
577 EFI_SUCCESS - The interface could be successfully installed
579 EFI_NOT_FOUND - The variable could not be discovered
581 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
585 VARIABLE_POINTER_TRACK Variable
;
588 EFI_PEI_SERVICES
**PeiServices
;
590 PeiServices
= GetPeiServicesTablePointer ();
591 if (VariableName
== NULL
|| VariableGuid
== NULL
|| DataSize
== NULL
) {
592 return EFI_INVALID_PARAMETER
;
595 // Find existing variable
597 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
598 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
604 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
605 if (*DataSize
>= VarDataSize
) {
607 // PO-TKW: Address one checking in this place
610 return EFI_INVALID_PARAMETER
;
613 (*PeiServices
)->CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
615 if (Attributes
!= NULL
) {
616 *Attributes
= Variable
.CurrPtr
->Attributes
;
619 *DataSize
= VarDataSize
;
622 *DataSize
= VarDataSize
;
623 return EFI_BUFFER_TOO_SMALL
;
629 PeiGetNextVariableName (
630 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
631 IN OUT UINTN
*VariableNameSize
,
632 IN OUT CHAR16
*VariableName
,
633 IN OUT EFI_GUID
*VariableGuid
639 Provide the get next variable functionality of the variable services.
643 PeiServices - General purpose services available to every PEIM.
644 VariabvleNameSize - The variable name's size.
645 VariableName - A pointer to the variable's name.
646 VariableGuid - A pointer to the EFI_GUID structure.
648 VariableNameSize - Size of the variable name
650 VariableName - The variable name
652 VendorGuid - The vendor's GUID
656 EFI_SUCCESS - The interface could be successfully installed
658 EFI_NOT_FOUND - The variable could not be discovered
662 VARIABLE_POINTER_TRACK Variable
;
665 EFI_PEI_SERVICES
**PeiServices
;
667 PeiServices
= GetPeiServicesTablePointer ();
668 if (VariableName
== NULL
|| VariableGuid
== NULL
|| VariableNameSize
== NULL
) {
669 return EFI_INVALID_PARAMETER
;
672 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
673 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
677 if (VariableName
[0] != 0) {
679 // If variable name is not NULL, get next variable
681 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
684 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
685 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
686 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
687 ASSERT (NameSizeOfVariable (Variable
.CurrPtr
) != 0);
689 VarNameSize
= (UINTN
) NameSizeOfVariable (Variable
.CurrPtr
);
690 if (VarNameSize
<= *VariableNameSize
) {
691 (*PeiServices
)->CopyMem (VariableName
, GetVariableNamePtr (Variable
.CurrPtr
), VarNameSize
);
693 (*PeiServices
)->CopyMem (VariableGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
695 Status
= EFI_SUCCESS
;
697 Status
= EFI_BUFFER_TOO_SMALL
;
700 *VariableNameSize
= VarNameSize
;
706 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
713 return EFI_NOT_FOUND
;