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
);
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 CONST CHAR16
*VariableName
,
174 IN CONST 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 (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
), Variable
->NameSize
)) {
213 PtrTrack
->CurrPtr
= Variable
;
219 return EFI_NOT_FOUND
;
226 IN EFI_PEI_SERVICES
**PeiServices
,
227 IN CONST CHAR16
*VariableName
,
228 IN CONST 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 (&mEfiVariableIndexTableGuid
);
270 if (GuidHob
== NULL
) {
271 IndexTable
= BuildGuidHob (&mEfiVariableIndexTableGuid
, 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
++)
280 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
282 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
283 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
284 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
290 if (IndexTable
->GoneThrough
) {
291 return EFI_NOT_FOUND
;
295 // If not found in HOB, then let's start from the MaxIndex we've found.
297 if (MaxIndex
!= NULL
) {
298 Variable
= GetNextVariablePtr (MaxIndex
);
300 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
301 Variable
= IndexTable
->StartPtr
;
303 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
304 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
305 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
307 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
308 return EFI_UNSUPPORTED
;
311 if (~VariableStoreHeader
->Size
== 0) {
312 return EFI_NOT_FOUND
;
315 // Find the variable by walk through non-volatile variable store
317 IndexTable
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
318 IndexTable
->EndPtr
= (VARIABLE_HEADER
*) ((UINTN
) VariableStoreHeader
+ VariableStoreHeader
->Size
);
321 // Start Pointers for the variable.
322 // Actual Data Pointer where data can be written.
324 Variable
= IndexTable
->StartPtr
;
328 // Find the variable by walk through non-volatile variable store
330 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
331 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
333 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
334 if (Variable
->State
== VAR_ADDED
) {
336 // Record Variable in VariableIndex HOB
338 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
340 VariableIndexTableUpdate (IndexTable
, Variable
);
343 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
348 Variable
= GetNextVariablePtr (Variable
);
351 // If gone through the VariableStore, that means we never find in Firmware any more.
353 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
354 IndexTable
->GoneThrough
= 1;
357 PtrTrack
->CurrPtr
= NULL
;
359 return EFI_NOT_FOUND
;
365 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
366 IN CONST CHAR16
*VariableName
,
367 IN CONST EFI_GUID
*VariableGuid
,
368 OUT UINT32
*Attributes
,
369 IN OUT UINTN
*DataSize
,
376 Provide the read variable functionality of the variable services.
380 PeiServices - General purpose services available to every PEIM.
382 VariableName - The variable name
384 VendorGuid - The vendor's GUID
386 Attributes - Pointer to the attribute
388 DataSize - Size of data
390 Data - Pointer to data
394 EFI_SUCCESS - The interface could be successfully installed
396 EFI_NOT_FOUND - The variable could not be discovered
398 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
402 VARIABLE_POINTER_TRACK Variable
;
405 EFI_PEI_SERVICES
**PeiServices
;
407 PeiServices
= GetPeiServicesTablePointer ();
408 if (VariableName
== NULL
|| VariableGuid
== NULL
) {
409 return EFI_INVALID_PARAMETER
;
412 // Find existing variable
414 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
415 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
421 VarDataSize
= Variable
.CurrPtr
->DataSize
;
422 if (*DataSize
>= VarDataSize
) {
423 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
425 if (Attributes
!= NULL
) {
426 *Attributes
= Variable
.CurrPtr
->Attributes
;
429 *DataSize
= VarDataSize
;
432 *DataSize
= VarDataSize
;
433 return EFI_BUFFER_TOO_SMALL
;
439 PeiGetNextVariableName (
440 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
441 IN OUT UINTN
*VariableNameSize
,
442 IN OUT CHAR16
*VariableName
,
443 IN OUT EFI_GUID
*VariableGuid
449 Provide the get next variable functionality of the variable services.
453 PeiServices - General purpose services available to every PEIM.
454 VariabvleNameSize - The variable name's size.
455 VariableName - A pointer to the variable's name.
456 VariableGuid - A pointer to the EFI_GUID structure.
458 VariableNameSize - Size of the variable name
460 VariableName - The variable name
462 VendorGuid - The vendor's GUID
466 EFI_SUCCESS - The interface could be successfully installed
468 EFI_NOT_FOUND - The variable could not be discovered
472 VARIABLE_POINTER_TRACK Variable
;
475 EFI_PEI_SERVICES
**PeiServices
;
477 PeiServices
= GetPeiServicesTablePointer ();
478 if (VariableName
== NULL
) {
479 return EFI_INVALID_PARAMETER
;
482 Status
= FindVariable (PeiServices
, VariableName
, VariableGuid
, &Variable
);
483 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
487 if (VariableName
[0] != 0) {
489 // If variable name is not NULL, get next variable
491 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
494 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
495 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
496 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
497 VarNameSize
= (UINTN
) Variable
.CurrPtr
->NameSize
;
498 if (VarNameSize
<= *VariableNameSize
) {
499 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
501 (*PeiServices
)->CopyMem (VariableGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
503 Status
= EFI_SUCCESS
;
505 Status
= EFI_BUFFER_TOO_SMALL
;
508 *VariableNameSize
= VarNameSize
;
514 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
521 return EFI_NOT_FOUND
;