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 EFI_HOB_GUID_TYPE
*GuidHob
;
249 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
250 VARIABLE_HEADER
*Variable
;
251 VARIABLE_HEADER
*MaxIndex
;
252 VARIABLE_INDEX_TABLE
*IndexTable
;
256 if (VariableName
!= 0 && VendorGuid
== NULL
) {
257 return EFI_INVALID_PARAMETER
;
260 // No Variable Address equals zero, so 0 as initial value is safe.
264 GuidHob
= GetFirstGuidHob (&gEfiVariableIndexTableGuid
);
265 if (GuidHob
== NULL
) {
266 IndexTable
= BuildGuidHob (&gEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
267 IndexTable
->Length
= 0;
268 IndexTable
->StartPtr
= NULL
;
269 IndexTable
->EndPtr
= NULL
;
270 IndexTable
->GoneThrough
= 0;
272 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
273 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
276 MaxIndex
= (VARIABLE_HEADER
*) (UINTN
) (IndexTable
->Index
[Count
] + ((UINTN
) IndexTable
->StartPtr
& 0xFFFF0000));
279 MaxIndex
= (VARIABLE_HEADER
*) (UINTN
) ((((UINT32
)IndexTable
->Index
[Count
]) << 2) + ((UINT32
)(UINTN
)IndexTable
->StartPtr
& 0xFFFC0000) );
282 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
283 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
284 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
290 if (IndexTable
->GoneThrough
) {
291 return EFI_NOT_FOUND
;
295 // If not found in HOB, then let's start from the MaxIndex we've found.
297 if (MaxIndex
!= NULL
) {
298 Variable
= GetNextVariablePtr (MaxIndex
);
300 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
301 Variable
= IndexTable
->StartPtr
;
303 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
304 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
305 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
307 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
308 return EFI_UNSUPPORTED
;
311 if (~VariableStoreHeader
->Size
== 0) {
312 return EFI_NOT_FOUND
;
315 // Find the variable by walk through non-volatile variable store
317 IndexTable
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
318 IndexTable
->EndPtr
= (VARIABLE_HEADER
*) ((UINTN
) VariableStoreHeader
+ VariableStoreHeader
->Size
);
321 // Start Pointers for the variable.
322 // Actual Data Pointer where data can be written.
324 Variable
= IndexTable
->StartPtr
;
328 // Find the variable by walk through non-volatile variable store
330 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
331 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
333 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
334 if (Variable
->State
== VAR_ADDED
) {
336 // Record Variable in VariableIndex HOB
338 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
341 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) (UINTN
) Variable
;
344 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) (((UINT32
)(UINTN
) Variable
) >> 2);
349 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
354 Variable
= GetNextVariablePtr (Variable
);
357 // If gone through the VariableStore, that means we never find in Firmware any more.
359 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
360 IndexTable
->GoneThrough
= 1;
363 PtrTrack
->CurrPtr
= NULL
;
365 return EFI_NOT_FOUND
;
371 IN EFI_PEI_SERVICES
**PeiServices
,
372 IN CHAR16
*VariableName
,
373 IN EFI_GUID
* VendorGuid
,
374 OUT UINT32
*Attributes OPTIONAL
,
375 IN OUT UINTN
*DataSize
,
382 Provide the read variable functionality of the variable services.
386 PeiServices - General purpose services available to every PEIM.
388 VariableName - The variable name
390 VendorGuid - The vendor's GUID
392 Attributes - Pointer to the attribute
394 DataSize - Size of data
396 Data - Pointer to data
400 EFI_SUCCESS - The interface could be successfully installed
402 EFI_NOT_FOUND - The variable could not be discovered
404 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
408 VARIABLE_POINTER_TRACK Variable
;
412 if (VariableName
== NULL
|| VendorGuid
== NULL
) {
413 return EFI_INVALID_PARAMETER
;
416 // Find existing variable
418 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
420 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
426 VarDataSize
= Variable
.CurrPtr
->DataSize
;
427 if (*DataSize
>= VarDataSize
) {
428 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
430 if (Attributes
!= NULL
) {
431 *Attributes
= Variable
.CurrPtr
->Attributes
;
434 *DataSize
= VarDataSize
;
437 *DataSize
= VarDataSize
;
438 return EFI_BUFFER_TOO_SMALL
;
444 PeiGetNextVariableName (
445 IN EFI_PEI_SERVICES
**PeiServices
,
446 IN OUT UINTN
*VariableNameSize
,
447 IN OUT CHAR16
*VariableName
,
448 IN OUT EFI_GUID
*VendorGuid
454 Provide the get next variable functionality of the variable services.
458 PeiServices - General purpose services available to every PEIM.
459 VariabvleNameSize - The variable name's size.
460 VariableName - A pointer to the variable's name.
461 VendorGuid - A pointer to the EFI_GUID structure.
463 VariableNameSize - Size of the variable name
465 VariableName - The variable name
467 VendorGuid - The vendor's GUID
471 EFI_SUCCESS - The interface could be successfully installed
473 EFI_NOT_FOUND - The variable could not be discovered
477 VARIABLE_POINTER_TRACK Variable
;
481 if (VariableName
== NULL
) {
482 return EFI_INVALID_PARAMETER
;
485 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
487 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
491 if (VariableName
[0] != 0) {
493 // If variable name is not NULL, get next variable
495 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
498 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
499 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
500 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
501 VarNameSize
= (UINTN
) Variable
.CurrPtr
->NameSize
;
502 if (VarNameSize
<= *VariableNameSize
) {
503 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
505 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
507 Status
= EFI_SUCCESS
;
509 Status
= EFI_BUFFER_TOO_SMALL
;
512 *VariableNameSize
= VarNameSize
;
518 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
525 return EFI_NOT_FOUND
;