3 Implement ReadOnly Variable Services required by PEIM and install
4 PI ReadOnly Varaiable2 PPI. These services operates the non volatile storage space.
6 Copyright (c) 2006 - 2008 Intel Corporation. <BR>
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
24 EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi
= {
26 PeiGetNextVariableName
29 EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
= {
30 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
31 &gEfiPeiReadOnlyVariable2PpiGuid
,
35 EFI_GUID mEfiVariableIndexTableGuid
= EFI_VARIABLE_INDEX_TABLE_GUID
;
39 PeimInitializeVariableServices (
40 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
41 IN EFI_PEI_SERVICES
**PeiServices
47 Provide the functionality of the variable services.
51 FfsHeadher - The FFS file header
52 PeiServices - General purpose services available to every PEIM.
56 Status - EFI_SUCCESS if the interface could be successfully
62 // Publish the variable capability to other modules
64 return (**PeiServices
).InstallPpi ((CONST EFI_PEI_SERVICES
**)PeiServices
, &mPpiListVariable
);
70 IN VARIABLE_STORE_HEADER
*VarStoreHeader
76 This code gets the pointer to the first variable memory pointer byte
80 VarStoreHeader Pointer to the Variable Store Header.
84 VARIABLE_HEADER* Pointer to last unavailable Variable Header
89 // The end of variable store
91 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
96 IN VARIABLE_STORE_HEADER
*VarStoreHeader
102 This code gets the pointer to the last variable memory pointer byte
106 VarStoreHeader Pointer to the Variable Store Header.
110 VARIABLE_HEADER* Pointer to last unavailable Variable Header
115 // The end of variable store
117 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
122 IsValidVariableHeader (
123 IN VARIABLE_HEADER
*Variable
129 This code checks if variable header is valid or not.
132 Variable Pointer to the Variable Header.
135 TRUE Variable header is valid.
136 FALSE Variable header is not valid.
140 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
150 IN VARIABLE_HEADER
*Variable
156 This code gets the size of name of variable.
160 Variable Pointer to the Variable Header.
164 UINTN Size of variable in bytes
168 if (Variable
->State
== (UINT8
) (-1) ||
169 Variable
->DataSize
== (UINT32
) -1 ||
170 Variable
->NameSize
== (UINT32
) -1 ||
171 Variable
->Attributes
== (UINT32
) -1) {
174 return (UINTN
) Variable
->NameSize
;
179 IN VARIABLE_HEADER
*Variable
185 This code gets the size of name of variable.
189 Variable Pointer to the Variable Header.
193 UINTN Size of variable in bytes
197 if (Variable
->State
== (UINT8
) -1 ||
198 Variable
->DataSize
== (UINT32
) -1 ||
199 Variable
->NameSize
== (UINT32
) -1 ||
200 Variable
->Attributes
== (UINT32
) -1) {
203 return (UINTN
) Variable
->DataSize
;
208 IN VARIABLE_HEADER
*Variable
214 This code gets the pointer to the variable name.
218 Variable Pointer to the Variable Header.
222 CHAR16* Pointer to Variable Name
227 return (CHAR16
*) (Variable
+ 1);
233 IN VARIABLE_HEADER
*Variable
239 This code gets the pointer to the variable data.
243 Variable Pointer to the Variable Header.
247 UINT8* Pointer to Variable Data
254 // Be careful about pad size for alignment
256 Value
= (UINTN
) GetVariableNamePtr (Variable
);
257 Value
+= NameSizeOfVariable (Variable
);
258 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
260 return (UINT8
*) Value
;
265 IN VARIABLE_HEADER
*Variable
271 This code gets the pointer to the next variable header.
275 Variable Pointer to the Variable Header.
279 VARIABLE_HEADER* Pointer to next variable header.
285 if (!IsValidVariableHeader (Variable
)) {
289 Value
= (UINTN
) GetVariableDataPtr (Variable
);
290 Value
+= DataSizeOfVariable (Variable
);
291 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
294 // Be careful about pad size for alignment
296 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
300 VARIABLE_STORE_STATUS
302 GetVariableStoreStatus (
303 IN VARIABLE_STORE_HEADER
*VarStoreHeader
309 This code gets the pointer to the variable name.
313 VarStoreHeader Pointer to the Variable Store Header.
317 EfiRaw Variable store is raw
318 EfiValid Variable store is valid
319 EfiInvalid Variable store is invalid
323 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
324 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
325 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
331 if (VarStoreHeader
->Signature
== 0xffffffff &&
332 VarStoreHeader
->Size
== 0xffffffff &&
333 VarStoreHeader
->Format
== 0xff &&
334 VarStoreHeader
->State
== 0xff
344 CompareWithValidVariable (
345 IN VARIABLE_HEADER
*Variable
,
346 IN CONST CHAR16
*VariableName
,
347 IN CONST EFI_GUID
*VendorGuid
,
348 OUT VARIABLE_POINTER_TRACK
*PtrTrack
354 This function compares a variable with variable entries in database
358 Variable - Pointer to the variable in our database
359 VariableName - Name of the variable to compare to 'Variable'
360 VendorGuid - GUID of the variable to compare to 'Variable'
361 PtrTrack - Variable Track Pointer structure that contains
362 Variable Information.
366 EFI_SUCCESS - Found match variable
367 EFI_NOT_FOUND - Variable not found
373 if (VariableName
[0] == 0) {
374 PtrTrack
->CurrPtr
= Variable
;
378 // Don't use CompareGuid function here for performance reasons.
379 // Instead we compare the GUID a UINT32 at a time and branch
380 // on the first failed comparison.
382 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
383 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
384 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
385 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
387 ASSERT (NameSizeOfVariable (Variable
) != 0);
388 Point
= (VOID
*) GetVariableNamePtr (Variable
);
389 if (!CompareMem (VariableName
, Point
, NameSizeOfVariable (Variable
))) {
390 PtrTrack
->CurrPtr
= Variable
;
396 return EFI_NOT_FOUND
;
402 IN CONST EFI_PEI_SERVICES
**PeiServices
,
403 IN CONST CHAR16
*VariableName
,
404 IN CONST EFI_GUID
*VendorGuid
,
405 OUT VARIABLE_POINTER_TRACK
*PtrTrack
411 This code finds variable in storage blocks (Non-Volatile)
415 PeiServices - General purpose services available to every PEIM.
416 VariableName - Name of the variable to be found
417 VendorGuid - Vendor GUID to be found.
418 PtrTrack - Variable Track Pointer structure that contains
419 Variable Information.
423 EFI_SUCCESS - Variable found successfully
424 EFI_NOT_FOUND - Variable not found
425 EFI_INVALID_PARAMETER - Invalid variable name
429 EFI_HOB_GUID_TYPE
*GuidHob
;
430 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
431 VARIABLE_HEADER
*Variable
;
432 VARIABLE_HEADER
*MaxIndex
;
433 VARIABLE_INDEX_TABLE
*IndexTable
;
437 if (VariableName
!= 0 && VendorGuid
== NULL
) {
438 return EFI_INVALID_PARAMETER
;
441 // No Variable Address equals zero, so 0 as initial value is safe.
445 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
446 if (GuidHob
== NULL
) {
447 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
448 IndexTable
->Length
= 0;
449 IndexTable
->StartPtr
= NULL
;
450 IndexTable
->EndPtr
= NULL
;
451 IndexTable
->GoneThrough
= 0;
453 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
454 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
456 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
458 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
459 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
460 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
466 if (IndexTable
->GoneThrough
) {
467 return EFI_NOT_FOUND
;
471 // If not found in HOB, then let's start from the MaxIndex we've found.
473 if (MaxIndex
!= NULL
) {
474 Variable
= GetNextVariablePtr (MaxIndex
);
476 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
477 Variable
= IndexTable
->StartPtr
;
479 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
480 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
481 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
483 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
484 return EFI_UNSUPPORTED
;
487 if (~VariableStoreHeader
->Size
== 0) {
488 return EFI_NOT_FOUND
;
491 // Find the variable by walk through non-volatile variable store
493 IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
494 IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
497 // Start Pointers for the variable.
498 // Actual Data Pointer where data can be written.
500 Variable
= IndexTable
->StartPtr
;
504 // Find the variable by walk through non-volatile variable store
506 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
507 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
509 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
510 if (Variable
->State
== VAR_ADDED
) {
512 // Record Variable in VariableIndex HOB
514 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
516 VariableIndexTableUpdate (IndexTable
, Variable
);
519 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
524 Variable
= GetNextVariablePtr (Variable
);
527 // If gone through the VariableStore, that means we never find in Firmware any more.
529 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
530 IndexTable
->GoneThrough
= 1;
533 PtrTrack
->CurrPtr
= NULL
;
535 return EFI_NOT_FOUND
;
541 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
542 IN CONST CHAR16
*VariableName
,
543 IN CONST EFI_GUID
*VariableGuid
,
544 OUT UINT32
*Attributes
,
545 IN OUT UINTN
*DataSize
,
552 Provide the read variable functionality of the variable services.
556 PeiServices - General purpose services available to every PEIM.
558 VariableName - The variable name
560 VendorGuid - The vendor's GUID
562 Attributes - Pointer to the attribute
564 DataSize - Size of data
566 Data - Pointer to data
570 EFI_SUCCESS - The interface could be successfully installed
572 EFI_NOT_FOUND - The variable could not be discovered
574 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
578 VARIABLE_POINTER_TRACK Variable
;
581 CONST EFI_PEI_SERVICES
**PeiServices
;
583 PeiServices
= GetPeiServicesTablePointer ();
584 if (VariableName
== NULL
|| VariableGuid
== NULL
|| DataSize
== NULL
) {
585 return EFI_INVALID_PARAMETER
;
588 // Find existing variable
590 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
591 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
597 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
598 if (*DataSize
>= VarDataSize
) {
600 // PO-TKW: Address one checking in this place
603 return EFI_INVALID_PARAMETER
;
606 (*PeiServices
)->CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
608 if (Attributes
!= NULL
) {
609 *Attributes
= Variable
.CurrPtr
->Attributes
;
612 *DataSize
= VarDataSize
;
615 *DataSize
= VarDataSize
;
616 return EFI_BUFFER_TOO_SMALL
;
622 PeiGetNextVariableName (
623 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
624 IN OUT UINTN
*VariableNameSize
,
625 IN OUT CHAR16
*VariableName
,
626 IN OUT EFI_GUID
*VariableGuid
632 Provide the get next variable functionality of the variable services.
636 PeiServices - General purpose services available to every PEIM.
637 VariabvleNameSize - The variable name's size.
638 VariableName - A pointer to the variable's name.
639 VariableGuid - A pointer to the EFI_GUID structure.
641 VariableNameSize - Size of the variable name
643 VariableName - The variable name
645 VendorGuid - The vendor's GUID
649 EFI_SUCCESS - The interface could be successfully installed
651 EFI_NOT_FOUND - The variable could not be discovered
655 VARIABLE_POINTER_TRACK Variable
;
658 CONST EFI_PEI_SERVICES
**PeiServices
;
660 PeiServices
= GetPeiServicesTablePointer ();
661 if (VariableName
== NULL
|| VariableGuid
== NULL
|| VariableNameSize
== NULL
) {
662 return EFI_INVALID_PARAMETER
;
665 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
666 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
670 if (VariableName
[0] != 0) {
672 // If variable name is not NULL, get next variable
674 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
677 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
678 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
679 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
680 ASSERT (NameSizeOfVariable (Variable
.CurrPtr
) != 0);
682 VarNameSize
= (UINTN
) NameSizeOfVariable (Variable
.CurrPtr
);
683 if (VarNameSize
<= *VariableNameSize
) {
684 (*PeiServices
)->CopyMem (VariableName
, GetVariableNamePtr (Variable
.CurrPtr
), VarNameSize
);
686 (*PeiServices
)->CopyMem (VariableGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
688 Status
= EFI_SUCCESS
;
690 Status
= EFI_BUFFER_TOO_SMALL
;
693 *VariableNameSize
= VarNameSize
;
699 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
706 return EFI_NOT_FOUND
;