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
26 static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi
= {
28 PeiGetNextVariableName
31 static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
= {
32 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
33 &gEfiPeiReadOnlyVariablePpiGuid
,
37 EFI_GUID gEfiVariableIndexTableGuid
= EFI_VARIABLE_INDEX_TABLE_GUID
;
41 PeimInitializeVariableServices (
42 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
43 IN EFI_PEI_SERVICES
**PeiServices
49 Provide the functionality of the variable services.
53 FfsHeadher - The FFS file header
54 PeiServices - General purpose services available to every PEIM.
58 Status - EFI_SUCCESS if the interface could be successfully
64 // Publish the variable capability to other modules
66 return (**PeiServices
).InstallPpi (PeiServices
, &mPpiListVariable
);
73 IN VARIABLE_HEADER
*Variable
79 This code checks if variable header is valid or not.
82 Variable Pointer to the Variable Header.
85 TRUE Variable header is valid.
86 FALSE Variable header is not valid.
90 return (VARIABLE_HEADER
*) ((UINTN
) GET_VARIABLE_DATA_PTR (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
96 IsValidVariableHeader (
97 IN VARIABLE_HEADER
*Variable
103 This code checks if variable header is valid or not.
106 Variable Pointer to the Variable Header.
109 TRUE Variable header is valid.
110 FALSE Variable header is not valid.
114 if (Variable
== NULL
||
115 Variable
->StartId
!= VARIABLE_DATA
||
116 (sizeof (VARIABLE_HEADER
) + Variable
->DataSize
+ Variable
->NameSize
) > MAX_VARIABLE_SIZE
125 VARIABLE_STORE_STATUS
127 GetVariableStoreStatus (
128 IN VARIABLE_STORE_HEADER
*VarStoreHeader
134 This code gets the pointer to the variable name.
138 VarStoreHeader Pointer to the Variable Store Header.
142 EfiRaw Variable store is raw
143 EfiValid Variable store is valid
144 EfiInvalid Variable store is invalid
148 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
149 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
150 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
156 if (VarStoreHeader
->Signature
== 0xffffffff &&
157 VarStoreHeader
->Size
== 0xffffffff &&
158 VarStoreHeader
->Format
== 0xff &&
159 VarStoreHeader
->State
== 0xff
170 CompareWithValidVariable (
171 IN VARIABLE_HEADER
*Variable
,
172 IN CHAR16
*VariableName
,
173 IN EFI_GUID
*VendorGuid
,
174 OUT VARIABLE_POINTER_TRACK
*PtrTrack
180 This function compares a variable with variable entries in database
184 Variable - Pointer to the variable in our database
185 VariableName - Name of the variable to compare to 'Variable'
186 VendorGuid - GUID of the variable to compare to 'Variable'
187 PtrTrack - Variable Track Pointer structure that contains
188 Variable Information.
192 EFI_SUCCESS - Found match variable
193 EFI_NOT_FOUND - Variable not found
197 if (VariableName
[0] == 0) {
198 PtrTrack
->CurrPtr
= Variable
;
202 // Don't use CompareGuid function here for performance reasons.
203 // Instead we compare the GUID a UINT32 at a time and branch
204 // on the first failed comparison.
206 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &Variable
->VendorGuid
)[0]) &&
207 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &Variable
->VendorGuid
)[1]) &&
208 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &Variable
->VendorGuid
)[2]) &&
209 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &Variable
->VendorGuid
)[3])
211 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
), Variable
->NameSize
)) {
212 PtrTrack
->CurrPtr
= Variable
;
218 return EFI_NOT_FOUND
;
225 IN EFI_PEI_SERVICES
**PeiServices
,
226 IN CHAR16
*VariableName
,
227 IN EFI_GUID
*VendorGuid
,
228 OUT VARIABLE_POINTER_TRACK
*PtrTrack
234 This code finds variable in storage blocks (Non-Volatile)
238 PeiServices - General purpose services available to every PEIM.
239 VariableName - Name of the variable to be found
240 VendorGuid - Vendor GUID to be found.
241 PtrTrack - Variable Track Pointer structure that contains
242 Variable Information.
246 EFI_SUCCESS - Variable found successfully
247 EFI_NOT_FOUND - Variable not found
248 EFI_INVALID_PARAMETER - Invalid variable name
252 EFI_HOB_GUID_TYPE
*GuidHob
;
253 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
254 VARIABLE_HEADER
*Variable
;
255 VARIABLE_HEADER
*MaxIndex
;
256 VARIABLE_INDEX_TABLE
*IndexTable
;
260 if (VariableName
!= 0 && VendorGuid
== NULL
) {
261 return EFI_INVALID_PARAMETER
;
264 // No Variable Address equals zero, so 0 as initial value is safe.
268 GuidHob
= GetFirstGuidHob (&gEfiVariableIndexTableGuid
);
269 if (GuidHob
== NULL
) {
270 IndexTable
= BuildGuidHob (&gEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
271 IndexTable
->Length
= 0;
272 IndexTable
->StartPtr
= NULL
;
273 IndexTable
->EndPtr
= NULL
;
274 IndexTable
->GoneThrough
= 0;
276 IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
277 for (Count
= 0; Count
< IndexTable
->Length
; Count
++)
279 MaxIndex
= GetVariableByIndex (IndexTable
, Count
);
281 if (CompareWithValidVariable (MaxIndex
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
282 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
283 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
289 if (IndexTable
->GoneThrough
) {
290 return EFI_NOT_FOUND
;
294 // If not found in HOB, then let's start from the MaxIndex we've found.
296 if (MaxIndex
!= NULL
) {
297 Variable
= GetNextVariablePtr (MaxIndex
);
299 if (IndexTable
->StartPtr
|| IndexTable
->EndPtr
) {
300 Variable
= IndexTable
->StartPtr
;
302 VariableBase
= (UINT8
*) (UINTN
) PcdGet32 (PcdFlashNvStorageVariableBase
);
303 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (VariableBase
+ \
304 ((EFI_FIRMWARE_VOLUME_HEADER
*) (VariableBase
)) -> HeaderLength
);
306 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
307 return EFI_UNSUPPORTED
;
310 if (~VariableStoreHeader
->Size
== 0) {
311 return EFI_NOT_FOUND
;
314 // Find the variable by walk through non-volatile variable store
316 IndexTable
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
317 IndexTable
->EndPtr
= (VARIABLE_HEADER
*) ((UINTN
) VariableStoreHeader
+ VariableStoreHeader
->Size
);
320 // Start Pointers for the variable.
321 // Actual Data Pointer where data can be written.
323 Variable
= IndexTable
->StartPtr
;
327 // Find the variable by walk through non-volatile variable store
329 PtrTrack
->StartPtr
= IndexTable
->StartPtr
;
330 PtrTrack
->EndPtr
= IndexTable
->EndPtr
;
332 while (IsValidVariableHeader (Variable
) && (Variable
<= IndexTable
->EndPtr
)) {
333 if (Variable
->State
== VAR_ADDED
) {
335 // Record Variable in VariableIndex HOB
337 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
)
339 VariableIndexTableUpdate (IndexTable
, Variable
);
342 if (CompareWithValidVariable (Variable
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
347 Variable
= GetNextVariablePtr (Variable
);
350 // If gone through the VariableStore, that means we never find in Firmware any more.
352 if (IndexTable
->Length
< VARIABLE_INDEX_TABLE_VOLUME
) {
353 IndexTable
->GoneThrough
= 1;
356 PtrTrack
->CurrPtr
= NULL
;
358 return EFI_NOT_FOUND
;
364 IN EFI_PEI_SERVICES
**PeiServices
,
365 IN CHAR16
*VariableName
,
366 IN EFI_GUID
* VendorGuid
,
367 OUT UINT32
*Attributes OPTIONAL
,
368 IN OUT UINTN
*DataSize
,
375 Provide the read variable functionality of the variable services.
379 PeiServices - General purpose services available to every PEIM.
381 VariableName - The variable name
383 VendorGuid - The vendor's GUID
385 Attributes - Pointer to the attribute
387 DataSize - Size of data
389 Data - Pointer to data
393 EFI_SUCCESS - The interface could be successfully installed
395 EFI_NOT_FOUND - The variable could not be discovered
397 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
401 VARIABLE_POINTER_TRACK Variable
;
405 if (VariableName
== NULL
|| VendorGuid
== NULL
) {
406 return EFI_INVALID_PARAMETER
;
409 // Find existing variable
411 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
413 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
419 VarDataSize
= Variable
.CurrPtr
->DataSize
;
420 if (*DataSize
>= VarDataSize
) {
421 (*PeiServices
)->CopyMem (Data
, GET_VARIABLE_DATA_PTR (Variable
.CurrPtr
), VarDataSize
);
423 if (Attributes
!= NULL
) {
424 *Attributes
= Variable
.CurrPtr
->Attributes
;
427 *DataSize
= VarDataSize
;
430 *DataSize
= VarDataSize
;
431 return EFI_BUFFER_TOO_SMALL
;
437 PeiGetNextVariableName (
438 IN EFI_PEI_SERVICES
**PeiServices
,
439 IN OUT UINTN
*VariableNameSize
,
440 IN OUT CHAR16
*VariableName
,
441 IN OUT EFI_GUID
*VendorGuid
447 Provide the get next variable functionality of the variable services.
451 PeiServices - General purpose services available to every PEIM.
452 VariabvleNameSize - The variable name's size.
453 VariableName - A pointer to the variable's name.
454 VendorGuid - A pointer to the EFI_GUID structure.
456 VariableNameSize - Size of the variable name
458 VariableName - The variable name
460 VendorGuid - The vendor's GUID
464 EFI_SUCCESS - The interface could be successfully installed
466 EFI_NOT_FOUND - The variable could not be discovered
470 VARIABLE_POINTER_TRACK Variable
;
474 if (VariableName
== NULL
) {
475 return EFI_INVALID_PARAMETER
;
478 Status
= FindVariable (PeiServices
, VariableName
, VendorGuid
, &Variable
);
480 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
484 if (VariableName
[0] != 0) {
486 // If variable name is not NULL, get next variable
488 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
491 while (!(Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
)) {
492 if (IsValidVariableHeader (Variable
.CurrPtr
)) {
493 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
494 VarNameSize
= (UINTN
) Variable
.CurrPtr
->NameSize
;
495 if (VarNameSize
<= *VariableNameSize
) {
496 (*PeiServices
)->CopyMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
), VarNameSize
);
498 (*PeiServices
)->CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
500 Status
= EFI_SUCCESS
;
502 Status
= EFI_BUFFER_TOO_SMALL
;
505 *VariableNameSize
= VarNameSize
;
511 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
518 return EFI_NOT_FOUND
;