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]);
86 IN VARIABLE_HEADER
*Variable
90 // Check whether the header is valid fully;
91 // Tricky: The unprogramed data in FLASH equals 0xff.
93 if (Variable
->DataSize
== (UINT32
) -1 ||
94 Variable
->Attributes
== (UINT32
) -1 ||
95 Variable
->NameSize
== (UINT32
) -1) {
98 return Variable
->NameSize
;
103 IN VARIABLE_HEADER
*Variable
107 // Check whether the header is valid fully;
108 // Tricky: The unprogramed data in FLASH equals 0xff.
110 if (Variable
->DataSize
== (UINT32
) -1 ||
111 Variable
->Attributes
== (UINT32
) -1 ||
112 Variable
->NameSize
== (UINT32
) -1) {
115 return Variable
->DataSize
;
119 AttributesOfVariable (
120 IN VARIABLE_HEADER
*Variable
125 // Check whether the header is valid fully;
126 // Tricky: The unprogramed data in FLASH equals 0xff.
128 if (Variable
->DataSize
== (UINT32
) -1 ||
129 Variable
->Attributes
== (UINT32
) -1 ||
130 Variable
->NameSize
== (UINT32
) -1) {
133 return Variable
->Attributes
;
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 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) GET_VARIABLE_DATA_PTR (Variable
) + DataSizeOfVariable (Variable
) + GET_PAD_SIZE (DataSizeOfVariable (Variable
)));
162 IsValidVariableHeader (
163 IN VARIABLE_HEADER
*Variable
169 This code checks if variable header is valid or not.
172 Variable Pointer to the Variable Header.
175 TRUE Variable header is valid.
176 FALSE Variable header is not valid.
180 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
188 VARIABLE_STORE_STATUS
190 GetVariableStoreStatus (
191 IN VARIABLE_STORE_HEADER
*VarStoreHeader
197 This code gets the pointer to the variable name.
201 VarStoreHeader Pointer to the Variable Store Header.
205 EfiRaw Variable store is raw
206 EfiValid Variable store is valid
207 EfiInvalid Variable store is invalid
211 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
212 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
213 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
219 if (VarStoreHeader
->Signature
== 0xffffffff &&
220 VarStoreHeader
->Size
== 0xffffffff &&
221 VarStoreHeader
->Format
== 0xff &&
222 VarStoreHeader
->State
== 0xff
233 CompareWithValidVariable (
234 IN VARIABLE_HEADER
*Variable
,
235 IN CONST CHAR16
*VariableName
,
236 IN CONST EFI_GUID
*VendorGuid
,
237 OUT VARIABLE_POINTER_TRACK
*PtrTrack
243 This function compares a variable with variable entries in database
247 Variable - Pointer to the variable in our database
248 VariableName - Name of the variable to compare to 'Variable'
249 VendorGuid - GUID of the variable to compare to 'Variable'
250 PtrTrack - Variable Track Pointer structure that contains
251 Variable Information.
255 EFI_SUCCESS - Found match variable
256 EFI_NOT_FOUND - Variable not found
260 if (VariableName
[0] == 0) {
261 PtrTrack
->CurrPtr
= Variable
;
265 // Don't use CompareGuid function here for performance reasons.
266 // Instead we compare the GUID a UINT32 at a time and branch
267 // on the first failed comparison.
269 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
270 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
271 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
272 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
274 ASSERT (NameSizeOfVariable (Variable
) != 0);
275 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
), NameSizeOfVariable (Variable
))) {
276 PtrTrack
->CurrPtr
= Variable
;
282 return EFI_NOT_FOUND
;
289 IN EFI_PEI_SERVICES
**PeiServices
,
290 IN CONST CHAR16
*VariableName
,
291 IN CONST EFI_GUID
*VendorGuid
,
292 OUT VARIABLE_POINTER_TRACK
*PtrTrack
298 This code finds variable in storage blocks (Non-Volatile)
302 PeiServices - General purpose services available to every PEIM.
303 VariableName - Name of the variable to be found
304 VendorGuid - Vendor GUID to be found.
305 PtrTrack - Variable Track Pointer structure that contains
306 Variable Information.
310 EFI_SUCCESS - Variable found successfully
311 EFI_NOT_FOUND - Variable not found
312 EFI_INVALID_PARAMETER - Invalid variable name
316 EFI_HOB_GUID_TYPE
*GuidHob
;
317 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
318 VARIABLE_HEADER
*Variable
;
319 VARIABLE_HEADER
*MaxIndex
;
320 VARIABLE_INDEX_TABLE
*IndexTable
;
324 if (VariableName
!= 0 && VendorGuid
== NULL
) {
325 return EFI_INVALID_PARAMETER
;
328 // No Variable Address equals zero, so 0 as initial value is safe.
332 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
333 if (GuidHob
== NULL
) {
334 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
335 IndexTable
->Length
= 0;
336 IndexTable
->StartPtr
= NULL
;
337 IndexTable
->EndPtr
= NULL
;
338 IndexTable
->GoneThrough
= 0;
340 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
341 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
343 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
344 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
345 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
346 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
352 if (IndexTable
->GoneThrough
) {
353 return EFI_NOT_FOUND
;
357 // If not found in HOB, then let's start from the MaxIndex we've found.
359 if (MaxIndex
!= NULL
) {
360 Variable
= GetNextVariablePtr (MaxIndex
);
362 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
363 Variable
= IndexTable
->StartPtr
;
365 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
366 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
367 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
369 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
370 return EFI_UNSUPPORTED
;
373 if (~VariableStoreHeader
->Size
== 0) {
374 return EFI_NOT_FOUND
;
377 // Find the variable by walk through non-volatile variable store
379 IndexTable
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
380 IndexTable
->EndPtr
= (VARIABLE_HEADER
*) ((UINTN
) VariableStoreHeader
+ VariableStoreHeader
->Size
);
383 // Start Pointers for the variable.
384 // Actual Data Pointer where data can be written.
386 Variable
= IndexTable
->StartPtr
;
390 // Find the variable by walk through non-volatile variable store
392 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
393 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
395 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
396 if (Variable
->State
== VAR_ADDED
) {
398 // Record Variable in VariableIndex HOB
400 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
402 VariableIndexTableUpdate (IndexTable
, Variable
);
405 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
410 Variable
= GetNextVariablePtr (Variable
);
413 // If gone through the VariableStore, that means we never find in Firmware any more.
415 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
416 IndexTable
->GoneThrough
= 1;
419 PtrTrack
->CurrPtr
= NULL
;
421 return EFI_NOT_FOUND
;
427 IN EFI_PEI_SERVICES
**PeiServices
,
428 IN CHAR16
*VariableName
,
429 IN EFI_GUID
* VendorGuid
,
430 OUT UINT32
*Attributes OPTIONAL
,
431 IN OUT UINTN
*DataSize
,
438 Provide the read variable functionality of the variable services.
442 PeiServices - General purpose services available to every PEIM.
444 VariableName - The variable name
446 VendorGuid - The vendor's GUID
448 Attributes - Pointer to the attribute
450 DataSize - Size of data
452 Data - Pointer to data
456 EFI_SUCCESS - The interface could be successfully installed
458 EFI_NOT_FOUND - The variable could not be discovered
460 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
464 VARIABLE_POINTER_TRACK Variable
;
468 if (VariableName
== NULL
|| VendorGuid
== NULL
) {
469 return EFI_INVALID_PARAMETER
;
472 // Find existing variable
474 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
476 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
482 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
483 if (*DataSize
>= VarDataSize
) {
484 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
486 if (Attributes
!= NULL
) {
487 *Attributes
= Variable
.CurrPtr
->Attributes
;
490 *DataSize
= VarDataSize
;
493 *DataSize
= VarDataSize
;
494 return EFI_BUFFER_TOO_SMALL
;
502 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
503 IN CONST CHAR16
*VariableName
,
504 IN CONST EFI_GUID
*VariableGuid
,
505 OUT UINT32
*Attributes
,
506 IN OUT UINTN
*DataSize
,
513 Provide the read variable functionality of the variable services.
517 PeiServices - General purpose services available to every PEIM.
519 VariableName - The variable name
521 VendorGuid - The vendor's GUID
523 Attributes - Pointer to the attribute
525 DataSize - Size of data
527 Data - Pointer to data
531 EFI_SUCCESS - The interface could be successfully installed
533 EFI_NOT_FOUND - The variable could not be discovered
535 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
539 return PeiGetVariable (
540 GetPeiServicesTablePointer (),
541 (CHAR16
*)VariableName
,
542 (EFI_GUID
*)VariableGuid
,
551 PeiGetNextVariableName (
552 IN EFI_PEI_SERVICES
**PeiServices
,
553 IN OUT UINTN
*VariableNameSize
,
554 IN OUT CHAR16
*VariableName
,
555 IN OUT EFI_GUID
*VendorGuid
561 Provide the get next variable functionality of the variable services.
565 PeiServices - General purpose services available to every PEIM.
566 VariabvleNameSize - The variable name's size.
567 VariableName - A pointer to the variable's name.
568 VendorGuid - A pointer to the EFI_GUID structure.
570 VariableNameSize - Size of the variable name
572 VariableName - The variable name
574 VendorGuid - The vendor's GUID
578 EFI_SUCCESS - The interface could be successfully installed
580 EFI_NOT_FOUND - The variable could not be discovered
584 VARIABLE_POINTER_TRACK Variable
;
588 if (VariableName
== NULL
) {
589 return EFI_INVALID_PARAMETER
;
592 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
594 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
598 if (VariableName
[0] != 0) {
600 // If variable name is not NULL, get next variable
602 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
605 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
606 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
607 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
608 ASSERT (NameSizeOfVariable (Variable
.CurrPtr
) != 0);
610 VarNameSize
= (UINTN
) NameSizeOfVariable (Variable
.CurrPtr
);
611 if (VarNameSize
<= *VariableNameSize
) {
612 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
614 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
616 Status
= EFI_SUCCESS
;
618 Status
= EFI_BUFFER_TOO_SMALL
;
621 *VariableNameSize
= VarNameSize
;
627 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
634 return EFI_NOT_FOUND
;
639 PeiGetNextVariableName2 (
640 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
641 IN OUT UINTN
*VariableNameSize
,
642 IN OUT CHAR16
*VariableName
,
643 IN OUT EFI_GUID
*VariableGuid
649 Provide the get next variable functionality of the variable services.
653 PeiServices - General purpose services available to every PEIM.
654 VariabvleNameSize - The variable name's size.
655 VariableName - A pointer to the variable's name.
656 VariableGuid - A pointer to the EFI_GUID structure.
658 VariableNameSize - Size of the variable name
660 VariableName - The variable name
662 VendorGuid - The vendor's GUID
666 EFI_SUCCESS - The interface could be successfully installed
668 EFI_NOT_FOUND - The variable could not be discovered
672 return PeiGetNextVariableName (
673 GetPeiServicesTablePointer (),