3 Copyright (c) 2006, Intel Corporation
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.
18 Framework PEIM to provide the Variable functionality
27 static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi
= {
29 PeiGetNextVariableName
32 static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
= {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
34 &gEfiPeiReadOnlyVariablePpiGuid
,
38 EFI_GUID gEfiVariableIndexTableGuid
= 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 (PeiServices
, &mPpiListVariable
);
73 IN VARIABLE_HEADER
*Variable
79 This code checks if variable header is valid or not.
82 Variable Pointer to the Variable Header.
85 TRUE Variable header is valid.
86 FALSE Variable header is not valid.
90 return (VARIABLE_HEADER
*) ((UINTN
) GET_VARIABLE_DATA_PTR (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
95 IsValidVariableHeader (
96 IN VARIABLE_HEADER
*Variable
102 This code checks if variable header is valid or not.
105 Variable Pointer to the Variable Header.
108 TRUE Variable header is valid.
109 FALSE Variable header is not valid.
113 if (Variable
== NULL
||
114 Variable
->StartId
!= VARIABLE_DATA
||
115 (sizeof (VARIABLE_HEADER
) + Variable
->DataSize
+ Variable
->NameSize
) > MAX_VARIABLE_SIZE
123 VARIABLE_STORE_STATUS
125 GetVariableStoreStatus (
126 IN VARIABLE_STORE_HEADER
*VarStoreHeader
132 This code gets the pointer to the variable name.
136 VarStoreHeader Pointer to the Variable Store Header.
140 EfiRaw Variable store is raw
141 EfiValid Variable store is valid
142 EfiInvalid Variable store is invalid
146 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
147 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
148 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
154 if (VarStoreHeader
->Signature
== 0xffffffff &&
155 VarStoreHeader
->Size
== 0xffffffff &&
156 VarStoreHeader
->Format
== 0xff &&
157 VarStoreHeader
->State
== 0xff
167 CompareWithValidVariable (
168 IN VARIABLE_HEADER
*Variable
,
169 IN CHAR16
*VariableName
,
170 IN EFI_GUID
*VendorGuid
,
171 OUT VARIABLE_POINTER_TRACK
*PtrTrack
177 This function compares a variable with variable entries in database
181 Variable - Pointer to the variable in our database
182 VariableName - Name of the variable to compare to 'Variable'
183 VendorGuid - GUID of the variable to compare to 'Variable'
184 PtrTrack - Variable Track Pointer structure that contains
185 Variable Information.
189 EFI_SUCCESS - Found match variable
190 EFI_NOT_FOUND - Variable not found
194 if (VariableName
[0] == 0) {
195 PtrTrack
->CurrPtr
= Variable
;
199 // Don't use CompareGuid function here for performance reasons.
200 // Instead we compare the GUID a UINT32 at a time and branch
201 // on the first failed comparison.
203 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
204 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
205 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
206 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
208 if (!StrCmp (VariableName
, GET_VARIABLE_NAME_PTR (Variable
))) {
209 PtrTrack
->CurrPtr
= Variable
;
215 return EFI_NOT_FOUND
;
221 IN EFI_PEI_SERVICES
**PeiServices
,
222 IN CHAR16
*VariableName
,
223 IN EFI_GUID
*VendorGuid
,
224 OUT VARIABLE_POINTER_TRACK
*PtrTrack
230 This code finds variable in storage blocks (Non-Volatile)
234 PeiServices - General purpose services available to every PEIM.
235 VariableName - Name of the variable to be found
236 VendorGuid - Vendor GUID to be found.
237 PtrTrack - Variable Track Pointer structure that contains
238 Variable Information.
242 EFI_SUCCESS - Variable found successfully
243 EFI_NOT_FOUND - Variable not found
244 EFI_INVALID_PARAMETER - Invalid variable name
248 PEI_FLASH_MAP_PPI
*FlashMapPpi
;
249 EFI_FLASH_SUBAREA_ENTRY
*VariableStoreEntry
;
251 EFI_HOB_GUID_TYPE
*GuidHob
;
252 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
253 VARIABLE_HEADER
*Variable
;
257 VARIABLE_HEADER
*MaxIndex
;
258 VARIABLE_INDEX_TABLE
*IndexTable
;
261 if (VariableName
!= 0 && VendorGuid
== NULL
) {
262 return EFI_INVALID_PARAMETER
;
265 // No Variable Address equals zero, so 0 as initial value is safe.
269 GuidHob
= GetFirstGuidHob (&gEfiVariableIndexTableGuid
);
270 if (GuidHob
== NULL
) {
271 IndexTable
= BuildGuidHob (&gEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
272 IndexTable
->Length
= 0;
273 IndexTable
->StartPtr
= NULL
;
274 IndexTable
->EndPtr
= NULL
;
275 IndexTable
->GoneThrough
= 0;
277 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
278 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
281 MaxIndex
= (VARIABLE_HEADER
*) (UINTN
) (IndexTable
->Index
[Count
] + ((UINTN
) IndexTable
->StartPtr
& 0xFFFF0000));
284 MaxIndex
= (VARIABLE_HEADER
*) (UINTN
) ((((UINT32
)IndexTable
->Index
[Count
]) << 2) + ((UINT32
)(UINTN
)IndexTable
->StartPtr
& 0xFFFC0000) );
287 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
288 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
289 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
295 if (IndexTable
->GoneThrough
) {
296 return EFI_NOT_FOUND
;
300 // If not found in HOB, then let's start from the MaxIndex we've found.
302 if (MaxIndex
!= NULL
) {
303 Variable
= GetNextVariablePtr (MaxIndex
);
305 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
306 Variable
= IndexTable
->StartPtr
;
309 // Locate FlashMap PPI
311 Status
= (**PeiServices
).LocatePpi (
313 &gPeiFlashMapPpiGuid
,
316 (VOID
**) &FlashMapPpi
318 ASSERT_EFI_ERROR (Status
);
321 // Get flash area info for variables
323 Status
= FlashMapPpi
->GetAreaInfo (
326 EFI_FLASH_AREA_EFI_VARIABLES
,
333 // Currently only one non-volatile variable store is supported
335 if (NumEntries
!= 1) {
336 return EFI_UNSUPPORTED
;
339 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (UINTN
) (VariableStoreEntry
->Base
);
341 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
342 return EFI_UNSUPPORTED
;
345 if (~VariableStoreHeader
->Size
== 0) {
346 return EFI_NOT_FOUND
;
349 // Find the variable by walk through non-volatile variable store
351 IndexTable
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
352 IndexTable
->EndPtr
= (VARIABLE_HEADER
*) ((UINTN
) VariableStoreHeader
+ VariableStoreHeader
->Size
);
355 // Start Pointers for the variable.
356 // Actual Data Pointer where data can be written.
358 Variable
= IndexTable
->StartPtr
;
362 // Find the variable by walk through non-volatile variable store
364 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
365 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
367 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
368 if (Variable
->State
== VAR_ADDED
) {
370 // Record Variable in VariableIndex HOB
372 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
375 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) (UINTN
) Variable
;
378 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) (((UINT32
)(UINTN
) Variable
) >> 2);
383 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
388 Variable
= GetNextVariablePtr (Variable
);
391 // If gone through the VariableStore, that means we never find in Firmware any more.
393 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
394 IndexTable
->GoneThrough
= 1;
397 PtrTrack
->CurrPtr
= NULL
;
399 return EFI_NOT_FOUND
;
405 IN EFI_PEI_SERVICES
**PeiServices
,
406 IN CHAR16
*VariableName
,
407 IN EFI_GUID
* VendorGuid
,
408 OUT UINT32
*Attributes OPTIONAL
,
409 IN OUT UINTN
*DataSize
,
416 Provide the read variable functionality of the variable services.
420 PeiServices - General purpose services available to every PEIM.
422 VariableName - The variable name
424 VendorGuid - The vendor's GUID
426 Attributes - Pointer to the attribute
428 DataSize - Size of data
430 Data - Pointer to data
434 EFI_SUCCESS - The interface could be successfully installed
436 EFI_NOT_FOUND - The variable could not be discovered
438 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
442 VARIABLE_POINTER_TRACK Variable
;
446 if (VariableName
== NULL
|| VendorGuid
== NULL
) {
447 return EFI_INVALID_PARAMETER
;
450 // Find existing variable
452 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
454 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
460 VarDataSize
= Variable
.CurrPtr
->DataSize
;
461 if (*DataSize
>= VarDataSize
) {
462 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
464 if (Attributes
!= NULL
) {
465 *Attributes
= Variable
.CurrPtr
->Attributes
;
468 *DataSize
= VarDataSize
;
471 *DataSize
= VarDataSize
;
472 return EFI_BUFFER_TOO_SMALL
;
478 PeiGetNextVariableName (
479 IN EFI_PEI_SERVICES
**PeiServices
,
480 IN OUT UINTN
*VariableNameSize
,
481 IN OUT CHAR16
*VariableName
,
482 IN OUT EFI_GUID
*VendorGuid
488 Provide the get next variable functionality of the variable services.
492 PeiServices - General purpose services available to every PEIM.
493 VariabvleNameSize - The variable name's size.
494 VariableName - A pointer to the variable's name.
495 VendorGuid - A pointer to the EFI_GUID structure.
497 VariableNameSize - Size of the variable name
499 VariableName - The variable name
501 VendorGuid - The vendor's GUID
505 EFI_SUCCESS - The interface could be successfully installed
507 EFI_NOT_FOUND - The variable could not be discovered
511 VARIABLE_POINTER_TRACK Variable
;
515 if (VariableName
== NULL
) {
516 return EFI_INVALID_PARAMETER
;
519 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
521 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
525 if (VariableName
[0] != 0) {
527 // If variable name is not NULL, get next variable
529 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
532 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
533 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
534 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
535 VarNameSize
= (UINTN
) Variable
.CurrPtr
->NameSize
;
536 if (VarNameSize
<= *VariableNameSize
) {
537 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
539 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
541 Status
= EFI_SUCCESS
;
543 Status
= EFI_BUFFER_TOO_SMALL
;
546 *VariableNameSize
= VarNameSize
;
552 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
559 return EFI_NOT_FOUND
;