2 Framework PEIM to provide the Variable functionality
4 Copyright (c) 2006 - 2008 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 Status - EFI_SUCCESS if the interface could be successfully
59 PeimInitializeVariableServices (
60 IN EFI_PEI_FILE_HANDLE FileHandle
,
61 IN CONST EFI_PEI_SERVICES
**PeiServices
65 // Publish the variable capability to other modules
67 return (**PeiServices
).InstallPpi (PeiServices
, &mPpiListVariable
[0]);
72 This code gets the pointer to the first variable memory pointer byte
74 @param VarStoreHeader Pointer to the Variable Store Header.
76 @return VARIABLE_HEADER* Pointer to last unavailable Variable Header
81 IN VARIABLE_STORE_HEADER
*VarStoreHeader
85 // The end of variable store
87 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
91 This code gets the pointer to the last variable memory pointer byte
93 @param VarStoreHeader Pointer to the Variable Store Header.
95 @return VARIABLE_HEADER* Pointer to last unavailable Variable Header
100 IN VARIABLE_STORE_HEADER
*VarStoreHeader
105 // The end of variable store
107 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
112 This code checks if variable header is valid or not.
114 @param Variable Pointer to the Variable Header.
116 @retval TRUE Variable header is valid.
117 @retval FALSE Variable header is not valid.
122 IsValidVariableHeader (
123 IN VARIABLE_HEADER
*Variable
126 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
134 This code gets the size of name of variable.
136 @param Variable Pointer to the Variable Header.
138 @return UINTN Size of variable in bytes
143 IN VARIABLE_HEADER
*Variable
146 if (Variable
->State
== (UINT8
) (-1) ||
147 Variable
->DataSize
== (UINT32
) -1 ||
148 Variable
->NameSize
== (UINT32
) -1 ||
149 Variable
->Attributes
== (UINT32
) -1) {
152 return (UINTN
) Variable
->NameSize
;
156 This code gets the size of name of variable.
158 @param Variable Pointer to the Variable Header.
160 @return UINTN Size of variable in bytes
165 IN VARIABLE_HEADER
*Variable
168 if (Variable
->State
== (UINT8
) -1 ||
169 Variable
->DataSize
== (UINT32
) -1 ||
170 Variable
->NameSize
== (UINT32
) -1 ||
171 Variable
->Attributes
== (UINT32
) -1) {
174 return (UINTN
) Variable
->DataSize
;
178 This code gets the pointer to the variable name.
180 @param Variable Pointer to the Variable Header.
182 @return CHAR16* Pointer to Variable Name
187 IN VARIABLE_HEADER
*Variable
192 return (CHAR16
*) (Variable
+ 1);
196 This code gets the pointer to the variable data.
198 @param Variable Pointer to the Variable Header.
200 @return UINT8* Pointer to Variable Data
205 IN VARIABLE_HEADER
*Variable
211 // Be careful about pad size for alignment
213 Value
= (UINTN
) GetVariableNamePtr (Variable
);
214 Value
+= NameSizeOfVariable (Variable
);
215 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
217 return (UINT8
*) Value
;
221 This code gets the pointer to the next variable header.
223 @param Variable Pointer to the Variable Header.
225 @return VARIABLE_HEADER* Pointer to next variable header.
230 IN VARIABLE_HEADER
*Variable
236 if (!IsValidVariableHeader (Variable
)) {
240 Value
= (UINTN
) GetVariableDataPtr (Variable
);
241 Value
+= DataSizeOfVariable (Variable
);
242 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
245 // Be careful about pad size for alignment
247 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
251 This code gets the pointer to the variable name.
253 @param VarStoreHeader Pointer to the Variable Store Header.
255 @retval EfiRaw Variable store is raw
256 @retval EfiValid Variable store is valid
257 @retval EfiInvalid Variable store is invalid
260 VARIABLE_STORE_STATUS
262 GetVariableStoreStatus (
263 IN VARIABLE_STORE_HEADER
*VarStoreHeader
267 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
268 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
269 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
275 if (VarStoreHeader
->Signature
== 0xffffffff &&
276 VarStoreHeader
->Size
== 0xffffffff &&
277 VarStoreHeader
->Format
== 0xff &&
278 VarStoreHeader
->State
== 0xff
288 This function compares a variable with variable entries in database
290 @param Variable - Pointer to the variable in our database
291 @param VariableName - Name of the variable to compare to 'Variable'
292 @param VendorGuid - GUID of the variable to compare to 'Variable'
293 @param PtrTrack - Variable Track Pointer structure that contains
294 Variable Information.
296 @retval EFI_SUCCESS - Found match variable
297 @retval EFI_NOT_FOUND - Variable not found
301 CompareWithValidVariable (
302 IN VARIABLE_HEADER
*Variable
,
303 IN CONST CHAR16
*VariableName
,
304 IN CONST EFI_GUID
*VendorGuid
,
305 OUT VARIABLE_POINTER_TRACK
*PtrTrack
311 if (VariableName
[0] == 0) {
312 PtrTrack
->CurrPtr
= Variable
;
316 // Don't use CompareGuid function here for performance reasons.
317 // Instead we compare the GUID a UINT32 at a time and branch
318 // on the first failed comparison.
320 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
321 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
322 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
323 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
325 ASSERT (NameSizeOfVariable (Variable
) != 0);
326 Point
= (VOID
*) GetVariableNamePtr (Variable
);
327 if (!CompareMem (VariableName
, Point
, NameSizeOfVariable (Variable
))) {
328 PtrTrack
->CurrPtr
= Variable
;
334 return EFI_NOT_FOUND
;
338 This code finds variable in storage blocks (Non-Volatile)
340 @param PeiServices - General purpose services available to every PEIM.
341 @param VariableName - Name of the variable to be found
342 @param VendorGuid - Vendor GUID to be found.
343 @param PtrTrack - Variable Track Pointer structure that contains
344 Variable Information.
346 @retval EFI_SUCCESS - Variable found successfully
347 @retval EFI_NOT_FOUND - Variable not found
348 @retval EFI_INVALID_PARAMETER - Invalid variable name
354 IN EFI_PEI_SERVICES
**PeiServices
,
355 IN CONST CHAR16
*VariableName
,
356 IN CONST EFI_GUID
*VendorGuid
,
357 OUT VARIABLE_POINTER_TRACK
*PtrTrack
361 EFI_HOB_GUID_TYPE
*GuidHob
;
362 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
363 VARIABLE_HEADER
*Variable
;
364 VARIABLE_HEADER
*MaxIndex
;
365 VARIABLE_INDEX_TABLE
*IndexTable
;
369 if (VariableName
!= 0 && VendorGuid
== NULL
) {
370 return EFI_INVALID_PARAMETER
;
373 // No Variable Address equals zero, so 0 as initial value is safe.
377 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
378 if (GuidHob
== NULL
) {
379 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
380 IndexTable
->Length
= 0;
381 IndexTable
->StartPtr
= NULL
;
382 IndexTable
->EndPtr
= NULL
;
383 IndexTable
->GoneThrough
= 0;
385 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
386 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
388 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
390 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
391 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
392 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
398 if (IndexTable
->GoneThrough
) {
399 return EFI_NOT_FOUND
;
403 // If not found in HOB, then let's start from the MaxIndex we've found.
405 if (MaxIndex
!= NULL
) {
406 Variable
= GetNextVariablePtr (MaxIndex
);
408 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
409 Variable
= IndexTable
->StartPtr
;
411 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
412 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
413 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
415 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
416 return EFI_UNSUPPORTED
;
419 if (~VariableStoreHeader
->Size
== 0) {
420 return EFI_NOT_FOUND
;
423 // Find the variable by walk through non-volatile variable store
425 IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
426 IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
429 // Start Pointers for the variable.
430 // Actual Data Pointer where data can be written.
432 Variable
= IndexTable
->StartPtr
;
436 // Find the variable by walk through non-volatile variable store
438 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
439 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
441 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
442 if (Variable
->State
== VAR_ADDED
) {
444 // Record Variable in VariableIndex HOB
446 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
448 VariableIndexTableUpdate (IndexTable
, Variable
);
451 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
456 Variable
= GetNextVariablePtr (Variable
);
459 // If gone through the VariableStore, that means we never find in Firmware any more.
461 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
462 IndexTable
->GoneThrough
= 1;
465 PtrTrack
->CurrPtr
= NULL
;
467 return EFI_NOT_FOUND
;
471 Provide the read variable functionality of the variable services.
473 @param PeiServices - General purpose services available to every PEIM.
475 @param VariableName - The variable name
477 @param VendorGuid - The vendor's GUID
479 @param Attributes - Pointer to the attribute
481 @param DataSize - Size of data
483 @param Data - Pointer to data
485 @retval EFI_SUCCESS - The interface could be successfully installed
487 @retval EFI_NOT_FOUND - The variable could not be discovered
489 @retval EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
495 IN EFI_PEI_SERVICES
**PeiServices
,
496 IN CHAR16
*VariableName
,
497 IN EFI_GUID
* VendorGuid
,
498 OUT UINT32
*Attributes OPTIONAL
,
499 IN OUT UINTN
*DataSize
,
504 VARIABLE_POINTER_TRACK Variable
;
508 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
509 return EFI_INVALID_PARAMETER
;
512 // Find existing variable
514 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
516 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
522 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
523 if (*DataSize
>= VarDataSize
) {
525 // PO-TKW: Address one checking in this place
528 return EFI_INVALID_PARAMETER
;
531 (*PeiServices
)->CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
533 if (Attributes
!= NULL
) {
534 *Attributes
= Variable
.CurrPtr
->Attributes
;
537 *DataSize
= VarDataSize
;
540 *DataSize
= VarDataSize
;
541 return EFI_BUFFER_TOO_SMALL
;
546 Provide the read variable functionality of the variable services.
548 @param PeiServices - General purpose services available to every PEIM.
550 @param VariableName - The variable name
552 @param VendorGuid - The vendor's GUID
554 @param Attributes - Pointer to the attribute
556 @param DataSize - Size of data
558 @param Data - Pointer to data
560 @retval EFI_SUCCESS - The interface could be successfully installed
562 @retval EFI_NOT_FOUND - The variable could not be discovered
564 @retval EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
570 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
571 IN CONST CHAR16
*VariableName
,
572 IN CONST EFI_GUID
*VariableGuid
,
573 OUT UINT32
*Attributes
,
574 IN OUT UINTN
*DataSize
,
579 return PeiGetVariable (
580 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer (),
581 (CHAR16
*)VariableName
,
582 (EFI_GUID
*)VariableGuid
,
590 Provide the get next variable functionality of the variable services.
592 @param PeiServices - General purpose services available to every PEIM.
593 @param VariabvleNameSize - The variable name's size.
594 @param VariableName - A pointer to the variable's name.
595 @param VendorGuid - A pointer to the EFI_GUID structure.
597 @param VariableNameSize - Size of the variable name
599 @param VariableName - The variable name
601 @param VendorGuid - The vendor's GUID
603 @retval EFI_SUCCESS - The interface could be successfully installed
605 @retval EFI_NOT_FOUND - The variable could not be discovered
610 PeiGetNextVariableName (
611 IN EFI_PEI_SERVICES
**PeiServices
,
612 IN OUT UINTN
*VariableNameSize
,
613 IN OUT CHAR16
*VariableName
,
614 IN OUT EFI_GUID
*VendorGuid
618 VARIABLE_POINTER_TRACK Variable
;
622 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
623 return EFI_INVALID_PARAMETER
;
626 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
628 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
632 if (VariableName
[0] != 0) {
634 // If variable name is not NULL, get next variable
636 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
639 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
640 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
641 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
642 ASSERT (NameSizeOfVariable (Variable
.CurrPtr
) != 0);
644 VarNameSize
= (UINTN
) NameSizeOfVariable (Variable
.CurrPtr
);
645 if (VarNameSize
<= *VariableNameSize
) {
646 (*PeiServices
)->CopyMem (VariableName
, GetVariableNamePtr (Variable
.CurrPtr
), VarNameSize
);
648 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
650 Status
= EFI_SUCCESS
;
652 Status
= EFI_BUFFER_TOO_SMALL
;
655 *VariableNameSize
= VarNameSize
;
661 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
668 return EFI_NOT_FOUND
;
672 Provide the get next variable functionality of the variable services.
674 @param PeiServices - General purpose services available to every PEIM.
675 @param VariabvleNameSize - The variable name's size.
676 @param VariableName - A pointer to the variable's name.
677 @param VariableGuid - A pointer to the EFI_GUID structure.
679 @param VariableNameSize - Size of the variable name
681 @param VariableName - The variable name
683 @param VendorGuid - The vendor's GUID
686 @retval EFI_SUCCESS - The interface could be successfully installed
688 @retval EFI_NOT_FOUND - The variable could not be discovered
693 PeiGetNextVariableName2 (
694 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
695 IN OUT UINTN
*VariableNameSize
,
696 IN OUT CHAR16
*VariableName
,
697 IN OUT EFI_GUID
*VariableGuid
701 return PeiGetNextVariableName (
702 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer (),