2 Framework PEIM to provide the Variable functionality
4 Copyright (c) 2006 - 2009 Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi
= {
24 PeiGetNextVariableName
27 EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariable2Ppi
= {
29 PeiGetNextVariableName2
32 EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
[] = {
34 (EFI_PEI_PPI_DESCRIPTOR_PPI
),
35 &gEfiPeiReadOnlyVariable2PpiGuid
,
39 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
40 &gEfiPeiReadOnlyVariablePpiGuid
,
45 EFI_GUID mEfiVariableIndexTableGuid
= EFI_VARIABLE_INDEX_TABLE_GUID
;
48 Provide the functionality of the variable services.
50 @param FileHandle Handle of the file being invoked.
51 @param PeiServices Describes the list of possible PEI Services.
53 @return EFI_SUCCESS If the interface could be successfully installed.
54 @return EFI_UNSUPPORTED If current boot path is in recovery mode, then does not
55 install this interface.
60 PeimInitializeVariableServices (
61 IN EFI_PEI_FILE_HANDLE FileHandle
,
62 IN CONST EFI_PEI_SERVICES
**PeiServices
65 EFI_BOOT_MODE BootMode
;
69 // Check if this is recovery boot path. If no, publish the variable access capability
70 // to other modules. If yes, the content of variable area is not reliable. Therefore,
71 // in this case we should not provide variable service to other pei modules.
73 Status
= (*PeiServices
)->GetBootMode (PeiServices
, &BootMode
);
74 ASSERT_EFI_ERROR (Status
);
76 if (BootMode
== BOOT_IN_RECOVERY_MODE
) {
77 return EFI_UNSUPPORTED
;
80 return (**PeiServices
).InstallPpi (PeiServices
, &mPpiListVariable
[0]);
85 This code gets the pointer to the first variable memory pointer byte
87 @param VarStoreHeader Pointer to the Variable Store Header.
89 @return VARIABLE_HEADER* Pointer to last unavailable Variable Header
94 IN VARIABLE_STORE_HEADER
*VarStoreHeader
98 // The end of variable store
100 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
104 This code gets the pointer to the last variable memory pointer byte
106 @param VarStoreHeader Pointer to the Variable Store Header.
108 @return VARIABLE_HEADER* Pointer to last unavailable Variable Header
113 IN VARIABLE_STORE_HEADER
*VarStoreHeader
118 // The end of variable store
120 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
125 This code checks if variable header is valid or not.
127 @param Variable Pointer to the Variable Header.
129 @retval TRUE Variable header is valid.
130 @retval FALSE Variable header is not valid.
135 IsValidVariableHeader (
136 IN VARIABLE_HEADER
*Variable
139 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
147 This code gets the size of name of variable.
149 @param Variable Pointer to the Variable Header.
151 @return UINTN Size of variable in bytes
156 IN VARIABLE_HEADER
*Variable
159 if (Variable
->State
== (UINT8
) (-1) ||
160 Variable
->DataSize
== (UINT32
) -1 ||
161 Variable
->NameSize
== (UINT32
) -1 ||
162 Variable
->Attributes
== (UINT32
) -1) {
165 return (UINTN
) Variable
->NameSize
;
169 This code gets the size of name of variable.
171 @param Variable Pointer to the Variable Header.
173 @return UINTN Size of variable in bytes
178 IN VARIABLE_HEADER
*Variable
181 if (Variable
->State
== (UINT8
) -1 ||
182 Variable
->DataSize
== (UINT32
) -1 ||
183 Variable
->NameSize
== (UINT32
) -1 ||
184 Variable
->Attributes
== (UINT32
) -1) {
187 return (UINTN
) Variable
->DataSize
;
191 This code gets the pointer to the variable name.
193 @param Variable Pointer to the Variable Header.
195 @return CHAR16* Pointer to Variable Name
200 IN VARIABLE_HEADER
*Variable
205 return (CHAR16
*) (Variable
+ 1);
209 This code gets the pointer to the variable data.
211 @param Variable Pointer to the Variable Header.
213 @return UINT8* Pointer to Variable Data
218 IN VARIABLE_HEADER
*Variable
224 // Be careful about pad size for alignment
226 Value
= (UINTN
) GetVariableNamePtr (Variable
);
227 Value
+= NameSizeOfVariable (Variable
);
228 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
230 return (UINT8
*) Value
;
234 This code gets the pointer to the next variable header.
236 @param Variable Pointer to the Variable Header.
238 @return VARIABLE_HEADER* Pointer to next variable header.
243 IN VARIABLE_HEADER
*Variable
249 if (!IsValidVariableHeader (Variable
)) {
253 Value
= (UINTN
) GetVariableDataPtr (Variable
);
254 Value
+= DataSizeOfVariable (Variable
);
255 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
258 // Be careful about pad size for alignment
260 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
264 This code gets the pointer to the variable name.
266 @param VarStoreHeader Pointer to the Variable Store Header.
268 @retval EfiRaw Variable store is raw
269 @retval EfiValid Variable store is valid
270 @retval EfiInvalid Variable store is invalid
273 VARIABLE_STORE_STATUS
275 GetVariableStoreStatus (
276 IN VARIABLE_STORE_HEADER
*VarStoreHeader
281 if (CompareGuid (&VarStoreHeader
->Signature
, &gEfiVariableGuid
) &&
282 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
283 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
289 if (((UINT32
*)(&VarStoreHeader
->Signature
))[0] == 0xffffffff &&
290 ((UINT32
*)(&VarStoreHeader
->Signature
))[1] == 0xffffffff &&
291 ((UINT32
*)(&VarStoreHeader
->Signature
))[2] == 0xffffffff &&
292 ((UINT32
*)(&VarStoreHeader
->Signature
))[3] == 0xffffffff &&
293 VarStoreHeader
->Size
== 0xffffffff &&
294 VarStoreHeader
->Format
== 0xff &&
295 VarStoreHeader
->State
== 0xff
305 This function compares a variable with variable entries in database
307 @param Variable - Pointer to the variable in our database
308 @param VariableName - Name of the variable to compare to 'Variable'
309 @param VendorGuid - GUID of the variable to compare to 'Variable'
310 @param PtrTrack - Variable Track Pointer structure that contains
311 Variable Information.
313 @retval EFI_SUCCESS - Found match variable
314 @retval EFI_NOT_FOUND - Variable not found
318 CompareWithValidVariable (
319 IN VARIABLE_HEADER
*Variable
,
320 IN CONST CHAR16
*VariableName
,
321 IN CONST EFI_GUID
*VendorGuid
,
322 OUT VARIABLE_POINTER_TRACK
*PtrTrack
328 if (VariableName
[0] == 0) {
329 PtrTrack
->CurrPtr
= Variable
;
333 // Don't use CompareGuid function here for performance reasons.
334 // Instead we compare the GUID a UINT32 at a time and branch
335 // on the first failed comparison.
337 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
338 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
339 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
340 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
342 ASSERT (NameSizeOfVariable (Variable
) != 0);
343 Point
= (VOID
*) GetVariableNamePtr (Variable
);
344 if (!CompareMem (VariableName
, Point
, NameSizeOfVariable (Variable
))) {
345 PtrTrack
->CurrPtr
= Variable
;
351 return EFI_NOT_FOUND
;
355 This code finds variable in storage blocks (Non-Volatile)
357 @param PeiServices - General purpose services available to every PEIM.
358 @param VariableName - Name of the variable to be found
359 @param VendorGuid - Vendor GUID to be found.
360 @param PtrTrack - Variable Track Pointer structure that contains
361 Variable Information.
363 @retval EFI_SUCCESS - Variable found successfully
364 @retval EFI_NOT_FOUND - Variable not found
365 @retval EFI_INVALID_PARAMETER - Invalid variable name
371 IN EFI_PEI_SERVICES
**PeiServices
,
372 IN CONST CHAR16
*VariableName
,
373 IN CONST EFI_GUID
*VendorGuid
,
374 OUT VARIABLE_POINTER_TRACK
*PtrTrack
378 EFI_HOB_GUID_TYPE
*GuidHob
;
379 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
380 VARIABLE_HEADER
*Variable
;
381 VARIABLE_HEADER
*MaxIndex
;
382 VARIABLE_INDEX_TABLE
*IndexTable
;
386 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
387 return EFI_INVALID_PARAMETER
;
390 // No Variable Address equals zero, so 0 as initial value is safe.
394 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
395 if (GuidHob
== NULL
) {
396 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
397 IndexTable
->Length
= 0;
398 IndexTable
->StartPtr
= NULL
;
399 IndexTable
->EndPtr
= NULL
;
400 IndexTable
->GoneThrough
= 0;
402 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
403 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
405 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
407 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
408 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
409 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
415 if (IndexTable
->GoneThrough
) {
416 return EFI_NOT_FOUND
;
420 // If not found in HOB, then let's start from the MaxIndex we've found.
422 if (MaxIndex
!= NULL
) {
423 Variable
= GetNextVariablePtr (MaxIndex
);
425 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
426 Variable
= IndexTable
->StartPtr
;
428 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
431 // Check if FV header is valid.
433 if (((EFI_FIRMWARE_VOLUME_HEADER
*) VariableBase
)->Signature
!= EFI_FVH_SIGNATURE
) {
434 return EFI_UNSUPPORTED
;
437 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
438 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
440 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
441 return EFI_UNSUPPORTED
;
444 if (~VariableStoreHeader
->Size
== 0) {
445 return EFI_NOT_FOUND
;
448 // Find the variable by walk through non-volatile variable store
450 IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
451 IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
454 // Start Pointers for the variable.
455 // Actual Data Pointer where data can be written.
457 Variable
= IndexTable
->StartPtr
;
461 // Find the variable by walk through non-volatile variable store
463 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
464 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
466 while ((Variable
< IndexTable
->EndPtr
) && IsValidVariableHeader (Variable
)) {
467 if (Variable
->State
== VAR_ADDED
) {
469 // Record Variable in VariableIndex HOB
471 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
473 VariableIndexTableUpdate (IndexTable
, Variable
);
476 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
481 Variable
= GetNextVariablePtr (Variable
);
484 // If gone through the VariableStore, that means we never find in Firmware any more.
486 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
487 IndexTable
->GoneThrough
= 1;
490 PtrTrack
->CurrPtr
= NULL
;
492 return EFI_NOT_FOUND
;
496 Provide the read variable functionality of the variable services.
498 @param PeiServices - General purpose services available to every PEIM.
500 @param VariableName - The variable name
502 @param VendorGuid - The vendor's GUID
504 @param Attributes - Pointer to the attribute
506 @param DataSize - Size of data
508 @param Data - Pointer to data
510 @retval EFI_SUCCESS - The interface could be successfully installed
512 @retval EFI_NOT_FOUND - The variable could not be discovered
514 @retval EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
520 IN EFI_PEI_SERVICES
**PeiServices
,
521 IN CHAR16
*VariableName
,
522 IN EFI_GUID
* VendorGuid
,
523 OUT UINT32
*Attributes OPTIONAL
,
524 IN OUT UINTN
*DataSize
,
529 VARIABLE_POINTER_TRACK Variable
;
533 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
534 return EFI_INVALID_PARAMETER
;
537 // Find existing variable
539 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
541 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
547 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
548 if (*DataSize
>= VarDataSize
) {
550 // PO-TKW: Address one checking in this place
553 return EFI_INVALID_PARAMETER
;
556 (*PeiServices
)->CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
558 if (Attributes
!= NULL
) {
559 *Attributes
= Variable
.CurrPtr
->Attributes
;
562 *DataSize
= VarDataSize
;
565 *DataSize
= VarDataSize
;
566 return EFI_BUFFER_TOO_SMALL
;
571 Provide the read variable functionality of the variable services.
573 @param PeiServices - General purpose services available to every PEIM.
575 @param VariableName - The variable name
577 @param VendorGuid - The vendor's GUID
579 @param Attributes - Pointer to the attribute
581 @param DataSize - Size of data
583 @param Data - Pointer to data
585 @retval EFI_SUCCESS - The interface could be successfully installed
587 @retval EFI_NOT_FOUND - The variable could not be discovered
589 @retval EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
595 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
596 IN CONST CHAR16
*VariableName
,
597 IN CONST EFI_GUID
*VariableGuid
,
598 OUT UINT32
*Attributes
,
599 IN OUT UINTN
*DataSize
,
604 return PeiGetVariable (
605 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer (),
606 (CHAR16
*)VariableName
,
607 (EFI_GUID
*)VariableGuid
,
615 Provide the get next variable functionality of the variable services.
617 @param PeiServices - General purpose services available to every PEIM.
618 @param VariabvleNameSize - The variable name's size.
619 @param VariableName - A pointer to the variable's name.
620 @param VendorGuid - A pointer to the EFI_GUID structure.
622 @param VariableNameSize - Size of the variable name
624 @param VariableName - The variable name
626 @param VendorGuid - The vendor's GUID
628 @retval EFI_SUCCESS - The interface could be successfully installed
630 @retval EFI_NOT_FOUND - The variable could not be discovered
635 PeiGetNextVariableName (
636 IN EFI_PEI_SERVICES
**PeiServices
,
637 IN OUT UINTN
*VariableNameSize
,
638 IN OUT CHAR16
*VariableName
,
639 IN OUT EFI_GUID
*VendorGuid
643 VARIABLE_POINTER_TRACK Variable
;
647 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
648 return EFI_INVALID_PARAMETER
;
651 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
653 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
657 if (VariableName
[0] != 0) {
659 // If variable name is not NULL, get next variable
661 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
664 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
665 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
666 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
667 ASSERT (NameSizeOfVariable (Variable
.CurrPtr
) != 0);
669 VarNameSize
= (UINTN
) NameSizeOfVariable (Variable
.CurrPtr
);
670 if (VarNameSize
<= *VariableNameSize
) {
671 (*PeiServices
)->CopyMem (VariableName
, GetVariableNamePtr (Variable
.CurrPtr
), VarNameSize
);
673 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
675 Status
= EFI_SUCCESS
;
677 Status
= EFI_BUFFER_TOO_SMALL
;
680 *VariableNameSize
= VarNameSize
;
686 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
693 return EFI_NOT_FOUND
;
697 Provide the get next variable functionality of the variable services.
699 @param PeiServices - General purpose services available to every PEIM.
700 @param VariabvleNameSize - The variable name's size.
701 @param VariableName - A pointer to the variable's name.
702 @param VariableGuid - A pointer to the EFI_GUID structure.
704 @param VariableNameSize - Size of the variable name
706 @param VariableName - The variable name
708 @param VendorGuid - The vendor's GUID
711 @retval EFI_SUCCESS - The interface could be successfully installed
713 @retval EFI_NOT_FOUND - The variable could not be discovered
718 PeiGetNextVariableName2 (
719 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
720 IN OUT UINTN
*VariableNameSize
,
721 IN OUT CHAR16
*VariableName
,
722 IN OUT EFI_GUID
*VariableGuid
726 return PeiGetNextVariableName (
727 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer (),