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
23 #include <Ppi/ReadOnlyVariable.h>
25 #include <Library/BaseLib.h>
30 static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi
= {
32 PeiGetNextVariableName
35 static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
= {
36 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
37 &gEfiPeiReadOnlyVariablePpiGuid
,
41 EFI_GUID gEfiVariableIndexTableGuid
= EFI_VARIABLE_INDEX_TABLE_GUID
;
45 PeimInitializeVariableServices (
46 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
47 IN EFI_PEI_SERVICES
**PeiServices
53 Provide the functionality of the variable services.
57 FfsHeadher - The FFS file header
58 PeiServices - General purpose services available to every PEIM.
62 Status - EFI_SUCCESS if the interface could be successfully
68 // Publish the variable capability to other modules
70 return (**PeiServices
).InstallPpi (PeiServices
, &mPpiListVariable
);
76 IN VARIABLE_HEADER
*Variable
82 This code checks if variable header is valid or not.
85 Variable Pointer to the Variable Header.
88 TRUE Variable header is valid.
89 FALSE Variable header is not valid.
93 return (VARIABLE_HEADER
*) ((UINTN
) GET_VARIABLE_DATA_PTR (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
98 IsValidVariableHeader (
99 IN VARIABLE_HEADER
*Variable
105 This code checks if variable header is valid or not.
108 Variable Pointer to the Variable Header.
111 TRUE Variable header is valid.
112 FALSE Variable header is not valid.
116 if (Variable
== NULL
||
117 Variable
->StartId
!= VARIABLE_DATA
||
118 (sizeof (VARIABLE_HEADER
) + Variable
->DataSize
+ Variable
->NameSize
) > MAX_VARIABLE_SIZE
126 VARIABLE_STORE_STATUS
128 GetVariableStoreStatus (
129 IN VARIABLE_STORE_HEADER
*VarStoreHeader
135 This code gets the pointer to the variable name.
139 VarStoreHeader Pointer to the Variable Store Header.
143 EfiRaw Variable store is raw
144 EfiValid Variable store is valid
145 EfiInvalid Variable store is invalid
149 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
150 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
151 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
157 if (VarStoreHeader
->Signature
== 0xffffffff &&
158 VarStoreHeader
->Size
== 0xffffffff &&
159 VarStoreHeader
->Format
== 0xff &&
160 VarStoreHeader
->State
== 0xff
170 CompareWithValidVariable (
171 IN VARIABLE_HEADER
*Variable
,
172 IN CHAR16
*VariableName
,
173 IN EFI_GUID
*VendorGuid
,
174 OUT VARIABLE_POINTER_TRACK
*PtrTrack
180 This function compares a variable with variable entries in database
184 Variable - Pointer to the variable in our database
185 VariableName - Name of the variable to compare to 'Variable'
186 VendorGuid - GUID of the variable to compare to 'Variable'
187 PtrTrack - Variable Track Pointer structure that contains
188 Variable Information.
192 EFI_SUCCESS - Found match variable
193 EFI_NOT_FOUND - Variable not found
197 if (VariableName
[0] == 0) {
198 PtrTrack
->CurrPtr
= Variable
;
202 // Don't use CompareGuid function here for performance reasons.
203 // Instead we compare the GUID a UINT32 at a time and branch
204 // on the first failed comparison.
206 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
207 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
208 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
209 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
211 if (!StrCmp (VariableName
, GET_VARIABLE_NAME_PTR (Variable
))) {
212 PtrTrack
->CurrPtr
= Variable
;
218 return EFI_NOT_FOUND
;
224 IN EFI_PEI_SERVICES
**PeiServices
,
225 IN CHAR16
*VariableName
,
226 IN EFI_GUID
*VendorGuid
,
227 OUT VARIABLE_POINTER_TRACK
*PtrTrack
233 This code finds variable in storage blocks (Non-Volatile)
237 PeiServices - General purpose services available to every PEIM.
238 VariableName - Name of the variable to be found
239 VendorGuid - Vendor GUID to be found.
240 PtrTrack - Variable Track Pointer structure that contains
241 Variable Information.
245 EFI_SUCCESS - Variable found successfully
246 EFI_NOT_FOUND - Variable not found
247 EFI_INVALID_PARAMETER - Invalid variable name
251 PEI_FLASH_MAP_PPI
*FlashMapPpi
;
252 EFI_FLASH_SUBAREA_ENTRY
*VariableStoreEntry
;
254 EFI_HOB_GUID_TYPE
*GuidHob
;
255 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
256 VARIABLE_HEADER
*Variable
;
260 VARIABLE_HEADER
*MaxIndex
;
261 VARIABLE_INDEX_TABLE
*IndexTable
;
264 if (VariableName
!= 0 && VendorGuid
== NULL
) {
265 return EFI_INVALID_PARAMETER
;
268 // No Variable Address equals zero, so 0 as initial value is safe.
272 GuidHob
= GetFirstGuidHob (&gEfiVariableIndexTableGuid
);
273 if (GuidHob
== NULL
) {
274 IndexTable
= BuildGuidHob (&gEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
275 IndexTable
->Length
= 0;
276 IndexTable
->StartPtr
= NULL
;
277 IndexTable
->EndPtr
= NULL
;
278 IndexTable
->GoneThrough
= 0;
280 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
281 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
284 MaxIndex
= (VARIABLE_HEADER
*) (UINTN
) (IndexTable
->Index
[Count
] + ((UINTN
) IndexTable
->StartPtr
& 0xFFFF0000));
287 MaxIndex
= (VARIABLE_HEADER
*) (UINTN
) ((((UINT32
)IndexTable
->Index
[Count
]) << 2) + ((UINT32
)(UINTN
)IndexTable
->StartPtr
& 0xFFFC0000) );
290 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
291 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
292 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
298 if (IndexTable
->GoneThrough
) {
299 return EFI_NOT_FOUND
;
303 // If not found in HOB, then let's start from the MaxIndex we've found.
305 if (MaxIndex
!= NULL
) {
306 Variable
= GetNextVariablePtr (MaxIndex
);
308 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
309 Variable
= IndexTable
->StartPtr
;
312 // Locate FlashMap PPI
314 Status
= (**PeiServices
).LocatePpi (
316 &gPeiFlashMapPpiGuid
,
319 (VOID
**) &FlashMapPpi
321 ASSERT_EFI_ERROR (Status
);
324 // Get flash area info for variables
326 Status
= FlashMapPpi
->GetAreaInfo (
329 EFI_FLASH_AREA_EFI_VARIABLES
,
336 // Currently only one non-volatile variable store is supported
338 if (NumEntries
!= 1) {
339 return EFI_UNSUPPORTED
;
342 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (UINTN
) (VariableStoreEntry
->Base
);
344 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
345 return EFI_UNSUPPORTED
;
348 if (~VariableStoreHeader
->Size
== 0) {
349 return EFI_NOT_FOUND
;
352 // Find the variable by walk through non-volatile variable store
354 IndexTable
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
355 IndexTable
->EndPtr
= (VARIABLE_HEADER
*) ((UINTN
) VariableStoreHeader
+ VariableStoreHeader
->Size
);
358 // Start Pointers for the variable.
359 // Actual Data Pointer where data can be written.
361 Variable
= IndexTable
->StartPtr
;
365 // Find the variable by walk through non-volatile variable store
367 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
368 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
370 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
371 if (Variable
->State
== VAR_ADDED
) {
373 // Record Variable in VariableIndex HOB
375 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
378 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) (UINTN
) Variable
;
381 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) (((UINT32
)(UINTN
) Variable
) >> 2);
386 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
391 Variable
= GetNextVariablePtr (Variable
);
394 // If gone through the VariableStore, that means we never find in Firmware any more.
396 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
397 IndexTable
->GoneThrough
= 1;
400 PtrTrack
->CurrPtr
= NULL
;
402 return EFI_NOT_FOUND
;
408 IN EFI_PEI_SERVICES
**PeiServices
,
409 IN CHAR16
*VariableName
,
410 IN EFI_GUID
* VendorGuid
,
411 OUT UINT32
*Attributes OPTIONAL
,
412 IN OUT UINTN
*DataSize
,
419 Provide the read variable functionality of the variable services.
423 PeiServices - General purpose services available to every PEIM.
425 VariableName - The variable name
427 VendorGuid - The vendor's GUID
429 Attributes - Pointer to the attribute
431 DataSize - Size of data
433 Data - Pointer to data
437 EFI_SUCCESS - The interface could be successfully installed
439 EFI_NOT_FOUND - The variable could not be discovered
441 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
445 VARIABLE_POINTER_TRACK Variable
;
449 if (VariableName
== NULL
|| VendorGuid
== NULL
) {
450 return EFI_INVALID_PARAMETER
;
453 // Find existing variable
455 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
457 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
463 VarDataSize
= Variable
.CurrPtr
->DataSize
;
464 if (*DataSize
>= VarDataSize
) {
465 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
467 if (Attributes
!= NULL
) {
468 *Attributes
= Variable
.CurrPtr
->Attributes
;
471 *DataSize
= VarDataSize
;
474 *DataSize
= VarDataSize
;
475 return EFI_BUFFER_TOO_SMALL
;
481 PeiGetNextVariableName (
482 IN EFI_PEI_SERVICES
**PeiServices
,
483 IN OUT UINTN
*VariableNameSize
,
484 IN OUT CHAR16
*VariableName
,
485 IN OUT EFI_GUID
*VendorGuid
491 Provide the get next variable functionality of the variable services.
495 PeiServices - General purpose services available to every PEIM.
496 VariabvleNameSize - The variable name's size.
497 VariableName - A pointer to the variable's name.
498 VendorGuid - A pointer to the EFI_GUID structure.
500 VariableNameSize - Size of the variable name
502 VariableName - The variable name
504 VendorGuid - The vendor's GUID
508 EFI_SUCCESS - The interface could be successfully installed
510 EFI_NOT_FOUND - The variable could not be discovered
514 VARIABLE_POINTER_TRACK Variable
;
518 if (VariableName
== NULL
) {
519 return EFI_INVALID_PARAMETER
;
522 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
524 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
528 if (VariableName
[0] != 0) {
530 // If variable name is not NULL, get next variable
532 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
535 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
536 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
537 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
538 VarNameSize
= (UINTN
) Variable
.CurrPtr
->NameSize
;
539 if (VarNameSize
<= *VariableNameSize
) {
540 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
542 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
544 Status
= EFI_SUCCESS
;
546 Status
= EFI_BUFFER_TOO_SMALL
;
549 *VariableNameSize
= VarNameSize
;
555 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
562 return EFI_NOT_FOUND
;