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
);
74 IN VARIABLE_HEADER
*Variable
80 This code checks if variable header is valid or not.
83 Variable Pointer to the Variable Header.
86 TRUE Variable header is valid.
87 FALSE Variable header is not valid.
91 return (VARIABLE_HEADER
*) ((UINTN
) GET_VARIABLE_DATA_PTR (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
97 IsValidVariableHeader (
98 IN VARIABLE_HEADER
*Variable
104 This code checks if variable header is valid or not.
107 Variable Pointer to the Variable Header.
110 TRUE Variable header is valid.
111 FALSE Variable header is not valid.
115 if (Variable
== NULL
||
116 Variable
->StartId
!= VARIABLE_DATA
||
117 (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
171 CompareWithValidVariable (
172 IN VARIABLE_HEADER
*Variable
,
173 IN CHAR16
*VariableName
,
174 IN EFI_GUID
*VendorGuid
,
175 OUT VARIABLE_POINTER_TRACK
*PtrTrack
181 This function compares a variable with variable entries in database
185 Variable - Pointer to the variable in our database
186 VariableName - Name of the variable to compare to 'Variable'
187 VendorGuid - GUID of the variable to compare to 'Variable'
188 PtrTrack - Variable Track Pointer structure that contains
189 Variable Information.
193 EFI_SUCCESS - Found match variable
194 EFI_NOT_FOUND - Variable not found
198 if (VariableName
[0] == 0) {
199 PtrTrack
->CurrPtr
= Variable
;
203 // Don't use CompareGuid function here for performance reasons.
204 // Instead we compare the GUID a UINT32 at a time and branch
205 // on the first failed comparison.
207 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
208 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
209 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
210 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
212 if (!StrCmp (VariableName
, GET_VARIABLE_NAME_PTR (Variable
))) {
213 PtrTrack
->CurrPtr
= Variable
;
219 return EFI_NOT_FOUND
;
226 IN EFI_PEI_SERVICES
**PeiServices
,
227 IN CHAR16
*VariableName
,
228 IN EFI_GUID
*VendorGuid
,
229 OUT VARIABLE_POINTER_TRACK
*PtrTrack
235 This code finds variable in storage blocks (Non-Volatile)
239 PeiServices - General purpose services available to every PEIM.
240 VariableName - Name of the variable to be found
241 VendorGuid - Vendor GUID to be found.
242 PtrTrack - Variable Track Pointer structure that contains
243 Variable Information.
247 EFI_SUCCESS - Variable found successfully
248 EFI_NOT_FOUND - Variable not found
249 EFI_INVALID_PARAMETER - Invalid variable name
253 EFI_HOB_GUID_TYPE
*GuidHob
;
254 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
255 VARIABLE_HEADER
*Variable
;
256 VARIABLE_HEADER
*MaxIndex
;
257 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
;
308 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
309 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
310 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
312 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
313 return EFI_UNSUPPORTED
;
316 if (~VariableStoreHeader
->Size
== 0) {
317 return EFI_NOT_FOUND
;
320 // Find the variable by walk through non-volatile variable store
322 IndexTable
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
323 IndexTable
->EndPtr
= (VARIABLE_HEADER
*) ((UINTN
) VariableStoreHeader
+ VariableStoreHeader
->Size
);
326 // Start Pointers for the variable.
327 // Actual Data Pointer where data can be written.
329 Variable
= IndexTable
->StartPtr
;
333 // Find the variable by walk through non-volatile variable store
335 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
336 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
338 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
339 if (Variable
->State
== VAR_ADDED
) {
341 // Record Variable in VariableIndex HOB
343 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
346 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) (UINTN
) Variable
;
349 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) (((UINT32
)(UINTN
) Variable
) >> 2);
354 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
359 Variable
= GetNextVariablePtr (Variable
);
362 // If gone through the VariableStore, that means we never find in Firmware any more.
364 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
365 IndexTable
->GoneThrough
= 1;
368 PtrTrack
->CurrPtr
= NULL
;
370 return EFI_NOT_FOUND
;
376 IN EFI_PEI_SERVICES
**PeiServices
,
377 IN CHAR16
*VariableName
,
378 IN EFI_GUID
* VendorGuid
,
379 OUT UINT32
*Attributes OPTIONAL
,
380 IN OUT UINTN
*DataSize
,
387 Provide the read variable functionality of the variable services.
391 PeiServices - General purpose services available to every PEIM.
393 VariableName - The variable name
395 VendorGuid - The vendor's GUID
397 Attributes - Pointer to the attribute
399 DataSize - Size of data
401 Data - Pointer to data
405 EFI_SUCCESS - The interface could be successfully installed
407 EFI_NOT_FOUND - The variable could not be discovered
409 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
413 VARIABLE_POINTER_TRACK Variable
;
417 if (VariableName
== NULL
|| VendorGuid
== NULL
) {
418 return EFI_INVALID_PARAMETER
;
421 // Find existing variable
423 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
425 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
431 VarDataSize
= Variable
.CurrPtr
->DataSize
;
432 if (*DataSize
>= VarDataSize
) {
433 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
435 if (Attributes
!= NULL
) {
436 *Attributes
= Variable
.CurrPtr
->Attributes
;
439 *DataSize
= VarDataSize
;
442 *DataSize
= VarDataSize
;
443 return EFI_BUFFER_TOO_SMALL
;
449 PeiGetNextVariableName (
450 IN EFI_PEI_SERVICES
**PeiServices
,
451 IN OUT UINTN
*VariableNameSize
,
452 IN OUT CHAR16
*VariableName
,
453 IN OUT EFI_GUID
*VendorGuid
459 Provide the get next variable functionality of the variable services.
463 PeiServices - General purpose services available to every PEIM.
464 VariabvleNameSize - The variable name's size.
465 VariableName - A pointer to the variable's name.
466 VendorGuid - A pointer to the EFI_GUID structure.
468 VariableNameSize - Size of the variable name
470 VariableName - The variable name
472 VendorGuid - The vendor's GUID
476 EFI_SUCCESS - The interface could be successfully installed
478 EFI_NOT_FOUND - The variable could not be discovered
482 VARIABLE_POINTER_TRACK Variable
;
486 if (VariableName
== NULL
) {
487 return EFI_INVALID_PARAMETER
;
490 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
492 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
496 if (VariableName
[0] != 0) {
498 // If variable name is not NULL, get next variable
500 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
503 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
504 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
505 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
506 VarNameSize
= (UINTN
) Variable
.CurrPtr
->NameSize
;
507 if (VarNameSize
<= *VariableNameSize
) {
508 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
510 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
512 Status
= EFI_SUCCESS
;
514 Status
= EFI_BUFFER_TOO_SMALL
;
517 *VariableNameSize
= VarNameSize
;
523 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
530 return EFI_NOT_FOUND
;