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
);
126 IN VARIABLE_HEADER
*Variable
132 This code checks if variable header is valid or not.
135 Variable Pointer to the Variable Header.
138 TRUE Variable header is valid.
139 FALSE Variable header is not valid.
143 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) GET_VARIABLE_DATA_PTR (Variable
) + DATASIZE_OF_VARIABLE (Variable
) + GET_PAD_SIZE (DATASIZE_OF_VARIABLE (Variable
)));
149 IsValidVariableHeader (
150 IN VARIABLE_HEADER
*Variable
156 This code checks if variable header is valid or not.
159 Variable Pointer to the Variable Header.
162 TRUE Variable header is valid.
163 FALSE Variable header is not valid.
167 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
175 VARIABLE_STORE_STATUS
177 GetVariableStoreStatus (
178 IN VARIABLE_STORE_HEADER
*VarStoreHeader
184 This code gets the pointer to the variable name.
188 VarStoreHeader Pointer to the Variable Store Header.
192 EfiRaw Variable store is raw
193 EfiValid Variable store is valid
194 EfiInvalid Variable store is invalid
198 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
199 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
200 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
206 if (VarStoreHeader
->Signature
== 0xffffffff &&
207 VarStoreHeader
->Size
== 0xffffffff &&
208 VarStoreHeader
->Format
== 0xff &&
209 VarStoreHeader
->State
== 0xff
220 CompareWithValidVariable (
221 IN VARIABLE_HEADER
*Variable
,
222 IN CONST CHAR16
*VariableName
,
223 IN CONST EFI_GUID
*VendorGuid
,
224 OUT VARIABLE_POINTER_TRACK
*PtrTrack
230 This function compares a variable with variable entries in database
234 Variable - Pointer to the variable in our database
235 VariableName - Name of the variable to compare to 'Variable'
236 VendorGuid - GUID of the variable to compare to 'Variable'
237 PtrTrack - Variable Track Pointer structure that contains
238 Variable Information.
242 EFI_SUCCESS - Found match variable
243 EFI_NOT_FOUND - Variable not found
247 if (VariableName
[0] == 0) {
248 PtrTrack
->CurrPtr
= Variable
;
252 // Don't use CompareGuid function here for performance reasons.
253 // Instead we compare the GUID a UINT32 at a time and branch
254 // on the first failed comparison.
256 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
257 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
258 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
259 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
261 ASSERT (NAMESIZE_OF_VARIABLE (Variable
) != 0);
262 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
), NAMESIZE_OF_VARIABLE (Variable
))) {
263 PtrTrack
->CurrPtr
= Variable
;
269 return EFI_NOT_FOUND
;
276 IN EFI_PEI_SERVICES
**PeiServices
,
277 IN CONST CHAR16
*VariableName
,
278 IN CONST EFI_GUID
*VendorGuid
,
279 OUT VARIABLE_POINTER_TRACK
*PtrTrack
285 This code finds variable in storage blocks (Non-Volatile)
289 PeiServices - General purpose services available to every PEIM.
290 VariableName - Name of the variable to be found
291 VendorGuid - Vendor GUID to be found.
292 PtrTrack - Variable Track Pointer structure that contains
293 Variable Information.
297 EFI_SUCCESS - Variable found successfully
298 EFI_NOT_FOUND - Variable not found
299 EFI_INVALID_PARAMETER - Invalid variable name
303 EFI_HOB_GUID_TYPE
*GuidHob
;
304 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
305 VARIABLE_HEADER
*Variable
;
306 VARIABLE_HEADER
*MaxIndex
;
307 VARIABLE_INDEX_TABLE
*IndexTable
;
311 if (VariableName
!= 0 && VendorGuid
== NULL
) {
312 return EFI_INVALID_PARAMETER
;
315 // No Variable Address equals zero, so 0 as initial value is safe.
319 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
320 if (GuidHob
== NULL
) {
321 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
322 IndexTable
->Length
= 0;
323 IndexTable
->StartPtr
= NULL
;
324 IndexTable
->EndPtr
= NULL
;
325 IndexTable
->GoneThrough
= 0;
327 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
328 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
330 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
332 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
333 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
334 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
340 if (IndexTable
->GoneThrough
) {
341 return EFI_NOT_FOUND
;
345 // If not found in HOB, then let's start from the MaxIndex we've found.
347 if (MaxIndex
!= NULL
) {
348 Variable
= GetNextVariablePtr (MaxIndex
);
350 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
351 Variable
= IndexTable
->StartPtr
;
353 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
354 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
355 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
357 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
358 return EFI_UNSUPPORTED
;
361 if (~VariableStoreHeader
->Size
== 0) {
362 return EFI_NOT_FOUND
;
365 // Find the variable by walk through non-volatile variable store
367 IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
368 IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
371 // Start Pointers for the variable.
372 // Actual Data Pointer where data can be written.
374 Variable
= IndexTable
->StartPtr
;
378 // Find the variable by walk through non-volatile variable store
380 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
381 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
383 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
384 if (Variable
->State
== VAR_ADDED
) {
386 // Record Variable in VariableIndex HOB
388 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
390 VariableIndexTableUpdate (IndexTable
, Variable
);
393 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
398 Variable
= GetNextVariablePtr (Variable
);
401 // If gone through the VariableStore, that means we never find in Firmware any more.
403 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
404 IndexTable
->GoneThrough
= 1;
407 PtrTrack
->CurrPtr
= NULL
;
409 return EFI_NOT_FOUND
;
415 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
416 IN CONST CHAR16
*VariableName
,
417 IN CONST EFI_GUID
*VariableGuid
,
418 OUT UINT32
*Attributes
,
419 IN OUT UINTN
*DataSize
,
426 Provide the read variable functionality of the variable services.
430 PeiServices - General purpose services available to every PEIM.
432 VariableName - The variable name
434 VendorGuid - The vendor's GUID
436 Attributes - Pointer to the attribute
438 DataSize - Size of data
440 Data - Pointer to data
444 EFI_SUCCESS - The interface could be successfully installed
446 EFI_NOT_FOUND - The variable could not be discovered
448 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
452 VARIABLE_POINTER_TRACK Variable
;
455 EFI_PEI_SERVICES
**PeiServices
;
457 PeiServices
= GetPeiServicesTablePointer ();
458 if (VariableName
== NULL
|| VariableGuid
== NULL
) {
459 return EFI_INVALID_PARAMETER
;
462 // Find existing variable
464 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
465 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
471 VarDataSize
= DATASIZE_OF_VARIABLE (Variable
.CurrPtr
);
472 if (*DataSize
>= VarDataSize
) {
473 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
475 if (Attributes
!= NULL
) {
476 *Attributes
= Variable
.CurrPtr
->Attributes
;
479 *DataSize
= VarDataSize
;
482 *DataSize
= VarDataSize
;
483 return EFI_BUFFER_TOO_SMALL
;
489 PeiGetNextVariableName (
490 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
491 IN OUT UINTN
*VariableNameSize
,
492 IN OUT CHAR16
*VariableName
,
493 IN OUT EFI_GUID
*VariableGuid
499 Provide the get next variable functionality of the variable services.
503 PeiServices - General purpose services available to every PEIM.
504 VariabvleNameSize - The variable name's size.
505 VariableName - A pointer to the variable's name.
506 VariableGuid - A pointer to the EFI_GUID structure.
508 VariableNameSize - Size of the variable name
510 VariableName - The variable name
512 VendorGuid - The vendor's GUID
516 EFI_SUCCESS - The interface could be successfully installed
518 EFI_NOT_FOUND - The variable could not be discovered
522 VARIABLE_POINTER_TRACK Variable
;
525 EFI_PEI_SERVICES
**PeiServices
;
527 PeiServices
= GetPeiServicesTablePointer ();
528 if (VariableName
== NULL
) {
529 return EFI_INVALID_PARAMETER
;
532 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
533 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
537 if (VariableName
[0] != 0) {
539 // If variable name is not NULL, get next variable
541 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
544 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
545 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
546 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
547 ASSERT (NAMESIZE_OF_VARIABLE (Variable
.CurrPtr
) != 0);
549 VarNameSize
= (UINTN
) NAMESIZE_OF_VARIABLE (Variable
.CurrPtr
);
550 if (VarNameSize
<= *VariableNameSize
) {
551 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
553 (*PeiServices
)->CopyMem (VariableGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
555 Status
= EFI_SUCCESS
;
557 Status
= EFI_BUFFER_TOO_SMALL
;
560 *VariableNameSize
= VarNameSize
;
566 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
573 return EFI_NOT_FOUND
;