2007-10-05 16:40:23 +02:00
/** @file
2008-04-09 09:07:50 +02:00
Implement all four UEFI Runtime Variable services for the nonvolatile
and volatile storage space and install variable architecture protocol .
2007-10-05 16:40:23 +02:00
2010-04-24 11:33:45 +02:00
Copyright ( c ) 2006 - 2010 , Intel Corporation . All rights reserved . < BR >
This program and the accompanying materials
2008-04-09 09:07:50 +02:00
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution . The full text of the license may be found at
http : //opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN " AS IS " BASIS ,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND , EITHER EXPRESS OR IMPLIED .
2007-07-19 12:09:07 +02:00
2007-10-05 16:40:23 +02:00
* */
2007-07-19 12:09:07 +02:00
# include "Variable.h"
2007-10-04 23:01:21 +02:00
2008-01-17 10:59:51 +01:00
VARIABLE_MODULE_GLOBAL * mVariableModuleGlobal ;
2007-10-05 16:40:23 +02:00
EFI_EVENT mVirtualAddressChangeEvent = NULL ;
EFI_HANDLE mHandle = NULL ;
2009-04-27 09:06:01 +02:00
///
/// The size of a 3 character ISO639 language code.
///
# define ISO_639_2_ENTRY_SIZE 3
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
///
/// The current Hii implementation accesses this variable many times on every boot.
/// Other common variables are only accessed once. This is why this cache algorithm
/// only targets a single variable. Probably to get an performance improvement out of
/// a Cache you would need a cache that improves the search performance for a variable.
///
2008-12-03 09:52:39 +01:00
VARIABLE_CACHE_ENTRY mVariableCache [ ] = {
{
& gEfiGlobalVariableGuid ,
L " Lang " ,
0x00000000 ,
0x00 ,
NULL
2009-04-27 09:06:01 +02:00
} ,
{
& gEfiGlobalVariableGuid ,
L " PlatformLang " ,
0x00000000 ,
0x00 ,
NULL
2008-12-03 09:52:39 +01:00
}
} ;
2009-04-27 09:06:01 +02:00
VARIABLE_INFO_ENTRY * gVariableInfo = NULL ;
EFI_EVENT mFvbRegistration = NULL ;
/**
Update the variable region with Variable information . These are the same
arguments as the EFI Variable services .
@ param [ in ] VariableName Name of variable
@ param [ in ] VendorGuid Guid of variable
@ param [ in ] Data Variable data
@ param [ in ] DataSize Size of data . 0 means delete
@ param [ in ] Attributes Attribues of the variable
@ param [ in ] Variable The variable information which is used to keep track of variable usage .
2009-03-09 07:39:13 +01:00
2009-04-27 09:06:01 +02:00
@ retval EFI_SUCCESS The update operation is success .
@ retval EFI_OUT_OF_RESOURCES Variable region is full , can not write other data into this region .
* */
EFI_STATUS
EFIAPI
UpdateVariable (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
IN VOID * Data ,
IN UINTN DataSize ,
IN UINT32 Attributes OPTIONAL ,
IN VARIABLE_POINTER_TRACK * Variable
) ;
2008-12-03 09:52:39 +01:00
2008-12-12 10:27:17 +01:00
/**
Acquires lock only at boot time . Simply returns at runtime .
This is a temperary function which will be removed when
EfiAcquireLock ( ) in UefiLib can handle the call in UEFI
Runtimer driver in RT phase .
It calls EfiAcquireLock ( ) at boot time , and simply returns
at runtime .
@ param Lock A pointer to the lock to acquire
* */
2007-07-19 12:09:07 +02:00
VOID
AcquireLockOnlyAtBootTime (
IN EFI_LOCK * Lock
)
{
if ( ! EfiAtRuntime ( ) ) {
EfiAcquireLock ( Lock ) ;
}
}
2008-12-12 10:27:17 +01:00
/**
Releases lock only at boot time . Simply returns at runtime .
This is a temperary function which will be removed when
EfiReleaseLock ( ) in UefiLib can handle the call in UEFI
Runtimer driver in RT phase .
It calls EfiReleaseLock ( ) at boot time , and simply returns
at runtime .
@ param Lock A pointer to the lock to release
* */
2007-07-19 12:09:07 +02:00
VOID
ReleaseLockOnlyAtBootTime (
IN EFI_LOCK * Lock
)
{
if ( ! EfiAtRuntime ( ) ) {
EfiReleaseLock ( Lock ) ;
}
}
2007-10-04 23:01:21 +02:00
2007-10-05 16:40:23 +02:00
/**
Routine used to track statistical information about variable usage .
The data is stored in the EFI system table so it can be accessed later .
VariableInfo . efi can dump out the table . Only Boot Services variable
accesses are tracked by this code . The PcdVariableCollectStatistics
build flag controls if this feature is enabled .
A read that hits in the cache will have Read and Cache true for
the transaction . Data is allocated by this routine , but never
freed .
@ param [ in ] VariableName Name of the Variable to track
@ param [ in ] VendorGuid Guid of the Variable to track
@ param [ in ] Volatile TRUE if volatile FALSE if non - volatile
@ param [ in ] Read TRUE if GetVariable ( ) was called
@ param [ in ] Write TRUE if SetVariable ( ) was called
@ param [ in ] Delete TRUE if deleted via SetVariable ( )
@ param [ in ] Cache TRUE for a cache hit .
* */
2007-10-04 23:01:21 +02:00
VOID
UpdateVariableInfo (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
IN BOOLEAN Volatile ,
IN BOOLEAN Read ,
IN BOOLEAN Write ,
IN BOOLEAN Delete ,
IN BOOLEAN Cache
)
{
VARIABLE_INFO_ENTRY * Entry ;
if ( FeaturePcdGet ( PcdVariableCollectStatistics ) ) {
if ( EfiAtRuntime ( ) ) {
// Don't collect statistics at runtime
return ;
}
if ( gVariableInfo = = NULL ) {
2007-10-05 16:40:23 +02:00
//
// on the first call allocate a entry and place a pointer to it in
// the EFI System Table
//
2007-10-04 23:01:21 +02:00
gVariableInfo = AllocateZeroPool ( sizeof ( VARIABLE_INFO_ENTRY ) ) ;
2007-10-05 16:40:23 +02:00
ASSERT ( gVariableInfo ! = NULL ) ;
2007-10-04 23:01:21 +02:00
CopyGuid ( & gVariableInfo - > VendorGuid , VendorGuid ) ;
2009-06-03 10:48:09 +02:00
gVariableInfo - > Name = AllocatePool ( StrSize ( VariableName ) ) ;
2009-01-16 09:14:39 +01:00
ASSERT ( gVariableInfo - > Name ! = NULL ) ;
2007-10-04 23:01:21 +02:00
StrCpy ( gVariableInfo - > Name , VariableName ) ;
gVariableInfo - > Volatile = Volatile ;
2009-02-27 06:35:08 +01:00
gBS - > InstallConfigurationTable ( & gEfiVariableGuid , gVariableInfo ) ;
2007-10-04 23:01:21 +02:00
}
for ( Entry = gVariableInfo ; Entry ! = NULL ; Entry = Entry - > Next ) {
if ( CompareGuid ( VendorGuid , & Entry - > VendorGuid ) ) {
if ( StrCmp ( VariableName , Entry - > Name ) = = 0 ) {
if ( Read ) {
Entry - > ReadCount + + ;
}
if ( Write ) {
Entry - > WriteCount + + ;
}
if ( Delete ) {
Entry - > DeleteCount + + ;
}
if ( Cache ) {
Entry - > CacheCount + + ;
}
return ;
}
}
if ( Entry - > Next = = NULL ) {
2007-10-05 16:40:23 +02:00
//
// If the entry is not in the table add it.
// Next iteration of the loop will fill in the data
//
2007-10-04 23:01:21 +02:00
Entry - > Next = AllocateZeroPool ( sizeof ( VARIABLE_INFO_ENTRY ) ) ;
2007-10-05 16:40:23 +02:00
ASSERT ( Entry - > Next ! = NULL ) ;
2007-10-04 23:01:21 +02:00
CopyGuid ( & Entry - > Next - > VendorGuid , VendorGuid ) ;
2009-06-03 10:48:09 +02:00
Entry - > Next - > Name = AllocatePool ( StrSize ( VariableName ) ) ;
2009-01-16 09:14:39 +01:00
ASSERT ( Entry - > Next - > Name ! = NULL ) ;
2007-10-04 23:01:21 +02:00
StrCpy ( Entry - > Next - > Name , VariableName ) ;
Entry - > Next - > Volatile = Volatile ;
}
}
}
}
2008-12-12 10:27:17 +01:00
/**
2007-07-19 12:09:07 +02:00
This code checks if variable header is valid or not .
2008-12-12 10:27:17 +01:00
@ param Variable Pointer to the Variable Header .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
@ retval TRUE Variable header is valid .
@ retval FALSE Variable header is not valid .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
BOOLEAN
IsValidVariableHeader (
IN VARIABLE_HEADER * Variable
)
2007-07-19 12:09:07 +02:00
{
2008-01-09 11:10:16 +01:00
if ( Variable = = NULL | | Variable - > StartId ! = VARIABLE_DATA ) {
2007-07-19 12:09:07 +02:00
return FALSE ;
}
return TRUE ;
}
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
/**
This function writes data to the FWH at the correct LBA even if the LBAs
are fragmented .
@ param Global Pointer to VARAIBLE_GLOBAL structure
@ param Volatile Point out the Variable is Volatile or Non - Volatile
@ param SetByIndex TRUE if target pointer is given as index
FALSE if target pointer is absolute
2009-03-09 07:39:13 +01:00
@ param Fvb Pointer to the writable FVB protocol
2008-12-12 10:27:17 +01:00
@ param DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
structure
@ param DataSize Size of data to be written
@ param Buffer Pointer to the buffer from which data is written
@ retval EFI_INVALID_PARAMETER Parameters not valid
@ retval EFI_SUCCESS Variable store successfully updated
* */
2007-07-19 12:09:07 +02:00
EFI_STATUS
UpdateVariableStore (
2009-03-09 07:39:13 +01:00
IN VARIABLE_GLOBAL * Global ,
IN BOOLEAN Volatile ,
IN BOOLEAN SetByIndex ,
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL * Fvb ,
IN UINTN DataPtrIndex ,
IN UINT32 DataSize ,
IN UINT8 * Buffer
2007-07-19 12:09:07 +02:00
)
{
EFI_FV_BLOCK_MAP_ENTRY * PtrBlockMapEntry ;
UINTN BlockIndex2 ;
UINTN LinearOffset ;
UINTN CurrWriteSize ;
UINTN CurrWritePtr ;
UINT8 * CurrBuffer ;
EFI_LBA LbaNumber ;
UINTN Size ;
EFI_FIRMWARE_VOLUME_HEADER * FwVolHeader ;
VARIABLE_STORE_HEADER * VolatileBase ;
EFI_PHYSICAL_ADDRESS FvVolHdr ;
EFI_PHYSICAL_ADDRESS DataPtr ;
EFI_STATUS Status ;
FwVolHeader = NULL ;
DataPtr = DataPtrIndex ;
//
// Check if the Data is Volatile
//
if ( ! Volatile ) {
2009-03-09 07:39:13 +01:00
Status = Fvb - > GetPhysicalAddress ( Fvb , & FvVolHdr ) ;
ASSERT_EFI_ERROR ( Status ) ;
2007-07-19 12:09:07 +02:00
FwVolHeader = ( EFI_FIRMWARE_VOLUME_HEADER * ) ( ( UINTN ) FvVolHdr ) ;
//
// Data Pointer should point to the actual Address where data is to be
// written
//
if ( SetByIndex ) {
2007-10-05 16:40:23 +02:00
DataPtr + = mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ;
2007-07-19 12:09:07 +02:00
}
if ( ( DataPtr + DataSize ) > = ( ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) ( ( UINT8 * ) FwVolHeader + FwVolHeader - > FvLength ) ) ) {
return EFI_INVALID_PARAMETER ;
}
} else {
//
// Data Pointer should point to the actual Address where data is to be
// written
//
2007-10-05 16:40:23 +02:00
VolatileBase = ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ) ;
2007-07-19 12:09:07 +02:00
if ( SetByIndex ) {
2007-10-05 16:40:23 +02:00
DataPtr + = mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ;
2007-07-19 12:09:07 +02:00
}
if ( ( DataPtr + DataSize ) > = ( ( UINTN ) ( ( UINT8 * ) VolatileBase + VolatileBase - > Size ) ) ) {
return EFI_INVALID_PARAMETER ;
}
2007-09-17 05:50:40 +02:00
//
// If Volatile Variable just do a simple mem copy.
//
CopyMem ( ( UINT8 * ) ( UINTN ) DataPtr , Buffer , DataSize ) ;
2007-07-19 12:09:07 +02:00
return EFI_SUCCESS ;
}
2007-09-17 05:50:40 +02:00
2007-07-19 12:09:07 +02:00
//
// If we are here we are dealing with Non-Volatile Variables
//
LinearOffset = ( UINTN ) FwVolHeader ;
CurrWritePtr = ( UINTN ) DataPtr ;
CurrWriteSize = DataSize ;
CurrBuffer = Buffer ;
LbaNumber = 0 ;
if ( CurrWritePtr < LinearOffset ) {
return EFI_INVALID_PARAMETER ;
}
for ( PtrBlockMapEntry = FwVolHeader - > BlockMap ; PtrBlockMapEntry - > NumBlocks ! = 0 ; PtrBlockMapEntry + + ) {
for ( BlockIndex2 = 0 ; BlockIndex2 < PtrBlockMapEntry - > NumBlocks ; BlockIndex2 + + ) {
//
// Check to see if the Variable Writes are spanning through multiple
// blocks.
//
if ( ( CurrWritePtr > = LinearOffset ) & & ( CurrWritePtr < LinearOffset + PtrBlockMapEntry - > Length ) ) {
if ( ( CurrWritePtr + CurrWriteSize ) < = ( LinearOffset + PtrBlockMapEntry - > Length ) ) {
2009-03-09 07:39:13 +01:00
Status = Fvb - > Write (
Fvb ,
2007-07-19 12:09:07 +02:00
LbaNumber ,
( UINTN ) ( CurrWritePtr - LinearOffset ) ,
& CurrWriteSize ,
CurrBuffer
) ;
2009-03-09 07:39:13 +01:00
return Status ;
2007-07-19 12:09:07 +02:00
} else {
Size = ( UINT32 ) ( LinearOffset + PtrBlockMapEntry - > Length - CurrWritePtr ) ;
2009-03-09 07:39:13 +01:00
Status = Fvb - > Write (
Fvb ,
2007-07-19 12:09:07 +02:00
LbaNumber ,
( UINTN ) ( CurrWritePtr - LinearOffset ) ,
& Size ,
CurrBuffer
) ;
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
CurrWritePtr = LinearOffset + PtrBlockMapEntry - > Length ;
CurrBuffer = CurrBuffer + Size ;
CurrWriteSize = CurrWriteSize - Size ;
}
}
LinearOffset + = PtrBlockMapEntry - > Length ;
LbaNumber + + ;
}
}
return EFI_SUCCESS ;
}
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
/**
2007-07-19 12:09:07 +02:00
This code gets the current status of Variable Store .
2008-12-12 10:27:17 +01:00
@ param VarStoreHeader Pointer to the Variable Store Header .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
@ retval EfiRaw Variable store status is raw
@ retval EfiValid Variable store status is valid
@ retval EfiInvalid Variable store status is invalid
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
VARIABLE_STORE_STATUS
GetVariableStoreStatus (
IN VARIABLE_STORE_HEADER * VarStoreHeader
)
2007-07-19 12:09:07 +02:00
{
2009-02-27 06:35:08 +01:00
if ( CompareGuid ( & VarStoreHeader - > Signature , & gEfiVariableGuid ) & &
2007-07-19 12:09:07 +02:00
VarStoreHeader - > Format = = VARIABLE_STORE_FORMATTED & &
VarStoreHeader - > State = = VARIABLE_STORE_HEALTHY
) {
return EfiValid ;
2009-02-27 06:35:08 +01:00
} else if ( ( ( UINT32 * ) ( & VarStoreHeader - > Signature ) ) [ 0 ] = = 0xffffffff & &
( ( UINT32 * ) ( & VarStoreHeader - > Signature ) ) [ 1 ] = = 0xffffffff & &
( ( UINT32 * ) ( & VarStoreHeader - > Signature ) ) [ 2 ] = = 0xffffffff & &
( ( UINT32 * ) ( & VarStoreHeader - > Signature ) ) [ 3 ] = = 0xffffffff & &
VarStoreHeader - > Size = = 0xffffffff & &
VarStoreHeader - > Format = = 0xff & &
VarStoreHeader - > State = = 0xff
2007-07-19 12:09:07 +02:00
) {
return EfiRaw ;
} else {
return EfiInvalid ;
}
}
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
/**
2008-01-14 07:35:23 +01:00
This code gets the size of name of variable .
2008-12-12 10:27:17 +01:00
@ param Variable Pointer to the Variable Header
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
@ return UINTN Size of variable in bytes
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
* */
UINTN
NameSizeOfVariable (
IN VARIABLE_HEADER * Variable
)
2008-01-14 07:35:23 +01:00
{
if ( Variable - > State = = ( UINT8 ) ( - 1 ) | |
2008-12-12 10:27:17 +01:00
Variable - > DataSize = = ( UINT32 ) ( - 1 ) | |
Variable - > NameSize = = ( UINT32 ) ( - 1 ) | |
Variable - > Attributes = = ( UINT32 ) ( - 1 ) ) {
2008-01-14 07:35:23 +01:00
return 0 ;
}
return ( UINTN ) Variable - > NameSize ;
}
2008-12-12 10:27:17 +01:00
/**
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
This code gets the size of variable data .
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
@ param Variable Pointer to the Variable Header
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
@ return Size of variable in bytes
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
* */
UINTN
DataSizeOfVariable (
IN VARIABLE_HEADER * Variable
)
2008-01-14 07:35:23 +01:00
{
2008-12-12 10:27:17 +01:00
if ( Variable - > State = = ( UINT8 ) ( - 1 ) | |
Variable - > DataSize = = ( UINT32 ) ( - 1 ) | |
Variable - > NameSize = = ( UINT32 ) ( - 1 ) | |
Variable - > Attributes = = ( UINT32 ) ( - 1 ) ) {
2008-01-14 07:35:23 +01:00
return 0 ;
}
return ( UINTN ) Variable - > DataSize ;
}
2008-12-12 10:27:17 +01:00
/**
2008-01-14 07:35:23 +01:00
This code gets the pointer to the variable name .
2008-12-12 10:27:17 +01:00
@ param Variable Pointer to the Variable Header
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
@ return Pointer to Variable Name which is Unicode encoding
2008-01-14 07:35:23 +01:00
2008-12-12 10:27:17 +01:00
* */
CHAR16 *
GetVariableNamePtr (
IN VARIABLE_HEADER * Variable
)
2008-01-14 07:35:23 +01:00
{
return ( CHAR16 * ) ( Variable + 1 ) ;
}
2008-12-12 10:27:17 +01:00
/**
2007-07-19 12:09:07 +02:00
This code gets the pointer to the variable data .
2008-12-12 10:27:17 +01:00
@ param Variable Pointer to the Variable Header
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
@ return Pointer to Variable Data
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
UINT8 *
GetVariableDataPtr (
IN VARIABLE_HEADER * Variable
)
2007-07-19 12:09:07 +02:00
{
2008-01-14 07:35:23 +01:00
UINTN Value ;
2007-07-19 12:09:07 +02:00
//
// Be careful about pad size for alignment
//
2008-01-14 07:35:23 +01:00
Value = ( UINTN ) GetVariableNamePtr ( Variable ) ;
Value + = NameSizeOfVariable ( Variable ) ;
Value + = GET_PAD_SIZE ( NameSizeOfVariable ( Variable ) ) ;
return ( UINT8 * ) Value ;
2007-07-19 12:09:07 +02:00
}
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
/**
2007-07-19 12:09:07 +02:00
This code gets the pointer to the next variable header .
2008-12-12 10:27:17 +01:00
@ param Variable Pointer to the Variable Header
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
@ return Pointer to next variable header
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
VARIABLE_HEADER *
GetNextVariablePtr (
IN VARIABLE_HEADER * Variable
)
2007-07-19 12:09:07 +02:00
{
2008-01-14 07:35:23 +01:00
UINTN Value ;
2007-07-19 12:09:07 +02:00
if ( ! IsValidVariableHeader ( Variable ) ) {
return NULL ;
}
2008-01-14 07:35:23 +01:00
Value = ( UINTN ) GetVariableDataPtr ( Variable ) ;
Value + = DataSizeOfVariable ( Variable ) ;
Value + = GET_PAD_SIZE ( DataSizeOfVariable ( Variable ) ) ;
2007-07-19 12:09:07 +02:00
//
// Be careful about pad size for alignment
//
2008-01-14 07:35:23 +01:00
return ( VARIABLE_HEADER * ) HEADER_ALIGN ( Value ) ;
2007-07-19 12:09:07 +02:00
}
2008-12-12 10:27:17 +01:00
/**
2008-01-10 05:26:13 +01:00
2008-12-12 10:27:17 +01:00
Gets the pointer to the first variable header in given variable store area .
2008-01-10 05:26:13 +01:00
2008-12-12 10:27:17 +01:00
@ param VarStoreHeader Pointer to the Variable Store Header .
2008-01-10 05:26:13 +01:00
2008-12-12 10:27:17 +01:00
@ return Pointer to the first variable header
2008-01-10 05:26:13 +01:00
2008-12-12 10:27:17 +01:00
* */
VARIABLE_HEADER *
GetStartPointer (
IN VARIABLE_STORE_HEADER * VarStoreHeader
)
2008-01-10 05:26:13 +01:00
{
//
// The end of variable store
//
return ( VARIABLE_HEADER * ) HEADER_ALIGN ( VarStoreHeader + 1 ) ;
}
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
/**
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
Gets the pointer to the end of the variable storage area .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
This function gets pointer to the end of the variable storage
area , according to the input variable store header .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
@ param VarStoreHeader Pointer to the Variable Store Header
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
@ return Pointer to the end of the variable storage area
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
VARIABLE_HEADER *
GetEndPointer (
IN VARIABLE_STORE_HEADER * VarStoreHeader
)
2007-07-19 12:09:07 +02:00
{
//
// The end of variable store
//
2008-01-10 05:26:13 +01:00
return ( VARIABLE_HEADER * ) HEADER_ALIGN ( ( UINTN ) VarStoreHeader + VarStoreHeader - > Size ) ;
2007-07-19 12:09:07 +02:00
}
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
/**
Variable store garbage collection and reclaim operation .
@ param VariableBase Base address of variable store
@ param LastVariableOffset Offset of last variable
@ param IsVolatile The variable store is volatile or not ,
if it is non - volatile , need FTW
@ param UpdatingVariable Pointer to updateing variable .
@ return EFI_OUT_OF_RESOURCES
@ return EFI_SUCCESS
@ return Others
* */
2007-07-19 12:09:07 +02:00
EFI_STATUS
Reclaim (
IN EFI_PHYSICAL_ADDRESS VariableBase ,
OUT UINTN * LastVariableOffset ,
2008-03-19 08:09:03 +01:00
IN BOOLEAN IsVolatile ,
IN VARIABLE_HEADER * UpdatingVariable
2007-07-19 12:09:07 +02:00
)
{
VARIABLE_HEADER * Variable ;
2008-03-19 08:09:03 +01:00
VARIABLE_HEADER * AddedVariable ;
2007-07-19 12:09:07 +02:00
VARIABLE_HEADER * NextVariable ;
2008-03-19 08:09:03 +01:00
VARIABLE_HEADER * NextAddedVariable ;
2007-07-19 12:09:07 +02:00
VARIABLE_STORE_HEADER * VariableStoreHeader ;
UINT8 * ValidBuffer ;
2008-03-19 08:09:03 +01:00
UINTN MaximumBufferSize ;
2007-07-19 12:09:07 +02:00
UINTN VariableSize ;
2008-10-26 08:32:20 +01:00
UINTN VariableNameSize ;
UINTN UpdatingVariableNameSize ;
2008-03-19 08:09:03 +01:00
UINTN NameSize ;
2007-07-19 12:09:07 +02:00
UINT8 * CurrPtr ;
2008-03-19 08:09:03 +01:00
VOID * Point0 ;
VOID * Point1 ;
BOOLEAN FoundAdded ;
2007-07-19 12:09:07 +02:00
EFI_STATUS Status ;
2008-10-26 08:32:20 +01:00
CHAR16 * VariableNamePtr ;
CHAR16 * UpdatingVariableNamePtr ;
2007-07-19 12:09:07 +02:00
VariableStoreHeader = ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) VariableBase ) ;
2009-04-07 08:42:12 +02:00
//
// recaluate the total size of Common/HwErr type variables in non-volatile area.
//
if ( ! IsVolatile ) {
mVariableModuleGlobal - > CommonVariableTotalSize = 0 ;
mVariableModuleGlobal - > HwErrVariableTotalSize = 0 ;
}
2007-07-19 12:09:07 +02:00
//
// Start Pointers for the variable.
//
2008-03-19 08:09:03 +01:00
Variable = GetStartPointer ( VariableStoreHeader ) ;
MaximumBufferSize = sizeof ( VARIABLE_STORE_HEADER ) ;
2007-07-19 12:09:07 +02:00
while ( IsValidVariableHeader ( Variable ) ) {
NextVariable = GetNextVariablePtr ( Variable ) ;
2008-03-19 08:09:03 +01:00
if ( Variable - > State = = VAR_ADDED | |
Variable - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED )
) {
2007-07-19 12:09:07 +02:00
VariableSize = ( UINTN ) NextVariable - ( UINTN ) Variable ;
2008-03-19 08:09:03 +01:00
MaximumBufferSize + = VariableSize ;
2007-07-19 12:09:07 +02:00
}
Variable = NextVariable ;
}
2008-03-19 08:09:03 +01:00
//
// Reserve the 1 Bytes with Oxff to identify the
// end of the variable buffer.
//
MaximumBufferSize + = 1 ;
ValidBuffer = AllocatePool ( MaximumBufferSize ) ;
2007-07-19 12:09:07 +02:00
if ( ValidBuffer = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
2008-03-19 08:09:03 +01:00
SetMem ( ValidBuffer , MaximumBufferSize , 0xff ) ;
2007-07-19 12:09:07 +02:00
//
// Copy variable store header
//
2008-03-19 08:09:03 +01:00
CopyMem ( ValidBuffer , VariableStoreHeader , sizeof ( VARIABLE_STORE_HEADER ) ) ;
CurrPtr = ( UINT8 * ) GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ValidBuffer ) ;
2007-07-19 12:09:07 +02:00
2008-03-19 08:09:03 +01:00
//
2008-10-12 01:44:40 +02:00
// Reinstall all ADDED variables as long as they are not identical to Updating Variable
2008-03-19 08:09:03 +01:00
//
Variable = GetStartPointer ( VariableStoreHeader ) ;
2007-07-19 12:09:07 +02:00
while ( IsValidVariableHeader ( Variable ) ) {
NextVariable = GetNextVariablePtr ( Variable ) ;
if ( Variable - > State = = VAR_ADDED ) {
2008-10-12 01:44:40 +02:00
if ( UpdatingVariable ! = NULL ) {
if ( UpdatingVariable = = Variable ) {
Variable = NextVariable ;
continue ;
}
2008-10-26 08:32:20 +01:00
VariableNameSize = NameSizeOfVariable ( Variable ) ;
UpdatingVariableNameSize = NameSizeOfVariable ( UpdatingVariable ) ;
VariableNamePtr = GetVariableNamePtr ( Variable ) ;
UpdatingVariableNamePtr = GetVariableNamePtr ( UpdatingVariable ) ;
2008-10-12 01:44:40 +02:00
if ( CompareGuid ( & Variable - > VendorGuid , & UpdatingVariable - > VendorGuid ) & &
2008-10-26 08:32:20 +01:00
VariableNameSize = = UpdatingVariableNameSize & &
CompareMem ( VariableNamePtr , UpdatingVariableNamePtr , VariableNameSize ) = = 0 ) {
2008-10-12 01:44:40 +02:00
Variable = NextVariable ;
continue ;
}
}
2007-07-19 12:09:07 +02:00
VariableSize = ( UINTN ) NextVariable - ( UINTN ) Variable ;
CopyMem ( CurrPtr , ( UINT8 * ) Variable , VariableSize ) ;
CurrPtr + = VariableSize ;
2009-04-07 08:42:12 +02:00
if ( ( ! IsVolatile ) & & ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
mVariableModuleGlobal - > HwErrVariableTotalSize + = VariableSize ;
} else if ( ( ! IsVolatile ) & & ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
mVariableModuleGlobal - > CommonVariableTotalSize + = VariableSize ;
}
2007-07-19 12:09:07 +02:00
}
Variable = NextVariable ;
}
2008-10-12 01:44:40 +02:00
//
// Reinstall the variable being updated if it is not NULL
//
if ( UpdatingVariable ! = NULL ) {
VariableSize = ( UINTN ) ( GetNextVariablePtr ( UpdatingVariable ) ) - ( UINTN ) UpdatingVariable ;
CopyMem ( CurrPtr , ( UINT8 * ) UpdatingVariable , VariableSize ) ;
CurrPtr + = VariableSize ;
2009-04-07 08:42:12 +02:00
if ( ( ! IsVolatile ) & & ( ( UpdatingVariable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
mVariableModuleGlobal - > HwErrVariableTotalSize + = VariableSize ;
} else if ( ( ! IsVolatile ) & & ( ( UpdatingVariable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
mVariableModuleGlobal - > CommonVariableTotalSize + = VariableSize ;
}
2008-10-12 01:44:40 +02:00
}
2008-03-19 08:09:03 +01:00
//
// Reinstall all in delete transition variables
//
Variable = GetStartPointer ( VariableStoreHeader ) ;
while ( IsValidVariableHeader ( Variable ) ) {
NextVariable = GetNextVariablePtr ( Variable ) ;
2008-10-12 01:44:40 +02:00
if ( Variable ! = UpdatingVariable & & Variable - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
2008-03-19 08:09:03 +01:00
//
// Buffer has cached all ADDED variable.
// Per IN_DELETED variable, we have to guarantee that
// no ADDED one in previous buffer.
//
FoundAdded = FALSE ;
AddedVariable = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ValidBuffer ) ;
while ( IsValidVariableHeader ( AddedVariable ) ) {
NextAddedVariable = GetNextVariablePtr ( AddedVariable ) ;
NameSize = NameSizeOfVariable ( AddedVariable ) ;
if ( CompareGuid ( & AddedVariable - > VendorGuid , & Variable - > VendorGuid ) & &
NameSize = = NameSizeOfVariable ( Variable )
) {
Point0 = ( VOID * ) GetVariableNamePtr ( AddedVariable ) ;
Point1 = ( VOID * ) GetVariableNamePtr ( Variable ) ;
2008-10-12 01:44:40 +02:00
if ( CompareMem ( Point0 , Point1 , NameSizeOfVariable ( AddedVariable ) ) = = 0 ) {
2008-03-19 08:09:03 +01:00
FoundAdded = TRUE ;
break ;
}
}
AddedVariable = NextAddedVariable ;
}
if ( ! FoundAdded ) {
2008-10-12 01:44:40 +02:00
//
// Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED
//
2008-03-19 08:09:03 +01:00
VariableSize = ( UINTN ) NextVariable - ( UINTN ) Variable ;
CopyMem ( CurrPtr , ( UINT8 * ) Variable , VariableSize ) ;
2008-10-12 01:44:40 +02:00
( ( VARIABLE_HEADER * ) CurrPtr ) - > State = VAR_ADDED ;
2008-03-19 08:09:03 +01:00
CurrPtr + = VariableSize ;
2009-04-07 08:42:12 +02:00
if ( ( ! IsVolatile ) & & ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
mVariableModuleGlobal - > HwErrVariableTotalSize + = VariableSize ;
} else if ( ( ! IsVolatile ) & & ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
mVariableModuleGlobal - > CommonVariableTotalSize + = VariableSize ;
}
2008-03-19 08:09:03 +01:00
}
}
Variable = NextVariable ;
}
2007-07-19 12:09:07 +02:00
if ( IsVolatile ) {
//
// If volatile variable store, just copy valid buffer
//
SetMem ( ( UINT8 * ) ( UINTN ) VariableBase , VariableStoreHeader - > Size , 0xff ) ;
2008-03-19 08:09:03 +01:00
CopyMem ( ( UINT8 * ) ( UINTN ) VariableBase , ValidBuffer , ( UINTN ) ( CurrPtr - ( UINT8 * ) ValidBuffer ) ) ;
2007-07-19 12:09:07 +02:00
Status = EFI_SUCCESS ;
} else {
//
// If non-volatile variable store, perform FTW here.
//
Status = FtwVariableSpace (
VariableBase ,
ValidBuffer ,
2008-03-19 08:09:03 +01:00
( UINTN ) ( CurrPtr - ( UINT8 * ) ValidBuffer )
2007-07-19 12:09:07 +02:00
) ;
}
2008-03-19 08:09:03 +01:00
if ( ! EFI_ERROR ( Status ) ) {
* LastVariableOffset = ( UINTN ) ( CurrPtr - ( UINT8 * ) ValidBuffer ) ;
} else {
2007-07-19 12:09:07 +02:00
* LastVariableOffset = 0 ;
}
2008-03-19 08:09:03 +01:00
FreePool ( ValidBuffer ) ;
2007-07-19 12:09:07 +02:00
return Status ;
}
2007-10-04 23:01:21 +02:00
2007-10-05 16:40:23 +02:00
/**
Update the Cache with Variable information . These are the same
arguments as the EFI Variable services .
@ param [ in ] VariableName Name of variable
@ param [ in ] VendorGuid Guid of variable
2008-12-12 10:48:24 +01:00
@ param [ in ] Attributes Attribues of the variable
2007-10-05 16:40:23 +02:00
@ param [ in ] DataSize Size of data . 0 means delete
@ param [ in ] Data Variable data
* */
2007-10-04 23:01:21 +02:00
VOID
UpdateVariableCache (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
2007-10-05 16:40:23 +02:00
IN UINT32 Attributes ,
IN UINTN DataSize ,
IN VOID * Data
2007-10-04 23:01:21 +02:00
)
{
VARIABLE_CACHE_ENTRY * Entry ;
UINTN Index ;
if ( EfiAtRuntime ( ) ) {
2009-02-12 02:55:32 +01:00
//
2007-10-04 23:01:21 +02:00
// Don't use the cache at runtime
2009-02-12 02:55:32 +01:00
//
2007-10-04 23:01:21 +02:00
return ;
}
for ( Index = 0 , Entry = mVariableCache ; Index < sizeof ( mVariableCache ) / sizeof ( VARIABLE_CACHE_ENTRY ) ; Index + + , Entry + + ) {
if ( CompareGuid ( VendorGuid , Entry - > Guid ) ) {
if ( StrCmp ( VariableName , Entry - > Name ) = = 0 ) {
Entry - > Attributes = Attributes ;
if ( DataSize = = 0 ) {
2009-02-12 02:55:32 +01:00
//
2007-10-04 23:01:21 +02:00
// Delete Case
2009-02-12 02:55:32 +01:00
//
2007-10-04 23:01:21 +02:00
if ( Entry - > DataSize ! = 0 ) {
FreePool ( Entry - > Data ) ;
}
Entry - > DataSize = DataSize ;
} else if ( DataSize = = Entry - > DataSize ) {
CopyMem ( Entry - > Data , Data , DataSize ) ;
} else {
Entry - > Data = AllocatePool ( DataSize ) ;
2009-02-12 02:55:32 +01:00
ASSERT ( Entry - > Data ! = NULL ) ;
2007-10-04 23:01:21 +02:00
Entry - > DataSize = DataSize ;
CopyMem ( Entry - > Data , Data , DataSize ) ;
}
}
}
}
}
2007-10-05 16:40:23 +02:00
/**
2008-12-12 10:27:17 +01:00
Search the cache to check if the variable is in it .
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
This function searches the variable cache . If the variable to find exists , return its data
and attributes .
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
@ param VariableName A Null - terminated Unicode string that is the name of the vendor ' s
variable . Each VariableName is unique for each
VendorGuid .
@ param VendorGuid A unique identifier for the vendor
@ param Attributes Pointer to the attributes bitmask of the variable for output .
@ param DataSize On input , size of the buffer of Data .
On output , size of the variable ' s data .
@ param Data Pointer to the data buffer for output .
@ retval EFI_SUCCESS VariableGuid & VariableName data was returned .
@ retval EFI_NOT_FOUND No matching variable found in cache .
@ retval EFI_BUFFER_TOO_SMALL * DataSize is smaller than size of the variable ' s data to return .
2007-10-05 16:40:23 +02:00
* */
2007-10-04 23:01:21 +02:00
EFI_STATUS
FindVariableInCache (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
OUT UINT32 * Attributes OPTIONAL ,
IN OUT UINTN * DataSize ,
OUT VOID * Data
)
{
VARIABLE_CACHE_ENTRY * Entry ;
UINTN Index ;
if ( EfiAtRuntime ( ) ) {
// Don't use the cache at runtime
return EFI_NOT_FOUND ;
}
for ( Index = 0 , Entry = mVariableCache ; Index < sizeof ( mVariableCache ) / sizeof ( VARIABLE_CACHE_ENTRY ) ; Index + + , Entry + + ) {
if ( CompareGuid ( VendorGuid , Entry - > Guid ) ) {
if ( StrCmp ( VariableName , Entry - > Name ) = = 0 ) {
if ( Entry - > DataSize = = 0 ) {
2007-10-05 16:40:23 +02:00
// Variable was deleted so return not found
2007-10-04 23:01:21 +02:00
return EFI_NOT_FOUND ;
2007-10-19 10:49:20 +02:00
} else if ( Entry - > DataSize > * DataSize ) {
2007-10-05 16:40:23 +02:00
// If the buffer is too small return correct size
2007-10-04 23:01:21 +02:00
* DataSize = Entry - > DataSize ;
return EFI_BUFFER_TOO_SMALL ;
} else {
2007-10-19 10:49:20 +02:00
* DataSize = Entry - > DataSize ;
2007-10-05 16:40:23 +02:00
// Return the data
2007-10-04 23:01:21 +02:00
CopyMem ( Data , Entry - > Data , Entry - > DataSize ) ;
if ( Attributes ! = NULL ) {
* Attributes = Entry - > Attributes ;
}
return EFI_SUCCESS ;
}
}
}
}
return EFI_NOT_FOUND ;
}
2008-12-12 10:27:17 +01:00
/**
Finds variable in storage blocks of volatile and non - volatile storage areas .
This code finds variable in storage blocks of volatile and non - volatile storage areas .
If VariableName is an empty string , then we just return the first
qualified variable without comparing VariableName and VendorGuid .
Otherwise , VariableName and VendorGuid are compared .
@ param VariableName Name of the variable to be found
@ param VendorGuid Vendor GUID to be found .
@ param PtrTrack VARIABLE_POINTER_TRACK structure for output ,
including the range searched and the target position .
@ param Global Pointer to VARIABLE_GLOBAL structure , including
base of volatile variable storage area , base of
NV variable storage area , and a lock .
@ retval EFI_INVALID_PARAMETER If VariableName is not an empty string , while
VendorGuid is NULL
@ retval EFI_SUCCESS Variable successfully found
@ retval EFI_INVALID_PARAMETER Variable not found
2007-10-04 23:01:21 +02:00
2008-12-12 10:27:17 +01:00
* */
2007-07-19 12:09:07 +02:00
EFI_STATUS
FindVariable (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
OUT VARIABLE_POINTER_TRACK * PtrTrack ,
IN VARIABLE_GLOBAL * Global
)
{
2008-03-19 08:09:03 +01:00
VARIABLE_HEADER * Variable [ 2 ] ;
VARIABLE_HEADER * InDeletedVariable ;
VARIABLE_STORE_HEADER * VariableStoreHeader [ 2 ] ;
UINTN InDeletedStorageIndex ;
UINTN Index ;
VOID * Point ;
2007-07-19 12:09:07 +02:00
//
2007-10-04 23:01:21 +02:00
// 0: Volatile, 1: Non-Volatile
2007-10-09 07:42:37 +02:00
// The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
// make use of this mapping to implement search algorithme.
2007-07-19 12:09:07 +02:00
//
2007-10-05 16:40:23 +02:00
VariableStoreHeader [ 0 ] = ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ) ;
VariableStoreHeader [ 1 ] = ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ) ;
2007-07-19 12:09:07 +02:00
//
// Start Pointers for the variable.
// Actual Data Pointer where data can be written.
//
2008-01-10 05:26:13 +01:00
Variable [ 0 ] = GetStartPointer ( VariableStoreHeader [ 0 ] ) ;
Variable [ 1 ] = GetStartPointer ( VariableStoreHeader [ 1 ] ) ;
2007-07-19 12:09:07 +02:00
if ( VariableName [ 0 ] ! = 0 & & VendorGuid = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
2008-03-19 08:09:03 +01:00
2007-07-19 12:09:07 +02:00
//
2007-10-04 23:01:21 +02:00
// Find the variable by walk through volatile and then non-volatile variable store
2007-07-19 12:09:07 +02:00
//
2008-03-19 08:09:03 +01:00
InDeletedVariable = NULL ;
InDeletedStorageIndex = 0 ;
2007-07-19 12:09:07 +02:00
for ( Index = 0 ; Index < 2 ; Index + + ) {
2009-03-16 10:57:10 +01:00
while ( ( Variable [ Index ] < GetEndPointer ( VariableStoreHeader [ Index ] ) ) & & IsValidVariableHeader ( Variable [ Index ] ) ) {
2008-03-19 08:09:03 +01:00
if ( Variable [ Index ] - > State = = VAR_ADDED | |
Variable [ Index ] - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED )
) {
2009-02-06 08:42:00 +01:00
if ( ! EfiAtRuntime ( ) | | ( ( Variable [ Index ] - > Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) ! = 0 ) ) {
2007-07-19 12:09:07 +02:00
if ( VariableName [ 0 ] = = 0 ) {
2008-03-19 08:09:03 +01:00
if ( Variable [ Index ] - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
InDeletedVariable = Variable [ Index ] ;
InDeletedStorageIndex = Index ;
} else {
PtrTrack - > StartPtr = GetStartPointer ( VariableStoreHeader [ Index ] ) ;
PtrTrack - > EndPtr = GetEndPointer ( VariableStoreHeader [ Index ] ) ;
PtrTrack - > CurrPtr = Variable [ Index ] ;
PtrTrack - > Volatile = ( BOOLEAN ) ( Index = = 0 ) ;
return EFI_SUCCESS ;
}
2007-07-19 12:09:07 +02:00
} else {
if ( CompareGuid ( VendorGuid , & Variable [ Index ] - > VendorGuid ) ) {
2008-01-14 07:35:23 +01:00
Point = ( VOID * ) GetVariableNamePtr ( Variable [ Index ] ) ;
ASSERT ( NameSizeOfVariable ( Variable [ Index ] ) ! = 0 ) ;
2009-02-06 06:37:46 +01:00
if ( CompareMem ( VariableName , Point , NameSizeOfVariable ( Variable [ Index ] ) ) = = 0 ) {
2008-03-19 08:09:03 +01:00
if ( Variable [ Index ] - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
InDeletedVariable = Variable [ Index ] ;
InDeletedStorageIndex = Index ;
} else {
PtrTrack - > StartPtr = GetStartPointer ( VariableStoreHeader [ Index ] ) ;
PtrTrack - > EndPtr = GetEndPointer ( VariableStoreHeader [ Index ] ) ;
PtrTrack - > CurrPtr = Variable [ Index ] ;
PtrTrack - > Volatile = ( BOOLEAN ) ( Index = = 0 ) ;
return EFI_SUCCESS ;
}
2007-07-19 12:09:07 +02:00
}
}
}
}
}
Variable [ Index ] = GetNextVariablePtr ( Variable [ Index ] ) ;
}
2008-03-19 08:09:03 +01:00
if ( InDeletedVariable ! = NULL ) {
PtrTrack - > StartPtr = GetStartPointer ( VariableStoreHeader [ InDeletedStorageIndex ] ) ;
PtrTrack - > EndPtr = GetEndPointer ( VariableStoreHeader [ InDeletedStorageIndex ] ) ;
PtrTrack - > CurrPtr = InDeletedVariable ;
PtrTrack - > Volatile = ( BOOLEAN ) ( InDeletedStorageIndex = = 0 ) ;
return EFI_SUCCESS ;
}
2007-07-19 12:09:07 +02:00
}
PtrTrack - > CurrPtr = NULL ;
return EFI_NOT_FOUND ;
}
2008-12-12 10:27:17 +01:00
/**
2009-04-27 09:06:01 +02:00
Get index from supported language codes according to language string .
This code is used to get corresponding index in supported language codes . It can handle
2009-04-30 07:32:11 +02:00
RFC4646 and ISO639 language tags .
2009-04-27 09:06:01 +02:00
In ISO639 language tags , take 3 - characters as a delimitation to find matched string and calculate the index .
2009-04-30 07:32:11 +02:00
In RFC4646 language tags , take semicolon as a delimitation to find matched string and calculate the index .
2009-04-27 09:06:01 +02:00
For example :
SupportedLang = " engfraengfra "
Lang = " eng "
Iso639Language = TRUE
The return value is " 0 " .
Another example :
SupportedLang = " en;fr;en-US;fr-FR "
Lang = " fr-FR "
Iso639Language = FALSE
The return value is " 3 " .
@ param SupportedLang Platform supported language codes .
@ param Lang Configured language .
2009-04-30 07:32:11 +02:00
@ param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646 .
2009-04-27 09:06:01 +02:00
@ retval the index of language in the language codes .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
2009-04-27 09:06:01 +02:00
UINTN
2007-10-05 16:40:23 +02:00
EFIAPI
2009-04-27 09:06:01 +02:00
GetIndexFromSupportedLangCodes (
IN CHAR8 * SupportedLang ,
IN CHAR8 * Lang ,
IN BOOLEAN Iso639Language
)
2007-07-19 12:09:07 +02:00
{
2009-04-27 09:06:01 +02:00
UINTN Index ;
UINT32 CompareLength ;
CHAR8 * Supported ;
Index = 0 ;
Supported = SupportedLang ;
if ( Iso639Language ) {
CompareLength = 3 ;
for ( Index = 0 ; Index < AsciiStrLen ( SupportedLang ) ; Index + = CompareLength ) {
if ( AsciiStrnCmp ( Lang , SupportedLang + Index , CompareLength ) = = 0 ) {
//
// Successfully find the index of Lang string in SupportedLang string.
//
Index = Index / CompareLength ;
return Index ;
}
}
ASSERT ( FALSE ) ;
return 0 ;
} else {
//
2009-04-30 07:32:11 +02:00
// Compare RFC4646 language code
2009-04-27 09:06:01 +02:00
//
while ( * Supported ! = ' \0 ' ) {
//
// take semicolon as delimitation, sequentially traverse supported language codes.
//
for ( CompareLength = 0 ; * Supported ! = ' ; ' & & * Supported ! = ' \0 ' ; CompareLength + + ) {
Supported + + ;
}
if ( AsciiStrnCmp ( Lang , Supported - CompareLength , CompareLength ) = = 0 ) {
//
// Successfully find the index of Lang string in SupportedLang string.
//
return Index ;
}
Index + + ;
}
ASSERT ( FALSE ) ;
return 0 ;
2007-07-19 12:09:07 +02:00
}
2009-04-27 09:06:01 +02:00
}
2007-10-04 23:01:21 +02:00
2009-04-27 09:06:01 +02:00
/**
Get language string from supported language codes according to index .
This code is used to get corresponding language string in supported language codes . It can handle
2009-04-30 07:32:11 +02:00
RFC4646 and ISO639 language tags .
2009-04-27 09:06:01 +02:00
In ISO639 language tags , take 3 - characters as a delimitation . Find language string according to the index .
2009-04-30 07:32:11 +02:00
In RFC4646 language tags , take semicolon as a delimitation . Find language string according to the index .
2009-04-27 09:06:01 +02:00
For example :
SupportedLang = " engfraengfra "
Index = " 1 "
Iso639Language = TRUE
The return value is " fra " .
Another example :
SupportedLang = " en;fr;en-US;fr-FR "
Index = " 1 "
Iso639Language = FALSE
The return value is " fr " .
@ param SupportedLang Platform supported language codes .
@ param Index the index in supported language codes .
2009-04-30 07:32:11 +02:00
@ param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646 .
2009-04-27 09:06:01 +02:00
@ retval the language string in the language codes .
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
* */
CHAR8 *
EFIAPI
GetLangFromSupportedLangCodes (
IN CHAR8 * SupportedLang ,
IN UINTN Index ,
IN BOOLEAN Iso639Language
)
{
UINTN SubIndex ;
UINT32 CompareLength ;
CHAR8 * Supported ;
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
SubIndex = 0 ;
Supported = SupportedLang ;
if ( Iso639Language ) {
//
// according to the index of Lang string in SupportedLang string to get the language.
// As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
// In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
//
CompareLength = 3 ;
SetMem ( mVariableModuleGlobal - > Lang , sizeof ( mVariableModuleGlobal - > Lang ) , 0 ) ;
return CopyMem ( mVariableModuleGlobal - > Lang , SupportedLang + Index * CompareLength , CompareLength ) ;
2007-07-19 12:09:07 +02:00
} else {
2009-04-27 09:06:01 +02:00
while ( TRUE ) {
//
// take semicolon as delimitation, sequentially traverse supported language codes.
//
for ( CompareLength = 0 ; * Supported ! = ' ; ' & & * Supported ! = ' \0 ' ; CompareLength + + ) {
Supported + + ;
}
if ( ( * Supported = = ' \0 ' ) & & ( SubIndex ! = Index ) ) {
//
// Have completed the traverse, but not find corrsponding string.
// This case is not allowed to happen.
//
ASSERT ( FALSE ) ;
return NULL ;
}
if ( SubIndex = = Index ) {
//
// according to the index of Lang string in SupportedLang string to get the language.
// As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
// In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
//
SetMem ( mVariableModuleGlobal - > PlatformLang , sizeof ( mVariableModuleGlobal - > PlatformLang ) , 0 ) ;
return CopyMem ( mVariableModuleGlobal - > PlatformLang , Supported - CompareLength , CompareLength ) ;
}
SubIndex + + ;
}
2007-07-19 12:09:07 +02:00
}
}
2009-04-27 09:06:01 +02:00
/**
Hook the operations in PlatformLangCodes , LangCodes , PlatformLang and Lang .
2007-10-05 16:40:23 +02:00
2009-04-27 09:06:01 +02:00
When setting Lang / LangCodes , simultaneously update PlatformLang / PlatformLangCodes .
2007-10-05 16:40:23 +02:00
2009-04-27 09:06:01 +02:00
According to UEFI spec , PlatformLangCodes / LangCodes are only set once in firmware initialization ,
and are read - only . Therefore , in variable driver , only store the original value for other use .
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
@ param [ in ] VariableName Name of variable
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
@ param [ in ] Data Variable data
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
@ param [ in ] DataSize Size of data . 0 means delete
@ retval EFI_SUCCESS auto update operation is successful .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
2007-10-05 16:40:23 +02:00
EFI_STATUS
EFIAPI
2009-04-27 09:06:01 +02:00
AutoUpdateLangVariable (
IN CHAR16 * VariableName ,
IN VOID * Data ,
IN UINTN DataSize
2007-10-05 16:40:23 +02:00
)
2007-07-19 12:09:07 +02:00
{
2009-04-27 09:06:01 +02:00
EFI_STATUS Status ;
CHAR8 * BestPlatformLang ;
CHAR8 * BestLang ;
UINTN Index ;
UINT32 Attributes ;
VARIABLE_POINTER_TRACK Variable ;
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
//
// According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.
//
Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS ;
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
if ( StrCmp ( VariableName , L " PlatformLangCodes " ) = = 0 ) {
//
// According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only
// Therefore, in variable driver, only store the original value for other use.
//
AsciiStrnCpy ( mVariableModuleGlobal - > PlatformLangCodes , Data , DataSize ) ;
} else if ( StrCmp ( VariableName , L " LangCodes " ) = = 0 ) {
//
// According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only
// Therefore, in variable driver, only store the original value for other use.
//
AsciiStrnCpy ( mVariableModuleGlobal - > LangCodes , Data , DataSize ) ;
2010-01-14 08:16:22 +01:00
} else if ( ( StrCmp ( VariableName , L " PlatformLang " ) = = 0 ) & & ( DataSize ! = 0 ) ) {
2009-04-27 09:06:01 +02:00
ASSERT ( AsciiStrLen ( mVariableModuleGlobal - > PlatformLangCodes ) ! = 0 ) ;
2008-01-09 11:10:16 +01:00
2009-04-27 09:06:01 +02:00
//
// When setting PlatformLang, firstly get most matched language string from supported language codes.
//
2009-04-28 05:32:24 +02:00
BestPlatformLang = GetBestLanguage ( mVariableModuleGlobal - > PlatformLangCodes , FALSE , Data , NULL ) ;
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
// Get the corresponding index in language codes.
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
Index = GetIndexFromSupportedLangCodes ( mVariableModuleGlobal - > PlatformLangCodes , BestPlatformLang , FALSE ) ;
2007-07-19 12:09:07 +02:00
//
2009-04-30 07:32:11 +02:00
// Get the corresponding ISO639 language tag according to RFC4646 language tag.
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
BestLang = GetLangFromSupportedLangCodes ( mVariableModuleGlobal - > LangCodes , Index , TRUE ) ;
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
// Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
FindVariable ( L " Lang " , & gEfiGlobalVariableGuid , & Variable , ( VARIABLE_GLOBAL * ) mVariableModuleGlobal ) ;
2008-01-09 11:10:16 +01:00
2009-04-27 09:06:01 +02:00
Status = UpdateVariable ( L " Lang " , & gEfiGlobalVariableGuid ,
BestLang , ISO_639_2_ENTRY_SIZE + 1 , Attributes , & Variable ) ;
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
DEBUG ( ( EFI_D_INFO , " Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a \n " , BestPlatformLang , BestLang ) ) ;
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
ASSERT_EFI_ERROR ( Status ) ;
2010-01-14 08:16:22 +01:00
} else if ( ( StrCmp ( VariableName , L " Lang " ) = = 0 ) & & ( DataSize ! = 0 ) ) {
2009-04-27 09:06:01 +02:00
ASSERT ( AsciiStrLen ( mVariableModuleGlobal - > LangCodes ) ! = 0 ) ;
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
//
// When setting Lang, firstly get most matched language string from supported language codes.
//
2009-04-28 05:32:24 +02:00
BestLang = GetBestLanguage ( mVariableModuleGlobal - > LangCodes , TRUE , Data , NULL ) ;
2009-04-27 09:06:01 +02:00
//
// Get the corresponding index in language codes.
//
Index = GetIndexFromSupportedLangCodes ( mVariableModuleGlobal - > LangCodes , BestLang , TRUE ) ;
//
2009-04-30 07:32:11 +02:00
// Get the corresponding RFC4646 language tag according to ISO639 language tag.
2009-04-27 09:06:01 +02:00
//
BestPlatformLang = GetLangFromSupportedLangCodes ( mVariableModuleGlobal - > PlatformLangCodes , Index , FALSE ) ;
//
// Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
//
FindVariable ( L " PlatformLang " , & gEfiGlobalVariableGuid , & Variable , ( VARIABLE_GLOBAL * ) mVariableModuleGlobal ) ;
Status = UpdateVariable ( L " PlatformLang " , & gEfiGlobalVariableGuid ,
2009-05-04 07:55:56 +02:00
BestPlatformLang , AsciiStrSize ( BestPlatformLang ) , Attributes , & Variable ) ;
2009-04-27 09:06:01 +02:00
DEBUG ( ( EFI_D_INFO , " Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a \n " , BestLang , BestPlatformLang ) ) ;
ASSERT_EFI_ERROR ( Status ) ;
}
return EFI_SUCCESS ;
2007-07-19 12:09:07 +02:00
}
2008-12-12 10:27:17 +01:00
/**
2009-04-27 09:06:01 +02:00
Update the variable region with Variable information . These are the same
arguments as the EFI Variable services .
2007-10-05 16:40:23 +02:00
2009-04-27 09:06:01 +02:00
@ param [ in ] VariableName Name of variable
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
@ param [ in ] VendorGuid Guid of variable
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
@ param [ in ] Data Variable data
@ param [ in ] DataSize Size of data . 0 means delete
@ param [ in ] Attributes Attribues of the variable
@ param [ in ] Variable The variable information which is used to keep track of variable usage .
@ retval EFI_SUCCESS The update operation is success .
@ retval EFI_OUT_OF_RESOURCES Variable region is full , can not write other data into this region .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
2007-10-05 16:40:23 +02:00
EFI_STATUS
EFIAPI
2009-04-27 09:06:01 +02:00
UpdateVariable (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
IN VOID * Data ,
IN UINTN DataSize ,
IN UINT32 Attributes OPTIONAL ,
IN VARIABLE_POINTER_TRACK * Variable
2007-10-05 16:40:23 +02:00
)
2007-07-19 12:09:07 +02:00
{
2009-03-09 07:39:13 +01:00
EFI_STATUS Status ;
VARIABLE_HEADER * NextVariable ;
2009-04-27 09:06:01 +02:00
UINTN ScratchSize ;
UINTN NonVolatileVarableStoreSize ;
2009-03-09 07:39:13 +01:00
UINTN VarNameOffset ;
UINTN VarDataOffset ;
2009-04-27 09:06:01 +02:00
UINTN VarNameSize ;
2009-03-09 07:39:13 +01:00
UINTN VarSize ;
2009-04-27 09:06:01 +02:00
BOOLEAN Volatile ;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL * Fvb ;
2009-03-09 07:39:13 +01:00
UINT8 State ;
BOOLEAN Reclaimed ;
2008-01-09 11:10:16 +01:00
2009-03-09 07:39:13 +01:00
Fvb = mVariableModuleGlobal - > FvbInstance ;
2009-04-27 09:06:01 +02:00
Reclaimed = FALSE ;
2008-01-09 11:10:16 +01:00
2009-04-27 09:06:01 +02:00
if ( Variable - > CurrPtr ! = NULL ) {
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
// Update/Delete existing variable
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
Volatile = Variable - > Volatile ;
2007-09-17 05:50:40 +02:00
if ( EfiAtRuntime ( ) ) {
//
// If EfiAtRuntime and the variable is Volatile and Runtime Access,
// the volatile is ReadOnly, and SetVariable should be aborted and
// return EFI_WRITE_PROTECTED.
//
2009-04-27 09:06:01 +02:00
if ( Variable - > Volatile ) {
2007-09-17 05:50:40 +02:00
Status = EFI_WRITE_PROTECTED ;
goto Done ;
}
//
// Only variable have NV attribute can be updated/deleted in Runtime
//
2009-04-27 09:06:01 +02:00
if ( ( Variable - > CurrPtr - > Attributes & EFI_VARIABLE_NON_VOLATILE ) = = 0 ) {
2007-09-17 05:50:40 +02:00
Status = EFI_INVALID_PARAMETER ;
goto Done ;
}
}
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
// Setting a data variable with no access, or zero DataSize attributes
// specified causes it to be deleted.
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
if ( DataSize = = 0 | | ( Attributes & ( EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS ) ) = = 0 ) {
2009-04-27 09:06:01 +02:00
State = Variable - > CurrPtr - > State ;
2007-09-17 05:50:40 +02:00
State & = VAR_DELETED ;
Status = UpdateVariableStore (
2007-10-05 16:40:23 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
2009-04-27 09:06:01 +02:00
Variable - > Volatile ,
2007-09-17 05:50:40 +02:00
FALSE ,
2009-03-09 07:39:13 +01:00
Fvb ,
2009-04-27 09:06:01 +02:00
( UINTN ) & Variable - > CurrPtr - > State ,
2007-09-17 05:50:40 +02:00
sizeof ( UINT8 ) ,
& State
) ;
2007-10-04 23:01:21 +02:00
if ( ! EFI_ERROR ( Status ) ) {
2007-10-06 19:02:23 +02:00
UpdateVariableInfo ( VariableName , VendorGuid , Volatile , FALSE , FALSE , TRUE , FALSE ) ;
2007-10-04 23:01:21 +02:00
UpdateVariableCache ( VariableName , VendorGuid , Attributes , DataSize , Data ) ;
}
2007-09-17 05:50:40 +02:00
goto Done ;
}
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
// If the variable is marked valid and the same data has been passed in
// then return to the caller immediately.
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
if ( DataSizeOfVariable ( Variable - > CurrPtr ) = = DataSize & &
( CompareMem ( Data , GetVariableDataPtr ( Variable - > CurrPtr ) , DataSize ) = = 0 ) ) {
2007-10-04 23:01:21 +02:00
2007-10-06 19:02:23 +02:00
UpdateVariableInfo ( VariableName , VendorGuid , Volatile , FALSE , TRUE , FALSE , FALSE ) ;
2007-09-17 05:50:40 +02:00
Status = EFI_SUCCESS ;
goto Done ;
2009-04-27 09:06:01 +02:00
} else if ( ( Variable - > CurrPtr - > State = = VAR_ADDED ) | |
( Variable - > CurrPtr - > State = = ( VAR_ADDED & VAR_IN_DELETED_TRANSITION ) ) ) {
2008-03-19 08:09:03 +01:00
2007-09-17 05:50:40 +02:00
//
// Mark the old variable as in delete transition
//
2009-04-27 09:06:01 +02:00
State = Variable - > CurrPtr - > State ;
2007-09-17 05:50:40 +02:00
State & = VAR_IN_DELETED_TRANSITION ;
Status = UpdateVariableStore (
2007-10-05 16:40:23 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
2009-04-27 09:06:01 +02:00
Variable - > Volatile ,
2007-09-17 05:50:40 +02:00
FALSE ,
2009-03-09 07:39:13 +01:00
Fvb ,
2009-04-27 09:06:01 +02:00
( UINTN ) & Variable - > CurrPtr - > State ,
2007-09-17 05:50:40 +02:00
sizeof ( UINT8 ) ,
& State
) ;
if ( EFI_ERROR ( Status ) ) {
goto Done ;
2007-10-04 23:01:21 +02:00
}
2007-09-17 05:50:40 +02:00
}
2009-04-27 09:06:01 +02:00
} else {
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
// Not found existing variable. Create a new variable
2007-09-17 05:50:40 +02:00
//
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
// Make sure we are trying to create a new variable.
// Setting a data variable with no access, or zero DataSize attributes means to delete it.
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
if ( DataSize = = 0 | | ( Attributes & ( EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS ) ) = = 0 ) {
Status = EFI_NOT_FOUND ;
goto Done ;
}
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
// Only variable have NV|RT attribute can be created in Runtime
//
if ( EfiAtRuntime ( ) & &
2008-12-12 10:48:24 +01:00
( ( ( Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) = = 0 ) | | ( ( Attributes & EFI_VARIABLE_NON_VOLATILE ) = = 0 ) ) ) {
2007-09-17 05:50:40 +02:00
Status = EFI_INVALID_PARAMETER ;
goto Done ;
}
}
//
// Function part - create a new variable and copy the data.
// Both update a variable and create a variable will come here.
//
// Tricky part: Use scratch data area at the end of volatile variable store
// as a temporary storage.
//
2007-10-05 16:40:23 +02:00
NextVariable = GetEndPointer ( ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ) ) ;
2010-01-30 00:39:48 +01:00
ScratchSize = MAX ( PcdGet32 ( PcdMaxVariableSize ) , PcdGet32 ( PcdMaxHardwareErrorVariableSize ) ) ;
2007-09-17 05:50:40 +02:00
2009-04-07 08:42:12 +02:00
SetMem ( NextVariable , ScratchSize , 0xff ) ;
2007-09-17 05:50:40 +02:00
NextVariable - > StartId = VARIABLE_DATA ;
NextVariable - > Attributes = Attributes ;
//
// NextVariable->State = VAR_ADDED;
//
NextVariable - > Reserved = 0 ;
VarNameOffset = sizeof ( VARIABLE_HEADER ) ;
VarNameSize = StrSize ( VariableName ) ;
CopyMem (
( UINT8 * ) ( ( UINTN ) NextVariable + VarNameOffset ) ,
VariableName ,
VarNameSize
) ;
VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE ( VarNameSize ) ;
CopyMem (
( UINT8 * ) ( ( UINTN ) NextVariable + VarDataOffset ) ,
Data ,
DataSize
) ;
CopyMem ( & NextVariable - > VendorGuid , VendorGuid , sizeof ( EFI_GUID ) ) ;
//
// There will be pad bytes after Data, the NextVariable->NameSize and
// NextVariable->DataSize should not include pad size so that variable
// service can get actual size in GetVariable
//
NextVariable - > NameSize = ( UINT32 ) VarNameSize ;
NextVariable - > DataSize = ( UINT32 ) DataSize ;
//
// The actual size of the variable that stores in storage should
// include pad size.
//
VarSize = VarDataOffset + DataSize + GET_PAD_SIZE ( DataSize ) ;
2008-12-12 10:48:24 +01:00
if ( ( Attributes & EFI_VARIABLE_NON_VOLATILE ) ! = 0 ) {
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
// Create a nonvolatile variable
2007-07-19 12:09:07 +02:00
//
2007-10-06 19:02:23 +02:00
Volatile = FALSE ;
2009-04-07 08:42:12 +02:00
NonVolatileVarableStoreSize = ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) ( mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ) ) - > Size ;
if ( ( ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = 0 )
2010-01-30 00:39:48 +01:00
& & ( ( VarSize + mVariableModuleGlobal - > HwErrVariableTotalSize ) > PcdGet32 ( PcdHwErrStorageSize ) ) )
2009-04-07 08:42:12 +02:00
| | ( ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = 0 )
2010-01-30 00:39:48 +01:00
& & ( ( VarSize + mVariableModuleGlobal - > CommonVariableTotalSize ) > NonVolatileVarableStoreSize - sizeof ( VARIABLE_STORE_HEADER ) - PcdGet32 ( PcdHwErrStorageSize ) ) ) ) {
2007-09-17 05:50:40 +02:00
if ( EfiAtRuntime ( ) ) {
Status = EFI_OUT_OF_RESOURCES ;
goto Done ;
}
//
// Perform garbage collection & reclaim operation
//
2009-04-27 09:06:01 +02:00
Status = Reclaim ( mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ,
& mVariableModuleGlobal - > NonVolatileLastVariableOffset , FALSE , Variable - > CurrPtr ) ;
2007-07-19 12:09:07 +02:00
if ( EFI_ERROR ( Status ) ) {
goto Done ;
}
//
2007-09-17 05:50:40 +02:00
// If still no enough space, return out of resources
2007-07-19 12:09:07 +02:00
//
2009-04-07 08:42:12 +02:00
if ( ( ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = 0 )
2010-01-30 00:39:48 +01:00
& & ( ( VarSize + mVariableModuleGlobal - > HwErrVariableTotalSize ) > PcdGet32 ( PcdHwErrStorageSize ) ) )
2009-04-07 08:42:12 +02:00
| | ( ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = 0 )
2010-01-30 00:39:48 +01:00
& & ( ( VarSize + mVariableModuleGlobal - > CommonVariableTotalSize ) > NonVolatileVarableStoreSize - sizeof ( VARIABLE_STORE_HEADER ) - PcdGet32 ( PcdHwErrStorageSize ) ) ) ) {
2007-09-17 05:50:40 +02:00
Status = EFI_OUT_OF_RESOURCES ;
2007-07-19 12:09:07 +02:00
goto Done ;
}
2007-09-17 05:50:40 +02:00
Reclaimed = TRUE ;
2007-07-19 12:09:07 +02:00
}
//
2007-09-17 05:50:40 +02:00
// Three steps
// 1. Write variable header
2008-01-14 07:35:23 +01:00
// 2. Set variable state to header valid
// 3. Write variable data
// 4. Set variable state to valid
2007-07-19 12:09:07 +02:00
//
//
2007-09-17 05:50:40 +02:00
// Step 1:
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
Status = UpdateVariableStore (
2007-10-05 16:40:23 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
2007-09-17 05:50:40 +02:00
FALSE ,
TRUE ,
2009-03-09 07:39:13 +01:00
Fvb ,
2009-04-27 09:06:01 +02:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset ,
2007-09-17 05:50:40 +02:00
sizeof ( VARIABLE_HEADER ) ,
( UINT8 * ) NextVariable
) ;
if ( EFI_ERROR ( Status ) ) {
goto Done ;
}
2008-01-14 07:35:23 +01:00
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
// Step 2:
2007-07-19 12:09:07 +02:00
//
2008-01-14 07:35:23 +01:00
NextVariable - > State = VAR_HEADER_VALID_ONLY ;
Status = UpdateVariableStore (
& mVariableModuleGlobal - > VariableGlobal ,
FALSE ,
TRUE ,
2009-03-09 07:39:13 +01:00
Fvb ,
2009-04-27 09:06:01 +02:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset ,
2008-01-14 07:35:23 +01:00
sizeof ( VARIABLE_HEADER ) ,
( UINT8 * ) NextVariable
) ;
if ( EFI_ERROR ( Status ) ) {
goto Done ;
}
//
// Step 3:
//
2007-09-17 05:50:40 +02:00
Status = UpdateVariableStore (
2007-10-05 16:40:23 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
2007-09-17 05:50:40 +02:00
FALSE ,
TRUE ,
2009-03-09 07:39:13 +01:00
Fvb ,
2009-04-27 09:06:01 +02:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset + sizeof ( VARIABLE_HEADER ) ,
2007-09-17 05:50:40 +02:00
( UINT32 ) VarSize - sizeof ( VARIABLE_HEADER ) ,
( UINT8 * ) NextVariable + sizeof ( VARIABLE_HEADER )
) ;
if ( EFI_ERROR ( Status ) ) {
goto Done ;
}
2007-07-19 12:09:07 +02:00
//
2008-01-14 07:35:23 +01:00
// Step 4:
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
NextVariable - > State = VAR_ADDED ;
Status = UpdateVariableStore (
2007-10-05 16:40:23 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
2007-09-17 05:50:40 +02:00
FALSE ,
TRUE ,
2009-03-09 07:39:13 +01:00
Fvb ,
2009-04-27 09:06:01 +02:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset ,
2007-09-17 05:50:40 +02:00
sizeof ( VARIABLE_HEADER ) ,
( UINT8 * ) NextVariable
) ;
if ( EFI_ERROR ( Status ) ) {
goto Done ;
}
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset + = HEADER_ALIGN ( VarSize ) ;
2007-07-19 12:09:07 +02:00
2009-04-07 08:42:12 +02:00
if ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = 0 ) {
mVariableModuleGlobal - > HwErrVariableTotalSize + = HEADER_ALIGN ( VarSize ) ;
} else {
mVariableModuleGlobal - > CommonVariableTotalSize + = HEADER_ALIGN ( VarSize ) ;
}
2007-09-17 05:50:40 +02:00
} else {
//
// Create a volatile variable
//
2007-10-06 19:02:23 +02:00
Volatile = TRUE ;
2007-09-17 05:50:40 +02:00
2009-04-27 09:06:01 +02:00
if ( ( UINT32 ) ( VarSize + mVariableModuleGlobal - > VolatileLastVariableOffset ) >
2007-10-05 16:40:23 +02:00
( ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) ( mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ) ) ) - > Size ) {
2007-07-19 12:09:07 +02:00
//
2007-09-17 05:50:40 +02:00
// Perform garbage collection & reclaim operation
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
Status = Reclaim ( mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ,
& mVariableModuleGlobal - > VolatileLastVariableOffset , TRUE , Variable - > CurrPtr ) ;
2007-07-19 12:09:07 +02:00
if ( EFI_ERROR ( Status ) ) {
goto Done ;
}
//
2007-09-17 05:50:40 +02:00
// If still no enough space, return out of resources
2007-07-19 12:09:07 +02:00
//
2009-04-27 09:06:01 +02:00
if ( ( UINT32 ) ( VarSize + mVariableModuleGlobal - > VolatileLastVariableOffset ) >
2007-10-05 16:40:23 +02:00
( ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) ( mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ) ) ) - > Size
2007-07-19 12:09:07 +02:00
) {
2007-09-17 05:50:40 +02:00
Status = EFI_OUT_OF_RESOURCES ;
2007-07-19 12:09:07 +02:00
goto Done ;
}
2007-09-17 05:50:40 +02:00
Reclaimed = TRUE ;
2007-07-19 12:09:07 +02:00
}
2007-09-17 05:50:40 +02:00
NextVariable - > State = VAR_ADDED ;
Status = UpdateVariableStore (
2007-10-05 16:40:23 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
2007-09-17 05:50:40 +02:00
TRUE ,
TRUE ,
2009-03-09 07:39:13 +01:00
Fvb ,
2009-04-27 09:06:01 +02:00
mVariableModuleGlobal - > VolatileLastVariableOffset ,
2007-09-17 05:50:40 +02:00
( UINT32 ) VarSize ,
( UINT8 * ) NextVariable
) ;
if ( EFI_ERROR ( Status ) ) {
goto Done ;
2007-07-19 12:09:07 +02:00
}
2007-09-17 05:50:40 +02:00
2009-04-27 09:06:01 +02:00
mVariableModuleGlobal - > VolatileLastVariableOffset + = HEADER_ALIGN ( VarSize ) ;
2007-09-17 05:50:40 +02:00
}
2009-04-27 09:06:01 +02:00
2007-09-17 05:50:40 +02:00
//
// Mark the old variable as deleted
//
2009-04-27 09:06:01 +02:00
if ( ! Reclaimed & & ! EFI_ERROR ( Status ) & & Variable - > CurrPtr ! = NULL ) {
State = Variable - > CurrPtr - > State ;
2007-09-17 05:50:40 +02:00
State & = VAR_DELETED ;
Status = UpdateVariableStore (
2009-04-27 09:06:01 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
Variable - > Volatile ,
FALSE ,
Fvb ,
( UINTN ) & Variable - > CurrPtr - > State ,
sizeof ( UINT8 ) ,
& State
) ;
}
if ( ! EFI_ERROR ( Status ) ) {
UpdateVariableInfo ( VariableName , VendorGuid , Volatile , FALSE , TRUE , FALSE , FALSE ) ;
UpdateVariableCache ( VariableName , VendorGuid , Attributes , DataSize , Data ) ;
}
Done :
return Status ;
}
/**
This code finds variable in storage blocks ( Volatile or Non - Volatile ) .
@ param VariableName Name of Variable to be found .
@ param VendorGuid Variable vendor GUID .
@ param Attributes Attribute value of the variable found .
@ param DataSize Size of Data found . If size is less than the
data , this value contains the required size .
@ param Data Data pointer .
@ return EFI_INVALID_PARAMETER Invalid parameter
@ return EFI_SUCCESS Find the specified variable
@ return EFI_NOT_FOUND Not found
@ return EFI_BUFFER_TO_SMALL DataSize is too small for the result
* */
EFI_STATUS
EFIAPI
RuntimeServiceGetVariable (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
OUT UINT32 * Attributes OPTIONAL ,
IN OUT UINTN * DataSize ,
OUT VOID * Data
)
{
EFI_STATUS Status ;
VARIABLE_POINTER_TRACK Variable ;
UINTN VarDataSize ;
if ( VariableName = = NULL | | VendorGuid = = NULL | | DataSize = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
//
// Find existing variable
//
Status = FindVariableInCache ( VariableName , VendorGuid , Attributes , DataSize , Data ) ;
if ( ( Status = = EFI_BUFFER_TOO_SMALL ) | | ( Status = = EFI_SUCCESS ) ) {
// Hit in the Cache
UpdateVariableInfo ( VariableName , VendorGuid , FALSE , TRUE , FALSE , FALSE , TRUE ) ;
goto Done ;
}
Status = FindVariable ( VariableName , VendorGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal ) ;
if ( Variable . CurrPtr = = NULL | | EFI_ERROR ( Status ) ) {
goto Done ;
}
//
// Get data size
//
VarDataSize = DataSizeOfVariable ( Variable . CurrPtr ) ;
ASSERT ( VarDataSize ! = 0 ) ;
if ( * DataSize > = VarDataSize ) {
if ( Data = = NULL ) {
Status = EFI_INVALID_PARAMETER ;
goto Done ;
2007-10-04 23:01:21 +02:00
}
2009-04-27 09:06:01 +02:00
CopyMem ( Data , GetVariableDataPtr ( Variable . CurrPtr ) , VarDataSize ) ;
if ( Attributes ! = NULL ) {
* Attributes = Variable . CurrPtr - > Attributes ;
}
* DataSize = VarDataSize ;
UpdateVariableInfo ( VariableName , VendorGuid , Variable . Volatile , TRUE , FALSE , FALSE , FALSE ) ;
UpdateVariableCache ( VariableName , VendorGuid , Variable . CurrPtr - > Attributes , VarDataSize , Data ) ;
Status = EFI_SUCCESS ;
goto Done ;
} else {
* DataSize = VarDataSize ;
Status = EFI_BUFFER_TOO_SMALL ;
goto Done ;
2007-07-19 12:09:07 +02:00
}
2009-04-27 09:06:01 +02:00
Done :
ReleaseLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
return Status ;
}
/**
This code Finds the Next available variable .
@ param VariableNameSize Size of the variable name
@ param VariableName Pointer to variable name
@ param VendorGuid Variable Vendor Guid
@ return EFI_INVALID_PARAMETER Invalid parameter
@ return EFI_SUCCESS Find the specified variable
@ return EFI_NOT_FOUND Not found
@ return EFI_BUFFER_TO_SMALL DataSize is too small for the result
* */
EFI_STATUS
EFIAPI
RuntimeServiceGetNextVariableName (
IN OUT UINTN * VariableNameSize ,
IN OUT CHAR16 * VariableName ,
IN OUT EFI_GUID * VendorGuid
)
{
VARIABLE_POINTER_TRACK Variable ;
UINTN VarNameSize ;
EFI_STATUS Status ;
if ( VariableNameSize = = NULL | | VariableName = = NULL | | VendorGuid = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
Status = FindVariable ( VariableName , VendorGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal ) ;
if ( Variable . CurrPtr = = NULL | | EFI_ERROR ( Status ) ) {
goto Done ;
}
if ( VariableName [ 0 ] ! = 0 ) {
//
// If variable name is not NULL, get next variable
//
Variable . CurrPtr = GetNextVariablePtr ( Variable . CurrPtr ) ;
}
while ( TRUE ) {
//
// If both volatile and non-volatile variable store are parsed,
// return not found
//
if ( Variable . CurrPtr > = Variable . EndPtr | | Variable . CurrPtr = = NULL ) {
Variable . Volatile = ( BOOLEAN ) ( Variable . Volatile ^ ( ( BOOLEAN ) 0x1 ) ) ;
if ( ! Variable . Volatile ) {
Variable . StartPtr = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ) ;
Variable . EndPtr = GetEndPointer ( ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ) ) ;
} else {
Status = EFI_NOT_FOUND ;
goto Done ;
}
Variable . CurrPtr = Variable . StartPtr ;
if ( ! IsValidVariableHeader ( Variable . CurrPtr ) ) {
continue ;
}
}
//
// Variable is found
//
if ( IsValidVariableHeader ( Variable . CurrPtr ) & & Variable . CurrPtr - > State = = VAR_ADDED ) {
if ( ( EfiAtRuntime ( ) & & ( ( Variable . CurrPtr - > Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) = = 0 ) ) = = 0 ) {
VarNameSize = NameSizeOfVariable ( Variable . CurrPtr ) ;
ASSERT ( VarNameSize ! = 0 ) ;
if ( VarNameSize < = * VariableNameSize ) {
CopyMem (
VariableName ,
GetVariableNamePtr ( Variable . CurrPtr ) ,
VarNameSize
) ;
CopyMem (
VendorGuid ,
& Variable . CurrPtr - > VendorGuid ,
sizeof ( EFI_GUID )
) ;
Status = EFI_SUCCESS ;
} else {
Status = EFI_BUFFER_TOO_SMALL ;
}
* VariableNameSize = VarNameSize ;
goto Done ;
}
}
Variable . CurrPtr = GetNextVariablePtr ( Variable . CurrPtr ) ;
}
2007-10-04 23:01:21 +02:00
2007-07-19 12:09:07 +02:00
Done :
2009-04-27 09:06:01 +02:00
ReleaseLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
return Status ;
}
/**
This code sets variable in storage blocks ( Volatile or Non - Volatile ) .
@ param VariableName Name of Variable to be found
@ param VendorGuid Variable vendor GUID
@ param Attributes Attribute value of the variable found
@ param DataSize Size of Data found . If size is less than the
data , this value contains the required size .
@ param Data Data pointer
@ return EFI_INVALID_PARAMETER Invalid parameter
@ return EFI_SUCCESS Set successfully
@ return EFI_OUT_OF_RESOURCES Resource not enough to set variable
@ return EFI_NOT_FOUND Not found
@ return EFI_WRITE_PROTECTED Variable is read - only
* */
EFI_STATUS
EFIAPI
RuntimeServiceSetVariable (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
IN UINT32 Attributes ,
IN UINTN DataSize ,
IN VOID * Data
)
{
VARIABLE_POINTER_TRACK Variable ;
EFI_STATUS Status ;
VARIABLE_HEADER * NextVariable ;
EFI_PHYSICAL_ADDRESS Point ;
//
// Check input parameters
//
if ( VariableName = = NULL | | VariableName [ 0 ] = = 0 | | VendorGuid = = NULL ) {
return EFI_INVALID_PARAMETER ;
2009-12-22 08:16:55 +01:00
}
if ( DataSize ! = 0 & & Data = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
2010-03-18 09:58:48 +01:00
//
// Not support authenticated variable write yet.
//
if ( ( Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS ) ! = 0 ) {
return EFI_INVALID_PARAMETER ;
}
2009-04-27 09:06:01 +02:00
//
// Make sure if runtime bit is set, boot service bit is set also
//
if ( ( Attributes & ( EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS ) ) = = EFI_VARIABLE_RUNTIME_ACCESS ) {
return EFI_INVALID_PARAMETER ;
}
//
// The size of the VariableName, including the Unicode Null in bytes plus
2010-01-30 00:39:48 +01:00
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)
// bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.
2009-04-27 09:06:01 +02:00
//
if ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
2010-01-30 00:39:48 +01:00
if ( ( DataSize > PcdGet32 ( PcdMaxHardwareErrorVariableSize ) ) | |
( sizeof ( VARIABLE_HEADER ) + StrSize ( VariableName ) + DataSize > PcdGet32 ( PcdMaxHardwareErrorVariableSize ) ) ) {
2009-04-27 09:06:01 +02:00
return EFI_INVALID_PARAMETER ;
}
//
// According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX"
//
if ( StrnCmp ( VariableName , L " HwErrRec " , StrLen ( L " HwErrRec " ) ) ! = 0 ) {
return EFI_INVALID_PARAMETER ;
}
} else {
//
// The size of the VariableName, including the Unicode Null in bytes plus
2010-01-30 00:39:48 +01:00
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.
2009-04-27 09:06:01 +02:00
//
2010-01-30 00:39:48 +01:00
if ( ( DataSize > PcdGet32 ( PcdMaxVariableSize ) ) | |
( sizeof ( VARIABLE_HEADER ) + StrSize ( VariableName ) + DataSize > PcdGet32 ( PcdMaxVariableSize ) ) ) {
2009-04-27 09:06:01 +02:00
return EFI_INVALID_PARAMETER ;
}
}
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
//
// Consider reentrant in MCA/INIT/NMI. It needs be reupdated;
//
if ( 1 < InterlockedIncrement ( & mVariableModuleGlobal - > VariableGlobal . ReentrantState ) ) {
Point = mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ; ;
//
// Parse non-volatile variable data and get last variable offset
//
NextVariable = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) Point ) ;
while ( ( NextVariable < GetEndPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) Point ) )
& & IsValidVariableHeader ( NextVariable ) ) {
NextVariable = GetNextVariablePtr ( NextVariable ) ;
}
mVariableModuleGlobal - > NonVolatileLastVariableOffset = ( UINTN ) NextVariable - ( UINTN ) Point ;
}
//
// Check whether the input variable is already existed
//
FindVariable ( VariableName , VendorGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal ) ;
//
// Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang
//
AutoUpdateLangVariable ( VariableName , Data , DataSize ) ;
Status = UpdateVariable ( VariableName , VendorGuid , Data , DataSize , Attributes , & Variable ) ;
2008-01-09 11:10:16 +01:00
InterlockedDecrement ( & mVariableModuleGlobal - > VariableGlobal . ReentrantState ) ;
2007-10-05 16:40:23 +02:00
ReleaseLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
2008-01-09 11:10:16 +01:00
2007-07-19 12:09:07 +02:00
return Status ;
}
2008-12-12 10:27:17 +01:00
/**
2007-07-19 12:09:07 +02:00
This code returns information about the EFI variables .
2008-12-12 10:27:17 +01:00
@ param Attributes Attributes bitmask to specify the type of variables
on which to return information .
@ param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
for the EFI variables associated with the attributes specified .
@ param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
for EFI variables associated with the attributes specified .
@ param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
associated with the attributes specified .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
@ return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied .
@ return EFI_SUCCESS Query successfully .
@ return EFI_UNSUPPORTED The attribute is not supported on this platform .
2007-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
* */
2007-10-05 16:40:23 +02:00
EFI_STATUS
EFIAPI
RuntimeServiceQueryVariableInfo (
IN UINT32 Attributes ,
OUT UINT64 * MaximumVariableStorageSize ,
OUT UINT64 * RemainingVariableStorageSize ,
OUT UINT64 * MaximumVariableSize
)
2007-07-19 12:09:07 +02:00
{
VARIABLE_HEADER * Variable ;
VARIABLE_HEADER * NextVariable ;
UINT64 VariableSize ;
VARIABLE_STORE_HEADER * VariableStoreHeader ;
2009-04-07 08:42:12 +02:00
UINT64 CommonVariableTotalSize ;
UINT64 HwErrVariableTotalSize ;
CommonVariableTotalSize = 0 ;
HwErrVariableTotalSize = 0 ;
2007-07-19 12:09:07 +02:00
2007-09-17 05:50:40 +02:00
if ( MaximumVariableStorageSize = = NULL | | RemainingVariableStorageSize = = NULL | | MaximumVariableSize = = NULL | | Attributes = = 0 ) {
2007-07-19 12:09:07 +02:00
return EFI_INVALID_PARAMETER ;
}
2009-04-07 08:42:12 +02:00
2007-09-17 05:50:40 +02:00
if ( ( Attributes & ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) = = 0 ) {
2007-07-19 12:09:07 +02:00
//
// Make sure the Attributes combination is supported by the platform.
//
2007-09-17 05:50:40 +02:00
return EFI_UNSUPPORTED ;
2007-07-19 12:09:07 +02:00
} else if ( ( Attributes & ( EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS ) ) = = EFI_VARIABLE_RUNTIME_ACCESS ) {
//
// Make sure if runtime bit is set, boot service bit is set also.
//
return EFI_INVALID_PARAMETER ;
2008-12-12 10:48:24 +01:00
} else if ( EfiAtRuntime ( ) & & ( ( Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) = = 0 ) ) {
2007-07-19 12:09:07 +02:00
//
// Make sure RT Attribute is set if we are in Runtime phase.
//
return EFI_INVALID_PARAMETER ;
2009-04-07 08:42:12 +02:00
} else if ( ( Attributes & ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
//
// Make sure Hw Attribute is set with NV.
//
return EFI_INVALID_PARAMETER ;
2010-03-18 09:58:48 +01:00
} else if ( ( Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS ) ! = 0 ) {
//
// Not support authentiated variable write yet.
//
return EFI_UNSUPPORTED ;
2007-07-19 12:09:07 +02:00
}
2007-10-05 16:40:23 +02:00
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
2007-07-19 12:09:07 +02:00
if ( ( Attributes & EFI_VARIABLE_NON_VOLATILE ) = = 0 ) {
//
// Query is Volatile related.
//
2007-10-05 16:40:23 +02:00
VariableStoreHeader = ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ) ;
2007-07-19 12:09:07 +02:00
} else {
//
// Query is Non-Volatile related.
//
2007-10-05 16:40:23 +02:00
VariableStoreHeader = ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ) ;
2007-07-19 12:09:07 +02:00
}
//
// Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
// with the storage size (excluding the storage header size).
//
* MaximumVariableStorageSize = VariableStoreHeader - > Size - sizeof ( VARIABLE_STORE_HEADER ) ;
2007-09-17 05:50:40 +02:00
//
// Harware error record variable needs larger size.
//
2009-04-07 08:42:12 +02:00
if ( ( Attributes & ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) = = ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
2010-01-30 00:39:48 +01:00
* MaximumVariableStorageSize = PcdGet32 ( PcdHwErrStorageSize ) ;
* MaximumVariableSize = PcdGet32 ( PcdMaxHardwareErrorVariableSize ) - sizeof ( VARIABLE_HEADER ) ;
2009-04-07 08:42:12 +02:00
} else {
if ( ( Attributes & EFI_VARIABLE_NON_VOLATILE ) ! = 0 ) {
2010-01-30 00:39:48 +01:00
ASSERT ( PcdGet32 ( PcdHwErrStorageSize ) < VariableStoreHeader - > Size ) ;
* MaximumVariableStorageSize = VariableStoreHeader - > Size - sizeof ( VARIABLE_STORE_HEADER ) - PcdGet32 ( PcdHwErrStorageSize ) ;
2009-04-07 08:42:12 +02:00
}
//
2010-01-30 00:39:48 +01:00
// Let *MaximumVariableSize be PcdGet32 (PcdMaxVariableSize) with the exception of the variable header size.
2009-04-07 08:42:12 +02:00
//
2010-01-30 00:39:48 +01:00
* MaximumVariableSize = PcdGet32 ( PcdMaxVariableSize ) - sizeof ( VARIABLE_HEADER ) ;
2007-09-17 05:50:40 +02:00
}
2007-07-19 12:09:07 +02:00
//
// Point to the starting address of the variables.
//
2008-01-10 05:26:13 +01:00
Variable = GetStartPointer ( VariableStoreHeader ) ;
2007-07-19 12:09:07 +02:00
//
// Now walk through the related variable store.
//
2009-03-27 06:05:48 +01:00
while ( ( Variable < GetEndPointer ( VariableStoreHeader ) ) & & IsValidVariableHeader ( Variable ) ) {
2007-07-19 12:09:07 +02:00
NextVariable = GetNextVariablePtr ( Variable ) ;
VariableSize = ( UINT64 ) ( UINTN ) NextVariable - ( UINT64 ) ( UINTN ) Variable ;
if ( EfiAtRuntime ( ) ) {
//
// we don't take the state of the variables in mind
// when calculating RemainingVariableStorageSize,
// since the space occupied by variables not marked with
// VAR_ADDED is not allowed to be reclaimed in Runtime.
//
2009-04-07 08:42:12 +02:00
if ( ( NextVariable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
HwErrVariableTotalSize + = VariableSize ;
} else {
CommonVariableTotalSize + = VariableSize ;
}
2007-07-19 12:09:07 +02:00
} else {
//
// Only care about Variables with State VAR_ADDED,because
// the space not marked as VAR_ADDED is reclaimable now.
//
if ( Variable - > State = = VAR_ADDED ) {
2009-04-07 08:42:12 +02:00
if ( ( NextVariable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
HwErrVariableTotalSize + = VariableSize ;
} else {
CommonVariableTotalSize + = VariableSize ;
}
2007-07-19 12:09:07 +02:00
}
}
//
// Go to the next one
//
Variable = NextVariable ;
}
2009-04-07 08:42:12 +02:00
if ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
* RemainingVariableStorageSize = * MaximumVariableStorageSize - HwErrVariableTotalSize ;
} else {
* RemainingVariableStorageSize = * MaximumVariableStorageSize - CommonVariableTotalSize ;
}
2007-09-17 05:50:40 +02:00
if ( * RemainingVariableStorageSize < sizeof ( VARIABLE_HEADER ) ) {
* MaximumVariableSize = 0 ;
} else if ( ( * RemainingVariableStorageSize - sizeof ( VARIABLE_HEADER ) ) < * MaximumVariableSize ) {
* MaximumVariableSize = * RemainingVariableStorageSize - sizeof ( VARIABLE_HEADER ) ;
}
2007-10-05 16:40:23 +02:00
ReleaseLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
2007-07-19 12:09:07 +02:00
return EFI_SUCCESS ;
}
2008-12-12 10:27:17 +01:00
/**
Notification function of EVT_GROUP_READY_TO_BOOT event group .
This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group .
When the Boot Manager is about to load and execute a boot option , it reclaims variable
storage if free size is below the threshold .
@ param Event Event whose notification function is being invoked
@ param Context Pointer to the notification function ' s context
* */
2008-01-17 10:59:51 +01:00
VOID
EFIAPI
ReclaimForOS (
EFI_EVENT Event ,
VOID * Context
)
{
2009-09-10 08:51:55 +02:00
EFI_STATUS Status ;
2009-04-07 08:42:12 +02:00
UINTN CommonVariableSpace ;
UINTN RemainingCommonVariableSpace ;
UINTN RemainingHwErrVariableSpace ;
2008-01-17 10:59:51 +01:00
Status = EFI_SUCCESS ;
2009-04-07 08:42:12 +02:00
CommonVariableSpace = ( ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) ( mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ) ) ) - > Size - sizeof ( VARIABLE_STORE_HEADER ) - PcdGet32 ( PcdHwErrStorageSize ) ; //Allowable max size of common variable storage space
RemainingCommonVariableSpace = CommonVariableSpace - mVariableModuleGlobal - > CommonVariableTotalSize ;
RemainingHwErrVariableSpace = PcdGet32 ( PcdHwErrStorageSize ) - mVariableModuleGlobal - > HwErrVariableTotalSize ;
2008-01-17 10:59:51 +01:00
//
2009-09-10 08:51:55 +02:00
// Check if the free area is blow a threshold.
2008-01-17 10:59:51 +01:00
//
2009-04-07 08:42:12 +02:00
if ( ( RemainingCommonVariableSpace < PcdGet32 ( PcdMaxVariableSize ) )
2009-09-10 08:51:55 +02:00
| | ( ( PcdGet32 ( PcdHwErrStorageSize ) ! = 0 ) & &
( RemainingHwErrVariableSpace < PcdGet32 ( PcdMaxHardwareErrorVariableSize ) ) ) ) {
2008-01-17 10:59:51 +01:00
Status = Reclaim (
2009-04-07 08:42:12 +02:00
mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ,
& mVariableModuleGlobal - > NonVolatileLastVariableOffset ,
FALSE ,
NULL
) ;
2008-01-17 10:59:51 +01:00
ASSERT_EFI_ERROR ( Status ) ;
}
}
2008-12-12 10:27:17 +01:00
/**
Initializes variable store area for non - volatile and volatile variable .
2010-01-15 09:03:23 +01:00
@ param FvbProtocol Pointer to an instance of EFI Firmware Volume Block Protocol .
2008-12-12 10:27:17 +01:00
@ retval EFI_SUCCESS Function successfully executed .
@ retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource .
* */
2007-07-19 12:09:07 +02:00
EFI_STATUS
VariableCommonInitialize (
2009-03-09 07:39:13 +01:00
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL * FvbProtocol
2007-07-19 12:09:07 +02:00
)
{
EFI_STATUS Status ;
VARIABLE_STORE_HEADER * VolatileVariableStore ;
VARIABLE_STORE_HEADER * VariableStoreHeader ;
VARIABLE_HEADER * NextVariable ;
2009-03-09 07:39:13 +01:00
EFI_PHYSICAL_ADDRESS TempVariableStoreHeader ;
2007-07-19 12:09:07 +02:00
EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor ;
2009-03-09 07:39:13 +01:00
EFI_PHYSICAL_ADDRESS BaseAddress ;
2007-07-19 12:09:07 +02:00
UINT64 Length ;
UINTN Index ;
UINT8 Data ;
2009-03-09 07:39:13 +01:00
EFI_PHYSICAL_ADDRESS VariableStoreBase ;
2007-10-05 16:40:23 +02:00
UINT64 VariableStoreLength ;
2008-01-17 10:59:51 +01:00
EFI_EVENT ReadyToBootEvent ;
2009-04-07 08:42:12 +02:00
UINTN ScratchSize ;
2010-01-15 09:03:23 +01:00
UINTN VariableSize ;
2007-07-19 12:09:07 +02:00
2008-01-17 10:59:51 +01:00
Status = EFI_SUCCESS ;
//
// Allocate runtime memory for variable driver global structure.
//
2009-04-27 09:06:01 +02:00
mVariableModuleGlobal = AllocateRuntimeZeroPool ( sizeof ( VARIABLE_MODULE_GLOBAL ) ) ;
2008-01-17 10:59:51 +01:00
if ( mVariableModuleGlobal = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
2007-07-19 12:09:07 +02:00
2007-10-05 16:40:23 +02:00
EfiInitializeLock ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock , TPL_NOTIFY ) ;
2007-07-19 12:09:07 +02:00
2009-08-26 04:59:28 +02:00
//
// Note that in EdkII variable driver implementation, Hardware Error Record type variable
// is stored with common variable in the same NV region. So the platform integrator should
// ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
// PcdFlashNvStorageVariableSize.
//
2010-01-30 00:39:48 +01:00
ASSERT ( PcdGet32 ( PcdHwErrStorageSize ) < = PcdGet32 ( PcdFlashNvStorageVariableSize ) ) ;
2009-08-26 04:59:28 +02:00
2007-07-19 12:09:07 +02:00
//
2009-04-07 08:42:12 +02:00
// Allocate memory for volatile variable store, note that there is a scratch space to store scratch data.
2007-07-19 12:09:07 +02:00
//
2010-01-30 00:39:48 +01:00
ScratchSize = MAX ( PcdGet32 ( PcdMaxVariableSize ) , PcdGet32 ( PcdMaxHardwareErrorVariableSize ) ) ;
VolatileVariableStore = AllocateRuntimePool ( PcdGet32 ( PcdVariableStoreSize ) + ScratchSize ) ;
2007-07-19 12:09:07 +02:00
if ( VolatileVariableStore = = NULL ) {
FreePool ( mVariableModuleGlobal ) ;
return EFI_OUT_OF_RESOURCES ;
}
2010-01-30 00:39:48 +01:00
SetMem ( VolatileVariableStore , PcdGet32 ( PcdVariableStoreSize ) + ScratchSize , 0xff ) ;
2007-07-19 12:09:07 +02:00
//
// Variable Specific Data
//
2007-10-05 16:40:23 +02:00
mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase = ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) VolatileVariableStore ;
2008-01-10 05:26:13 +01:00
mVariableModuleGlobal - > VolatileLastVariableOffset = ( UINTN ) GetStartPointer ( VolatileVariableStore ) - ( UINTN ) VolatileVariableStore ;
2009-03-09 07:39:13 +01:00
mVariableModuleGlobal - > FvbInstance = FvbProtocol ;
2007-07-19 12:09:07 +02:00
2009-02-27 06:35:08 +01:00
CopyGuid ( & VolatileVariableStore - > Signature , & gEfiVariableGuid ) ;
2010-01-30 00:39:48 +01:00
VolatileVariableStore - > Size = PcdGet32 ( PcdVariableStoreSize ) ;
2007-07-19 12:09:07 +02:00
VolatileVariableStore - > Format = VARIABLE_STORE_FORMATTED ;
VolatileVariableStore - > State = VARIABLE_STORE_HEALTHY ;
VolatileVariableStore - > Reserved = 0 ;
VolatileVariableStore - > Reserved1 = 0 ;
//
// Get non volatile varaible store
//
2009-03-09 07:39:13 +01:00
TempVariableStoreHeader = ( EFI_PHYSICAL_ADDRESS ) PcdGet32 ( PcdFlashNvStorageVariableBase ) ;
2007-10-05 16:40:23 +02:00
VariableStoreBase = TempVariableStoreHeader + \
2009-03-09 07:39:13 +01:00
( ( ( EFI_FIRMWARE_VOLUME_HEADER * ) ( UINTN ) ( TempVariableStoreHeader ) ) - > HeaderLength ) ;
2007-10-05 16:40:23 +02:00
VariableStoreLength = ( UINT64 ) PcdGet32 ( PcdFlashNvStorageVariableSize ) - \
2009-03-09 07:39:13 +01:00
( ( ( EFI_FIRMWARE_VOLUME_HEADER * ) ( UINTN ) ( TempVariableStoreHeader ) ) - > HeaderLength ) ;
2007-07-19 12:09:07 +02:00
//
// Mark the variable storage region of the FLASH as RUNTIME
//
2007-10-05 16:40:23 +02:00
BaseAddress = VariableStoreBase & ( ~ EFI_PAGE_MASK ) ;
Length = VariableStoreLength + ( VariableStoreBase - BaseAddress ) ;
2007-07-19 12:09:07 +02:00
Length = ( Length + EFI_PAGE_SIZE - 1 ) & ( ~ EFI_PAGE_MASK ) ;
Status = gDS - > GetMemorySpaceDescriptor ( BaseAddress , & GcdDescriptor ) ;
if ( EFI_ERROR ( Status ) ) {
2008-01-17 10:59:51 +01:00
goto Done ;
2007-07-19 12:09:07 +02:00
}
Status = gDS - > SetMemorySpaceAttributes (
BaseAddress ,
Length ,
GcdDescriptor . Attributes | EFI_MEMORY_RUNTIME
) ;
if ( EFI_ERROR ( Status ) ) {
2008-01-17 10:59:51 +01:00
goto Done ;
2007-07-19 12:09:07 +02:00
}
//
// Get address of non volatile variable store base
//
2007-10-05 16:40:23 +02:00
mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase = VariableStoreBase ;
2009-03-09 07:39:13 +01:00
VariableStoreHeader = ( VARIABLE_STORE_HEADER * ) ( UINTN ) VariableStoreBase ;
2007-07-19 12:09:07 +02:00
if ( GetVariableStoreStatus ( VariableStoreHeader ) = = EfiValid ) {
if ( ~ VariableStoreHeader - > Size = = 0 ) {
Status = UpdateVariableStore (
2007-10-05 16:40:23 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
2007-07-19 12:09:07 +02:00
FALSE ,
FALSE ,
mVariableModuleGlobal - > FvbInstance ,
( UINTN ) & VariableStoreHeader - > Size ,
sizeof ( UINT32 ) ,
2007-10-05 16:40:23 +02:00
( UINT8 * ) & VariableStoreLength
2007-07-19 12:09:07 +02:00
) ;
//
// As Variables are stored in NV storage, which are slow devices,such as flash.
// Variable operation may skip checking variable program result to improve performance,
// We can assume Variable program is OK through some check point.
// Variable Store Size Setting should be the first Variable write operation,
// We can assume all Read/Write is OK if we can set Variable store size successfully.
// If write fail, we will assert here
//
2007-10-05 16:40:23 +02:00
ASSERT ( VariableStoreHeader - > Size = = VariableStoreLength ) ;
2007-07-19 12:09:07 +02:00
if ( EFI_ERROR ( Status ) ) {
2008-01-17 10:59:51 +01:00
goto Done ;
2007-07-19 12:09:07 +02:00
}
}
//
// Parse non-volatile variable data and get last variable offset
//
2009-03-09 07:39:13 +01:00
NextVariable = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) VariableStoreBase ) ;
2007-07-19 12:09:07 +02:00
Status = EFI_SUCCESS ;
while ( IsValidVariableHeader ( NextVariable ) ) {
2009-04-07 08:42:12 +02:00
VariableSize = NextVariable - > NameSize + NextVariable - > DataSize + sizeof ( VARIABLE_HEADER ) ;
if ( ( NextVariable - > Attributes & ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) = = ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
mVariableModuleGlobal - > HwErrVariableTotalSize + = HEADER_ALIGN ( VariableSize ) ;
} else {
mVariableModuleGlobal - > CommonVariableTotalSize + = HEADER_ALIGN ( VariableSize ) ;
}
2007-07-19 12:09:07 +02:00
NextVariable = GetNextVariablePtr ( NextVariable ) ;
}
2009-03-09 07:39:13 +01:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset = ( UINTN ) NextVariable - ( UINTN ) VariableStoreBase ;
2007-07-19 12:09:07 +02:00
//
// Check if the free area is really free.
//
for ( Index = mVariableModuleGlobal - > NonVolatileLastVariableOffset ; Index < VariableStoreHeader - > Size ; Index + + ) {
2007-10-05 16:40:23 +02:00
Data = ( ( UINT8 * ) ( UINTN ) mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ) [ Index ] ;
2007-07-19 12:09:07 +02:00
if ( Data ! = 0xff ) {
//
// There must be something wrong in variable store, do reclaim operation.
//
Status = Reclaim (
2007-10-05 16:40:23 +02:00
mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ,
2007-07-19 12:09:07 +02:00
& mVariableModuleGlobal - > NonVolatileLastVariableOffset ,
2008-03-19 08:09:03 +01:00
FALSE ,
NULL
2007-07-19 12:09:07 +02:00
) ;
2008-01-17 10:59:51 +01:00
if ( EFI_ERROR ( Status ) ) {
goto Done ;
}
2007-07-19 12:09:07 +02:00
break ;
}
}
2008-01-17 10:59:51 +01:00
//
// Register the event handling function to reclaim variable for OS usage.
//
Status = EfiCreateEventReadyToBootEx (
TPL_NOTIFY ,
ReclaimForOS ,
NULL ,
& ReadyToBootEvent
) ;
2009-03-05 03:59:11 +01:00
} else {
Status = EFI_VOLUME_CORRUPTED ;
DEBUG ( ( EFI_D_INFO , " Variable Store header is corrupted \n " ) ) ;
2007-07-19 12:09:07 +02:00
}
2008-01-17 10:59:51 +01:00
Done :
2007-07-19 12:09:07 +02:00
if ( EFI_ERROR ( Status ) ) {
FreePool ( mVariableModuleGlobal ) ;
FreePool ( VolatileVariableStore ) ;
}
return Status ;
}
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
/**
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event .
It convers pointer to new virtual address .
@ param Event Event whose notification function is being invoked
@ param Context Pointer to the notification function ' s context
* */
2007-10-05 16:40:23 +02:00
VOID
EFIAPI
VariableClassAddressChangeEvent (
IN EFI_EVENT Event ,
IN VOID * Context
)
{
2009-03-09 07:39:13 +01:00
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal - > FvbInstance - > GetBlockSize ) ;
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal - > FvbInstance - > GetPhysicalAddress ) ;
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal - > FvbInstance - > GetAttributes ) ;
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal - > FvbInstance - > SetAttributes ) ;
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal - > FvbInstance - > Read ) ;
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal - > FvbInstance - > Write ) ;
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal - > FvbInstance - > EraseBlocks ) ;
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal - > FvbInstance ) ;
2007-10-05 16:40:23 +02:00
EfiConvertPointer (
0x0 ,
( VOID * * ) & mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase
) ;
EfiConvertPointer (
0x0 ,
( VOID * * ) & mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase
) ;
EfiConvertPointer ( 0x0 , ( VOID * * ) & mVariableModuleGlobal ) ;
}
2010-01-15 09:03:23 +01:00
/**
Firmware Volume Block Protocol notification event handler .
Discover NV Variable Store and install Variable Arch Protocol .
@ param [ in ] Event Event whose notification function is being invoked .
@ param [ in ] Context Pointer to the notification function ' s context .
* */
2009-03-09 07:39:13 +01:00
VOID
EFIAPI
FvbNotificationEvent (
IN EFI_EVENT Event ,
IN VOID * Context
)
{
EFI_STATUS Status ;
EFI_HANDLE * HandleBuffer ;
UINTN HandleCount ;
UINTN Index ;
EFI_PHYSICAL_ADDRESS FvbBaseAddress ;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL * Fvb ;
EFI_FIRMWARE_VOLUME_HEADER * FwVolHeader ;
EFI_FVB_ATTRIBUTES_2 Attributes ;
EFI_SYSTEM_TABLE * SystemTable ;
EFI_PHYSICAL_ADDRESS NvStorageVariableBase ;
SystemTable = ( EFI_SYSTEM_TABLE * ) Context ;
Fvb = NULL ;
//
// Locate all handles of Fvb protocol
//
Status = gBS - > LocateHandleBuffer (
ByProtocol ,
& gEfiFirmwareVolumeBlockProtocolGuid ,
NULL ,
& HandleCount ,
& HandleBuffer
) ;
if ( EFI_ERROR ( Status ) ) {
return ;
}
//
// Get the FVB to access variable store
//
2009-03-10 09:40:29 +01:00
for ( Index = 0 ; Index < HandleCount ; Index + = 1 , Status = EFI_NOT_FOUND , Fvb = NULL ) {
2009-03-09 07:39:13 +01:00
Status = gBS - > HandleProtocol (
HandleBuffer [ Index ] ,
& gEfiFirmwareVolumeBlockProtocolGuid ,
( VOID * * ) & Fvb
) ;
if ( EFI_ERROR ( Status ) ) {
Status = EFI_NOT_FOUND ;
break ;
}
//
// Ensure this FVB protocol supported Write operation.
//
Status = Fvb - > GetAttributes ( Fvb , & Attributes ) ;
if ( EFI_ERROR ( Status ) | | ( ( Attributes & EFI_FVB2_WRITE_STATUS ) = = 0 ) ) {
continue ;
}
//
// Compare the address and select the right one
//
Status = Fvb - > GetPhysicalAddress ( Fvb , & FvbBaseAddress ) ;
if ( EFI_ERROR ( Status ) ) {
continue ;
}
FwVolHeader = ( EFI_FIRMWARE_VOLUME_HEADER * ) ( ( UINTN ) FvbBaseAddress ) ;
NvStorageVariableBase = ( EFI_PHYSICAL_ADDRESS ) PcdGet32 ( PcdFlashNvStorageVariableBase ) ;
if ( ( NvStorageVariableBase > = FvbBaseAddress ) & & ( NvStorageVariableBase < ( FvbBaseAddress + FwVolHeader - > FvLength ) ) ) {
Status = EFI_SUCCESS ;
break ;
}
}
FreePool ( HandleBuffer ) ;
2009-03-10 09:40:29 +01:00
if ( ! EFI_ERROR ( Status ) & & Fvb ! = NULL ) {
2009-03-19 04:13:08 +01:00
//
// Close the notify event to avoid install gEfiVariableArchProtocolGuid & gEfiVariableWriteArchProtocolGuid again.
//
Status = gBS - > CloseEvent ( Event ) ;
ASSERT_EFI_ERROR ( Status ) ;
2009-03-09 07:39:13 +01:00
Status = VariableCommonInitialize ( Fvb ) ;
ASSERT_EFI_ERROR ( Status ) ;
2009-03-16 10:57:10 +01:00
SystemTable - > RuntimeServices - > GetVariable = RuntimeServiceGetVariable ;
2009-03-09 07:39:13 +01:00
SystemTable - > RuntimeServices - > GetNextVariableName = RuntimeServiceGetNextVariableName ;
2009-03-16 10:57:10 +01:00
SystemTable - > RuntimeServices - > SetVariable = RuntimeServiceSetVariable ;
SystemTable - > RuntimeServices - > QueryVariableInfo = RuntimeServiceQueryVariableInfo ;
2009-03-09 07:39:13 +01:00
//
// Now install the Variable Runtime Architectural Protocol on a new handle
//
Status = gBS - > InstallMultipleProtocolInterfaces (
& mHandle ,
& gEfiVariableArchProtocolGuid , NULL ,
& gEfiVariableWriteArchProtocolGuid , NULL ,
NULL
) ;
ASSERT_EFI_ERROR ( Status ) ;
Status = gBS - > CreateEventEx (
EVT_NOTIFY_SIGNAL ,
TPL_NOTIFY ,
VariableClassAddressChangeEvent ,
NULL ,
& gEfiEventVirtualAddressChangeGuid ,
& mVirtualAddressChangeEvent
) ;
ASSERT_EFI_ERROR ( Status ) ;
}
}
2007-10-05 16:40:23 +02:00
/**
Variable Driver main entry point . The Variable driver places the 4 EFI
runtime services in the EFI System Table and installs arch protocols
2008-12-12 10:27:17 +01:00
for variable read and write services being availible . It also registers
notification function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event .
2007-10-05 16:40:23 +02:00
@ param [ in ] ImageHandle The firmware allocated handle for the EFI image .
@ param [ in ] SystemTable A pointer to the EFI System Table .
2008-12-12 10:27:17 +01:00
@ retval EFI_SUCCESS Variable service successfully initialized .
2007-10-05 16:40:23 +02:00
* */
EFI_STATUS
EFIAPI
VariableServiceInitialize (
IN EFI_HANDLE ImageHandle ,
IN EFI_SYSTEM_TABLE * SystemTable
)
{
//
2009-03-09 07:39:13 +01:00
// Register FvbNotificationEvent () notify function.
//
EfiCreateProtocolNotifyEvent (
& gEfiFirmwareVolumeBlockProtocolGuid ,
TPL_CALLBACK ,
FvbNotificationEvent ,
( VOID * ) SystemTable ,
& mFvbRegistration
) ;
2007-10-05 16:40:23 +02:00
return EFI_SUCCESS ;
}