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 static EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi
= {
26 PeiGetNextVariableName
29 static 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
);
123 IsValidVariableHeader (
124 IN VARIABLE_HEADER
*Variable
130 This code checks if variable header is valid or not.
133 Variable Pointer to the Variable Header.
136 TRUE Variable header is valid.
137 FALSE Variable header is not valid.
141 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
151 IN VARIABLE_HEADER
*Variable
157 This code gets the size of name of variable.
161 Variable Pointer to the Variable Header.
165 UINTN Size of variable in bytes
169 if (Variable
->State
== (UINT8
) (-1) ||
170 Variable
->DataSize
== (UINT32
) -1 ||
171 Variable
->NameSize
== (UINT32
) -1 ||
172 Variable
->Attributes
== (UINT32
) -1) {
175 return (UINTN
) Variable
->NameSize
;
180 IN VARIABLE_HEADER
*Variable
186 This code gets the size of name of variable.
190 Variable Pointer to the Variable Header.
194 UINTN Size of variable in bytes
198 if (Variable
->State
== (UINT8
) -1 ||
199 Variable
->DataSize
== (UINT32
) -1 ||
200 Variable
->NameSize
== (UINT32
) -1 ||
201 Variable
->Attributes
== (UINT32
) -1) {
204 return (UINTN
) Variable
->DataSize
;
209 IN VARIABLE_HEADER
*Variable
215 This code gets the pointer to the variable name.
219 Variable Pointer to the Variable Header.
223 CHAR16* Pointer to Variable Name
228 return (CHAR16
*) (Variable
+ 1);
234 IN VARIABLE_HEADER
*Variable
240 This code gets the pointer to the variable data.
244 Variable Pointer to the Variable Header.
248 UINT8* Pointer to Variable Data
255 // Be careful about pad size for alignment
257 Value
= (UINTN
) GetVariableNamePtr (Variable
);
258 Value
+= NameSizeOfVariable (Variable
);
259 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
261 return (UINT8
*) Value
;
266 IN VARIABLE_HEADER
*Variable
272 This code gets the pointer to the next variable header.
276 Variable Pointer to the Variable Header.
280 VARIABLE_HEADER* Pointer to next variable header.
286 if (!IsValidVariableHeader (Variable
)) {
290 Value
= (UINTN
) GetVariableDataPtr (Variable
);
291 Value
+= DataSizeOfVariable (Variable
);
292 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
295 // Be careful about pad size for alignment
297 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
302 VARIABLE_STORE_STATUS
304 GetVariableStoreStatus (
305 IN VARIABLE_STORE_HEADER
*VarStoreHeader
311 This code gets the pointer to the variable name.
315 VarStoreHeader Pointer to the Variable Store Header.
319 EfiRaw Variable store is raw
320 EfiValid Variable store is valid
321 EfiInvalid Variable store is invalid
325 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
326 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
327 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
333 if (VarStoreHeader
->Signature
== 0xffffffff &&
334 VarStoreHeader
->Size
== 0xffffffff &&
335 VarStoreHeader
->Format
== 0xff &&
336 VarStoreHeader
->State
== 0xff
347 CompareWithValidVariable (
348 IN VARIABLE_HEADER
*Variable
,
349 IN CONST CHAR16
*VariableName
,
350 IN CONST EFI_GUID
*VendorGuid
,
351 OUT VARIABLE_POINTER_TRACK
*PtrTrack
357 This function compares a variable with variable entries in database
361 Variable - Pointer to the variable in our database
362 VariableName - Name of the variable to compare to 'Variable'
363 VendorGuid - GUID of the variable to compare to 'Variable'
364 PtrTrack - Variable Track Pointer structure that contains
365 Variable Information.
369 EFI_SUCCESS - Found match variable
370 EFI_NOT_FOUND - Variable not found
376 if (VariableName
[0] == 0) {
377 PtrTrack
->CurrPtr
= Variable
;
381 // Don't use CompareGuid function here for performance reasons.
382 // Instead we compare the GUID a UINT32 at a time and branch
383 // on the first failed comparison.
385 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
386 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
387 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
388 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
390 ASSERT (NameSizeOfVariable (Variable
) != 0);
391 Point
= (VOID
*) GetVariableNamePtr (Variable
);
392 if (!CompareMem (VariableName
, Point
, NameSizeOfVariable (Variable
))) {
393 PtrTrack
->CurrPtr
= Variable
;
399 return EFI_NOT_FOUND
;
406 IN CONST EFI_PEI_SERVICES
**PeiServices
,
407 IN CONST CHAR16
*VariableName
,
408 IN CONST EFI_GUID
*VendorGuid
,
409 OUT VARIABLE_POINTER_TRACK
*PtrTrack
415 This code finds variable in storage blocks (Non-Volatile)
419 PeiServices - General purpose services available to every PEIM.
420 VariableName - Name of the variable to be found
421 VendorGuid - Vendor GUID to be found.
422 PtrTrack - Variable Track Pointer structure that contains
423 Variable Information.
427 EFI_SUCCESS - Variable found successfully
428 EFI_NOT_FOUND - Variable not found
429 EFI_INVALID_PARAMETER - Invalid variable name
433 EFI_HOB_GUID_TYPE
*GuidHob
;
434 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
435 VARIABLE_HEADER
*Variable
;
436 VARIABLE_HEADER
*MaxIndex
;
437 VARIABLE_INDEX_TABLE
*IndexTable
;
441 if (VariableName
!= 0 && VendorGuid
== NULL
) {
442 return EFI_INVALID_PARAMETER
;
445 // No Variable Address equals zero, so 0 as initial value is safe.
449 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
450 if (GuidHob
== NULL
) {
451 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
452 IndexTable
->Length
= 0;
453 IndexTable
->StartPtr
= NULL
;
454 IndexTable
->EndPtr
= NULL
;
455 IndexTable
->GoneThrough
= 0;
457 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
458 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
460 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
462 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
463 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
464 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
470 if (IndexTable
->GoneThrough
) {
471 return EFI_NOT_FOUND
;
475 // If not found in HOB, then let's start from the MaxIndex we've found.
477 if (MaxIndex
!= NULL
) {
478 Variable
= GetNextVariablePtr (MaxIndex
);
480 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
481 Variable
= IndexTable
->StartPtr
;
483 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
484 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
485 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
487 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
488 return EFI_UNSUPPORTED
;
491 if (~VariableStoreHeader
->Size
== 0) {
492 return EFI_NOT_FOUND
;
495 // Find the variable by walk through non-volatile variable store
497 IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
498 IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
501 // Start Pointers for the variable.
502 // Actual Data Pointer where data can be written.
504 Variable
= IndexTable
->StartPtr
;
508 // Find the variable by walk through non-volatile variable store
510 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
511 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
513 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
514 if (Variable
->State
== VAR_ADDED
) {
516 // Record Variable in VariableIndex HOB
518 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
520 VariableIndexTableUpdate (IndexTable
, Variable
);
523 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
528 Variable
= GetNextVariablePtr (Variable
);
531 // If gone through the VariableStore, that means we never find in Firmware any more.
533 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
534 IndexTable
->GoneThrough
= 1;
537 PtrTrack
->CurrPtr
= NULL
;
539 return EFI_NOT_FOUND
;
545 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
546 IN CONST CHAR16
*VariableName
,
547 IN CONST EFI_GUID
*VariableGuid
,
548 OUT UINT32
*Attributes
,
549 IN OUT UINTN
*DataSize
,
556 Provide the read variable functionality of the variable services.
560 PeiServices - General purpose services available to every PEIM.
562 VariableName - The variable name
564 VendorGuid - The vendor's GUID
566 Attributes - Pointer to the attribute
568 DataSize - Size of data
570 Data - Pointer to data
574 EFI_SUCCESS - The interface could be successfully installed
576 EFI_NOT_FOUND - The variable could not be discovered
578 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
582 VARIABLE_POINTER_TRACK Variable
;
585 CONST EFI_PEI_SERVICES
**PeiServices
;
587 PeiServices
= GetPeiServicesTablePointer ();
588 if (VariableName
== NULL
|| VariableGuid
== NULL
|| DataSize
== NULL
) {
589 return EFI_INVALID_PARAMETER
;
592 // Find existing variable
594 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
595 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
601 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
602 if (*DataSize
>= VarDataSize
) {
604 // PO-TKW: Address one checking in this place
607 return EFI_INVALID_PARAMETER
;
610 (*PeiServices
)->CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
612 if (Attributes
!= NULL
) {
613 *Attributes
= Variable
.CurrPtr
->Attributes
;
616 *DataSize
= VarDataSize
;
619 *DataSize
= VarDataSize
;
620 return EFI_BUFFER_TOO_SMALL
;
626 PeiGetNextVariableName (
627 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
628 IN OUT UINTN
*VariableNameSize
,
629 IN OUT CHAR16
*VariableName
,
630 IN OUT EFI_GUID
*VariableGuid
636 Provide the get next variable functionality of the variable services.
640 PeiServices - General purpose services available to every PEIM.
641 VariabvleNameSize - The variable name's size.
642 VariableName - A pointer to the variable's name.
643 VariableGuid - A pointer to the EFI_GUID structure.
645 VariableNameSize - Size of the variable name
647 VariableName - The variable name
649 VendorGuid - The vendor's GUID
653 EFI_SUCCESS - The interface could be successfully installed
655 EFI_NOT_FOUND - The variable could not be discovered
659 VARIABLE_POINTER_TRACK Variable
;
662 CONST EFI_PEI_SERVICES
**PeiServices
;
664 PeiServices
= GetPeiServicesTablePointer ();
665 if (VariableName
== NULL
|| VariableGuid
== NULL
|| VariableNameSize
== NULL
) {
666 return EFI_INVALID_PARAMETER
;
669 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
670 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
674 if (VariableName
[0] != 0) {
676 // If variable name is not NULL, get next variable
678 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
681 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
682 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
683 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
684 ASSERT (NameSizeOfVariable (Variable
.CurrPtr
) != 0);
686 VarNameSize
= (UINTN
) NameSizeOfVariable (Variable
.CurrPtr
);
687 if (VarNameSize
<= *VariableNameSize
) {
688 (*PeiServices
)->CopyMem (VariableName
, GetVariableNamePtr (Variable
.CurrPtr
), VarNameSize
);
690 (*PeiServices
)->CopyMem (VariableGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
692 Status
= EFI_SUCCESS
;
694 Status
= EFI_BUFFER_TOO_SMALL
;
697 *VariableNameSize
= VarNameSize
;
703 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
710 return EFI_NOT_FOUND
;