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 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
);
125 IN VARIABLE_HEADER
*Variable
129 // Check whether the header is valid fully;
130 // Tricky: The unprogramed data in FLASH equals 0xff.
132 if (Variable
->DataSize
== (UINT32
) -1 ||
133 Variable
->Attributes
== (UINT32
) -1 ||
134 Variable
->NameSize
== (UINT32
) -1) {
137 return Variable
->NameSize
;
142 IN VARIABLE_HEADER
*Variable
146 // Check whether the header is valid fully;
147 // Tricky: The unprogramed data in FLASH equals 0xff.
149 if (Variable
->DataSize
== (UINT32
) -1 ||
150 Variable
->Attributes
== (UINT32
) -1 ||
151 Variable
->NameSize
== (UINT32
) -1) {
154 return Variable
->DataSize
;
158 AttributesOfVariable (
159 IN VARIABLE_HEADER
*Variable
164 // Check whether the header is valid fully;
165 // Tricky: The unprogramed data in FLASH equals 0xff.
167 if (Variable
->DataSize
== (UINT32
) -1 ||
168 Variable
->Attributes
== (UINT32
) -1 ||
169 Variable
->NameSize
== (UINT32
) -1) {
172 return Variable
->Attributes
;
179 IN VARIABLE_HEADER
*Variable
185 This code checks if variable header is valid or not.
188 Variable Pointer to the Variable Header.
191 TRUE Variable header is valid.
192 FALSE Variable header is not valid.
196 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) GET_VARIABLE_DATA_PTR (Variable
) + DataSizeOfVariable (Variable
) + GET_PAD_SIZE (DataSizeOfVariable (Variable
)));
202 IsValidVariableHeader (
203 IN VARIABLE_HEADER
*Variable
209 This code checks if variable header is valid or not.
212 Variable Pointer to the Variable Header.
215 TRUE Variable header is valid.
216 FALSE Variable header is not valid.
220 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
228 VARIABLE_STORE_STATUS
230 GetVariableStoreStatus (
231 IN VARIABLE_STORE_HEADER
*VarStoreHeader
237 This code gets the pointer to the variable name.
241 VarStoreHeader Pointer to the Variable Store Header.
245 EfiRaw Variable store is raw
246 EfiValid Variable store is valid
247 EfiInvalid Variable store is invalid
251 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
252 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
253 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
259 if (VarStoreHeader
->Signature
== 0xffffffff &&
260 VarStoreHeader
->Size
== 0xffffffff &&
261 VarStoreHeader
->Format
== 0xff &&
262 VarStoreHeader
->State
== 0xff
273 CompareWithValidVariable (
274 IN VARIABLE_HEADER
*Variable
,
275 IN CONST CHAR16
*VariableName
,
276 IN CONST EFI_GUID
*VendorGuid
,
277 OUT VARIABLE_POINTER_TRACK
*PtrTrack
283 This function compares a variable with variable entries in database
287 Variable - Pointer to the variable in our database
288 VariableName - Name of the variable to compare to 'Variable'
289 VendorGuid - GUID of the variable to compare to 'Variable'
290 PtrTrack - Variable Track Pointer structure that contains
291 Variable Information.
295 EFI_SUCCESS - Found match variable
296 EFI_NOT_FOUND - Variable not found
300 if (VariableName
[0] == 0) {
301 PtrTrack
->CurrPtr
= Variable
;
305 // Don't use CompareGuid function here for performance reasons.
306 // Instead we compare the GUID a UINT32 at a time and branch
307 // on the first failed comparison.
309 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
310 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
311 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
312 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
314 ASSERT (NameSizeOfVariable (Variable
) != 0);
315 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
), NameSizeOfVariable (Variable
))) {
316 PtrTrack
->CurrPtr
= Variable
;
322 return EFI_NOT_FOUND
;
329 IN EFI_PEI_SERVICES
**PeiServices
,
330 IN CONST CHAR16
*VariableName
,
331 IN CONST EFI_GUID
*VendorGuid
,
332 OUT VARIABLE_POINTER_TRACK
*PtrTrack
338 This code finds variable in storage blocks (Non-Volatile)
342 PeiServices - General purpose services available to every PEIM.
343 VariableName - Name of the variable to be found
344 VendorGuid - Vendor GUID to be found.
345 PtrTrack - Variable Track Pointer structure that contains
346 Variable Information.
350 EFI_SUCCESS - Variable found successfully
351 EFI_NOT_FOUND - Variable not found
352 EFI_INVALID_PARAMETER - Invalid variable name
356 EFI_HOB_GUID_TYPE
*GuidHob
;
357 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
358 VARIABLE_HEADER
*Variable
;
359 VARIABLE_HEADER
*MaxIndex
;
360 VARIABLE_INDEX_TABLE
*IndexTable
;
364 if (VariableName
!= 0 && VendorGuid
== NULL
) {
365 return EFI_INVALID_PARAMETER
;
368 // No Variable Address equals zero, so 0 as initial value is safe.
372 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
373 if (GuidHob
== NULL
) {
374 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
375 IndexTable
->Length
= 0;
376 IndexTable
->StartPtr
= NULL
;
377 IndexTable
->EndPtr
= NULL
;
378 IndexTable
->GoneThrough
= 0;
380 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
381 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
383 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
385 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
386 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
387 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
393 if (IndexTable
->GoneThrough
) {
394 return EFI_NOT_FOUND
;
398 // If not found in HOB, then let's start from the MaxIndex we've found.
400 if (MaxIndex
!= NULL
) {
401 Variable
= GetNextVariablePtr (MaxIndex
);
403 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
404 Variable
= IndexTable
->StartPtr
;
406 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
407 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
408 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
410 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
411 return EFI_UNSUPPORTED
;
414 if (~VariableStoreHeader
->Size
== 0) {
415 return EFI_NOT_FOUND
;
418 // Find the variable by walk through non-volatile variable store
420 IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
421 IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
424 // Start Pointers for the variable.
425 // Actual Data Pointer where data can be written.
427 Variable
= IndexTable
->StartPtr
;
431 // Find the variable by walk through non-volatile variable store
433 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
434 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
436 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
437 if (Variable
->State
== VAR_ADDED
) {
439 // Record Variable in VariableIndex HOB
441 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
443 VariableIndexTableUpdate (IndexTable
, Variable
);
446 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
451 Variable
= GetNextVariablePtr (Variable
);
454 // If gone through the VariableStore, that means we never find in Firmware any more.
456 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
457 IndexTable
->GoneThrough
= 1;
460 PtrTrack
->CurrPtr
= NULL
;
462 return EFI_NOT_FOUND
;
468 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
469 IN CONST CHAR16
*VariableName
,
470 IN CONST EFI_GUID
*VariableGuid
,
471 OUT UINT32
*Attributes
,
472 IN OUT UINTN
*DataSize
,
479 Provide the read variable functionality of the variable services.
483 PeiServices - General purpose services available to every PEIM.
485 VariableName - The variable name
487 VendorGuid - The vendor's GUID
489 Attributes - Pointer to the attribute
491 DataSize - Size of data
493 Data - Pointer to data
497 EFI_SUCCESS - The interface could be successfully installed
499 EFI_NOT_FOUND - The variable could not be discovered
501 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
505 VARIABLE_POINTER_TRACK Variable
;
508 EFI_PEI_SERVICES
**PeiServices
;
510 PeiServices
= GetPeiServicesTablePointer ();
511 if (VariableName
== NULL
|| VariableGuid
== NULL
) {
512 return EFI_INVALID_PARAMETER
;
515 // Find existing variable
517 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
518 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
524 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
525 if (*DataSize
>= VarDataSize
) {
526 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
528 if (Attributes
!= NULL
) {
529 *Attributes
= Variable
.CurrPtr
->Attributes
;
532 *DataSize
= VarDataSize
;
535 *DataSize
= VarDataSize
;
536 return EFI_BUFFER_TOO_SMALL
;
542 PeiGetNextVariableName (
543 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
544 IN OUT UINTN
*VariableNameSize
,
545 IN OUT CHAR16
*VariableName
,
546 IN OUT EFI_GUID
*VariableGuid
552 Provide the get next variable functionality of the variable services.
556 PeiServices - General purpose services available to every PEIM.
557 VariabvleNameSize - The variable name's size.
558 VariableName - A pointer to the variable's name.
559 VariableGuid - A pointer to the EFI_GUID structure.
561 VariableNameSize - Size of the variable name
563 VariableName - The variable name
565 VendorGuid - The vendor's GUID
569 EFI_SUCCESS - The interface could be successfully installed
571 EFI_NOT_FOUND - The variable could not be discovered
575 VARIABLE_POINTER_TRACK Variable
;
578 EFI_PEI_SERVICES
**PeiServices
;
580 PeiServices
= GetPeiServicesTablePointer ();
581 if (VariableName
== NULL
) {
582 return EFI_INVALID_PARAMETER
;
585 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
586 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
590 if (VariableName
[0] != 0) {
592 // If variable name is not NULL, get next variable
594 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
597 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
598 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
599 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
600 ASSERT (NameSizeOfVariable (Variable
.CurrPtr
) != 0);
602 VarNameSize
= (UINTN
) NameSizeOfVariable (Variable
.CurrPtr
);
603 if (VarNameSize
<= *VariableNameSize
) {
604 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
606 (*PeiServices
)->CopyMem (VariableGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
608 Status
= EFI_SUCCESS
;
610 Status
= EFI_BUFFER_TOO_SMALL
;
613 *VariableNameSize
= VarNameSize
;
619 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
626 return EFI_NOT_FOUND
;