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 Framework PEIM to provide the Variable functionality
22 // The package level header files this module uses
27 // The protocols, PPI and GUID defintions for this module
29 #include <Ppi/ReadOnlyVariable.h>
31 // The Library classes this module consumes
33 #include <Library/DebugLib.h>
34 #include <Library/PeimEntryPoint.h>
35 #include <Library/HobLib.h>
36 #include <Library/PcdLib.h>
37 #include <Library/BaseMemoryLib.h>
45 static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi
= {
47 PeiGetNextVariableName
50 static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
= {
51 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
52 &gEfiPeiReadOnlyVariablePpiGuid
,
56 EFI_GUID mEfiVariableIndexTableGuid
= EFI_VARIABLE_INDEX_TABLE_GUID
;
60 PeimInitializeVariableServices (
61 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
62 IN EFI_PEI_SERVICES
**PeiServices
68 Provide the functionality of the variable services.
72 FfsHeadher - The FFS file header
73 PeiServices - General purpose services available to every PEIM.
77 Status - EFI_SUCCESS if the interface could be successfully
83 // Publish the variable capability to other modules
85 return (**PeiServices
).InstallPpi (PeiServices
, &mPpiListVariable
);
92 IN VARIABLE_HEADER
*Variable
98 This code checks if variable header is valid or not.
101 Variable Pointer to the Variable Header.
104 TRUE Variable header is valid.
105 FALSE Variable header is not valid.
109 return (VARIABLE_HEADER
*) ((UINTN
) GET_VARIABLE_DATA_PTR (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
115 IsValidVariableHeader (
116 IN VARIABLE_HEADER
*Variable
122 This code checks if variable header is valid or not.
125 Variable Pointer to the Variable Header.
128 TRUE Variable header is valid.
129 FALSE Variable header is not valid.
133 if (Variable
== NULL
||
134 Variable
->StartId
!= VARIABLE_DATA
||
135 (sizeof (VARIABLE_HEADER
) + Variable
->DataSize
+ Variable
->NameSize
) > MAX_VARIABLE_SIZE
144 VARIABLE_STORE_STATUS
146 GetVariableStoreStatus (
147 IN VARIABLE_STORE_HEADER
*VarStoreHeader
153 This code gets the pointer to the variable name.
157 VarStoreHeader Pointer to the Variable Store Header.
161 EfiRaw Variable store is raw
162 EfiValid Variable store is valid
163 EfiInvalid Variable store is invalid
167 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
168 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
169 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
175 if (VarStoreHeader
->Signature
== 0xffffffff &&
176 VarStoreHeader
->Size
== 0xffffffff &&
177 VarStoreHeader
->Format
== 0xff &&
178 VarStoreHeader
->State
== 0xff
189 CompareWithValidVariable (
190 IN VARIABLE_HEADER
*Variable
,
191 IN CHAR16
*VariableName
,
192 IN EFI_GUID
*VendorGuid
,
193 OUT VARIABLE_POINTER_TRACK
*PtrTrack
199 This function compares a variable with variable entries in database
203 Variable - Pointer to the variable in our database
204 VariableName - Name of the variable to compare to 'Variable'
205 VendorGuid - GUID of the variable to compare to 'Variable'
206 PtrTrack - Variable Track Pointer structure that contains
207 Variable Information.
211 EFI_SUCCESS - Found match variable
212 EFI_NOT_FOUND - Variable not found
216 if (VariableName
[0] == 0) {
217 PtrTrack
->CurrPtr
= Variable
;
221 // Don't use CompareGuid function here for performance reasons.
222 // Instead we compare the GUID a UINT32 at a time and branch
223 // on the first failed comparison.
225 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
226 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
227 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
228 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
230 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
), Variable
->NameSize
)) {
231 PtrTrack
->CurrPtr
= Variable
;
237 return EFI_NOT_FOUND
;
244 IN EFI_PEI_SERVICES
**PeiServices
,
245 IN CHAR16
*VariableName
,
246 IN EFI_GUID
*VendorGuid
,
247 OUT VARIABLE_POINTER_TRACK
*PtrTrack
253 This code finds variable in storage blocks (Non-Volatile)
257 PeiServices - General purpose services available to every PEIM.
258 VariableName - Name of the variable to be found
259 VendorGuid - Vendor GUID to be found.
260 PtrTrack - Variable Track Pointer structure that contains
261 Variable Information.
265 EFI_SUCCESS - Variable found successfully
266 EFI_NOT_FOUND - Variable not found
267 EFI_INVALID_PARAMETER - Invalid variable name
271 EFI_HOB_GUID_TYPE
*GuidHob
;
272 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
273 VARIABLE_HEADER
*Variable
;
274 VARIABLE_HEADER
*MaxIndex
;
275 VARIABLE_INDEX_TABLE
*IndexTable
;
279 if (VariableName
!= 0 && VendorGuid
== NULL
) {
280 return EFI_INVALID_PARAMETER
;
283 // No Variable Address equals zero, so 0 as initial value is safe.
287 GuidHob
= GetFirstGuidHob (&mEfiVariableIndexTableGuid
);
288 if (GuidHob
== NULL
) {
289 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
290 IndexTable
->Length
= 0;
291 IndexTable
->StartPtr
= NULL
;
292 IndexTable
->EndPtr
= NULL
;
293 IndexTable
->GoneThrough
= 0;
295 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
296 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
298 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
300 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
301 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
302 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
308 if (IndexTable
->GoneThrough
) {
309 return EFI_NOT_FOUND
;
313 // If not found in HOB, then let's start from the MaxIndex we've found.
315 if (MaxIndex
!= NULL
) {
316 Variable
= GetNextVariablePtr (MaxIndex
);
318 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
319 Variable
= IndexTable
->StartPtr
;
321 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
322 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
323 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
325 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
326 return EFI_UNSUPPORTED
;
329 if (~VariableStoreHeader
->Size
== 0) {
330 return EFI_NOT_FOUND
;
333 // Find the variable by walk through non-volatile variable store
335 IndexTable
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
336 IndexTable
->EndPtr
= (VARIABLE_HEADER
*) ((UINTN
) VariableStoreHeader
+ VariableStoreHeader
->Size
);
339 // Start Pointers for the variable.
340 // Actual Data Pointer where data can be written.
342 Variable
= IndexTable
->StartPtr
;
346 // Find the variable by walk through non-volatile variable store
348 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
349 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
351 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
352 if (Variable
->State
== VAR_ADDED
) {
354 // Record Variable in VariableIndex HOB
356 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
358 VariableIndexTableUpdate (IndexTable
, Variable
);
361 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
366 Variable
= GetNextVariablePtr (Variable
);
369 // If gone through the VariableStore, that means we never find in Firmware any more.
371 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
372 IndexTable
->GoneThrough
= 1;
375 PtrTrack
->CurrPtr
= NULL
;
377 return EFI_NOT_FOUND
;
383 IN EFI_PEI_SERVICES
**PeiServices
,
384 IN CHAR16
*VariableName
,
385 IN EFI_GUID
* VendorGuid
,
386 OUT UINT32
*Attributes OPTIONAL
,
387 IN OUT UINTN
*DataSize
,
394 Provide the read variable functionality of the variable services.
398 PeiServices - General purpose services available to every PEIM.
400 VariableName - The variable name
402 VendorGuid - The vendor's GUID
404 Attributes - Pointer to the attribute
406 DataSize - Size of data
408 Data - Pointer to data
412 EFI_SUCCESS - The interface could be successfully installed
414 EFI_NOT_FOUND - The variable could not be discovered
416 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
420 VARIABLE_POINTER_TRACK Variable
;
424 if (VariableName
== NULL
|| VendorGuid
== NULL
) {
425 return EFI_INVALID_PARAMETER
;
428 // Find existing variable
430 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
432 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
438 VarDataSize
= Variable
.CurrPtr
->DataSize
;
439 if (*DataSize
>= VarDataSize
) {
440 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
442 if (Attributes
!= NULL
) {
443 *Attributes
= Variable
.CurrPtr
->Attributes
;
446 *DataSize
= VarDataSize
;
449 *DataSize
= VarDataSize
;
450 return EFI_BUFFER_TOO_SMALL
;
456 PeiGetNextVariableName (
457 IN EFI_PEI_SERVICES
**PeiServices
,
458 IN OUT UINTN
*VariableNameSize
,
459 IN OUT CHAR16
*VariableName
,
460 IN OUT EFI_GUID
*VendorGuid
466 Provide the get next variable functionality of the variable services.
470 PeiServices - General purpose services available to every PEIM.
471 VariabvleNameSize - The variable name's size.
472 VariableName - A pointer to the variable's name.
473 VendorGuid - A pointer to the EFI_GUID structure.
475 VariableNameSize - Size of the variable name
477 VariableName - The variable name
479 VendorGuid - The vendor's GUID
483 EFI_SUCCESS - The interface could be successfully installed
485 EFI_NOT_FOUND - The variable could not be discovered
489 VARIABLE_POINTER_TRACK Variable
;
493 if (VariableName
== NULL
) {
494 return EFI_INVALID_PARAMETER
;
497 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
499 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
503 if (VariableName
[0] != 0) {
505 // If variable name is not NULL, get next variable
507 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
510 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
511 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
512 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
513 VarNameSize
= (UINTN
) Variable
.CurrPtr
->NameSize
;
514 if (VarNameSize
<= *VariableNameSize
) {
515 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
517 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
519 Status
= EFI_SUCCESS
;
521 Status
= EFI_BUFFER_TOO_SMALL
;
524 *VariableNameSize
= VarNameSize
;
530 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
537 return EFI_NOT_FOUND
;