2007-10-05 16:40:23 +02:00
/** @file
2015-07-01 05:08:29 +02:00
The common variable operation routines shared by DXE_RUNTIME variable
2010-12-10 10:27:54 +01:00
module and DXE_SMM variable module .
2015-07-01 05:08:29 +02:00
2014-11-19 02:08:23 +01:00
Caution : This module requires additional review when modified .
This driver will have external input - variable data . They may be input in SMM mode .
This external input must be validated carefully to avoid security issue like
buffer overflow , integer overflow .
VariableServiceGetNextVariableName ( ) and VariableServiceQueryVariableInfo ( ) are external API .
They need check input parameter .
VariableServiceGetVariable ( ) and VariableServiceSetVariable ( ) are external API
to receive datasize and data buffer . The size should be checked carefully .
2015-07-01 05:08:29 +02:00
VariableServiceSetVariable ( ) should also check authenticate data to avoid buffer overflow ,
integer overflow . It should also check attribute to avoid authentication bypass .
2016-01-19 14:22:05 +01:00
Copyright ( c ) 2006 - 2016 , Intel Corporation . All rights reserved . < BR >
2015-10-23 07:28:38 +02:00
( C ) Copyright 2015 Hewlett Packard Enterprise Development LP < BR >
2015-07-01 05:08:29 +02:00
This program and the accompanying materials
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
2008-04-09 09:07:50 +02:00
2015-07-01 05:08:29 +02:00
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-07-19 12:09:07 +02:00
2008-12-12 10:27:17 +01:00
///
2010-12-10 10:27:54 +01:00
/// Define a memory cache that improves the search performance for a variable.
2008-12-12 10:27:17 +01:00
///
2013-05-17 05:49:35 +02:00
VARIABLE_STORE_HEADER * mNvVariableCache = NULL ;
2008-12-03 09:52:39 +01:00
2015-10-23 07:28:38 +02:00
///
/// Memory cache of Fv Header.
///
EFI_FIRMWARE_VOLUME_HEADER * mNvFvHeaderCache = NULL ;
2010-12-10 10:27:54 +01:00
///
/// The memory entry used for variable statistics data.
///
2013-05-17 05:49:35 +02:00
VARIABLE_INFO_ENTRY * gVariableInfo = NULL ;
///
/// The flag to indicate whether the platform has left the DXE phase of execution.
///
BOOLEAN mEndOfDxe = FALSE ;
///
2015-08-25 05:01:56 +02:00
/// It indicates the var check request source.
/// In the implementation, DXE is regarded as untrusted, and SMM is trusted.
2013-05-17 05:49:35 +02:00
///
2015-08-25 05:01:56 +02:00
VAR_CHECK_REQUEST_SOURCE mRequestSource = VarCheckFromUntrusted ;
2007-07-19 12:09:07 +02:00
2015-02-02 04:17:27 +01:00
//
// It will record the current boot error flag before EndOfDxe.
//
VAR_ERROR_FLAG mCurrentBootVarErrFlag = VAR_ERROR_FLAG_NO_ERROR ;
2007-10-04 23:01:21 +02:00
2015-07-01 05:08:29 +02:00
VARIABLE_ENTRY_PROPERTY mVariableEntryProperty [ ] = {
{
& gEdkiiVarErrorFlagGuid ,
VAR_ERROR_FLAG_NAME ,
{
VAR_CHECK_VARIABLE_PROPERTY_REVISION ,
VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY ,
VARIABLE_ATTRIBUTE_NV_BS_RT ,
sizeof ( VAR_ERROR_FLAG ) ,
sizeof ( VAR_ERROR_FLAG )
}
} ,
} ;
2015-08-25 05:01:56 +02:00
AUTH_VAR_LIB_CONTEXT_IN mAuthContextIn = {
2015-07-01 05:08:29 +02:00
AUTH_VAR_LIB_CONTEXT_IN_STRUCT_VERSION ,
2015-07-02 12:06:32 +02:00
//
// StructSize, TO BE FILLED
//
0 ,
2015-07-01 05:08:29 +02:00
//
// MaxAuthVariableSize, TO BE FILLED
//
0 ,
VariableExLibFindVariable ,
VariableExLibFindNextVariable ,
VariableExLibUpdateVariable ,
VariableExLibGetScratchBuffer ,
VariableExLibCheckRemainingSpaceForConsistency ,
VariableExLibAtRuntime ,
} ;
2015-08-25 05:01:56 +02:00
AUTH_VAR_LIB_CONTEXT_OUT mAuthContextOut ;
2015-07-01 05:08:29 +02:00
2007-10-05 16:40:23 +02:00
/**
2015-07-01 05:08:29 +02:00
SecureBoot Hook for auth variable update .
@ param [ in ] VariableName Name of Variable to be found .
@ param [ in ] VendorGuid Variable vendor GUID .
* */
VOID
EFIAPI
SecureBootHook (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid
) ;
2016-01-19 14:22:05 +01:00
/**
Initialization for MOR Lock Control .
@ retval EFI_SUCEESS MorLock initialization success .
@ return Others Some error occurs .
* */
EFI_STATUS
MorLockInit (
VOID
) ;
/**
This service is an MOR / MorLock checker handler for the SetVariable ( ) .
@ param VariableName the name of the vendor ' s variable , as a
Null - Terminated Unicode String
@ param VendorGuid Unify identifier for vendor .
@ param Attributes Point to memory location to return the attributes of variable . If the point
is NULL , the parameter would be ignored .
@ param DataSize The size in bytes of Data - Buffer .
@ param Data Point to the content of the variable .
@ retval EFI_SUCCESS The MOR / MorLock check pass , and Variable driver can store the variable data .
@ retval EFI_INVALID_PARAMETER The MOR / MorLock data or data size or attributes is not allowed for MOR variable .
@ retval EFI_ACCESS_DENIED The MOR / MorLock is locked .
@ retval EFI_ALREADY_STARTED The MorLock variable is handled inside this function .
Variable driver can just return EFI_SUCCESS .
* */
EFI_STATUS
SetVariableCheckHandlerMor (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
IN UINT32 Attributes ,
IN UINTN DataSize ,
IN VOID * Data
) ;
2015-07-01 05:08:29 +02:00
/**
Routine used to track statistical information about variable usage .
2007-10-05 16:40:23 +02:00
The data is stored in the EFI system table so it can be accessed later .
2015-07-01 05:08:29 +02:00
VariableInfo . efi can dump out the table . Only Boot Services variable
2007-10-05 16:40:23 +02:00
accesses are tracked by this code . The PcdVariableCollectStatistics
2015-07-01 05:08:29 +02:00
build flag controls if this feature is enabled .
2007-10-05 16:40:23 +02:00
2015-07-01 05:08:29 +02:00
A read that hits in the cache will have Read and Cache true for
2007-10-05 16:40:23 +02:00
the transaction . Data is allocated by this routine , but never
freed .
2010-12-10 10:27:54 +01:00
@ 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 ( ) .
2007-10-05 16:40:23 +02:00
@ 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 ) ) {
2010-12-10 10:27:54 +01:00
if ( AtRuntime ( ) ) {
// Don't collect statistics at runtime.
2007-10-04 23:01:21 +02:00
return ;
}
if ( gVariableInfo = = NULL ) {
2007-10-05 16:40:23 +02:00
//
2010-12-10 10:27:54 +01:00
// On the first call allocate a entry and place a pointer to it in
// the EFI System Table.
2007-10-05 16:40:23 +02:00
//
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 ) ;
2014-08-07 10:54:34 +02:00
gVariableInfo - > Name = AllocateZeroPool ( StrSize ( VariableName ) ) ;
2009-01-16 09:14:39 +01:00
ASSERT ( gVariableInfo - > Name ! = NULL ) ;
2015-07-01 10:34:22 +02:00
StrCpyS ( gVariableInfo - > Name , StrSize ( VariableName ) / sizeof ( CHAR16 ) , VariableName ) ;
2007-10-04 23:01:21 +02:00
gVariableInfo - > Volatile = Volatile ;
}
2015-07-01 05:08:29 +02:00
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.
2010-12-10 10:27:54 +01:00
// Next iteration of the loop will fill in the data.
2007-10-05 16:40:23 +02:00
//
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 ) ;
2014-08-07 10:54:34 +02:00
Entry - > Next - > Name = AllocateZeroPool ( StrSize ( VariableName ) ) ;
2009-01-16 09:14:39 +01:00
ASSERT ( Entry - > Next - > Name ! = NULL ) ;
2015-07-01 10:34:22 +02:00
StrCpyS ( Entry - > Next - > Name , StrSize ( VariableName ) / sizeof ( CHAR16 ) , VariableName ) ;
2007-10-04 23:01:21 +02:00
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 .
2014-10-31 11:26:54 +01:00
@ param Variable Pointer to the Variable Header .
@ param VariableStoreEnd Pointer to the Variable Store End .
2007-07-19 12:09:07 +02:00
2014-10-31 11:26:54 +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 (
2014-10-31 11:26:54 +01:00
IN VARIABLE_HEADER * Variable ,
IN VARIABLE_HEADER * VariableStoreEnd
2008-12-12 10:27:17 +01:00
)
2007-07-19 12:09:07 +02:00
{
2014-10-31 11:26:54 +01:00
if ( ( Variable = = NULL ) | | ( Variable > = VariableStoreEnd ) | | ( Variable - > StartId ! = VARIABLE_DATA ) ) {
//
// Variable is NULL or has reached the end of variable store,
// or the StartId is not correct.
//
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 .
2010-12-10 10:27:54 +01:00
@ 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 .
@ 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
2010-12-10 10:27:54 +01:00
structure .
@ param DataSize Size of data to be written .
@ param Buffer Pointer to the buffer from which data is written .
2008-12-12 10:27:17 +01:00
2010-12-10 10:27:54 +01:00
@ retval EFI_INVALID_PARAMETER Parameters not valid .
@ retval EFI_SUCCESS Variable store successfully updated .
2008-12-12 10:27:17 +01:00
* */
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 ;
//
2010-12-10 10:27:54 +01:00
// Check if the Data is Volatile.
2007-07-19 12:09:07 +02:00
//
if ( ! Volatile ) {
2015-07-01 05:08:29 +02:00
if ( Fvb = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
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
2010-12-10 10:27:54 +01:00
// written.
2007-07-19 12:09:07 +02:00
//
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
2010-12-10 10:27:54 +01:00
// written.
2007-07-19 12:09:07 +02:00
//
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 ;
}
2015-07-01 05:08:29 +02:00
2007-09-17 05:50:40 +02:00
//
// If Volatile Variable just do a simple mem copy.
2015-07-01 05:08:29 +02:00
//
2007-09-17 05:50:40 +02:00
CopyMem ( ( UINT8 * ) ( UINTN ) DataPtr , Buffer , DataSize ) ;
2007-07-19 12:09:07 +02:00
return EFI_SUCCESS ;
}
2015-07-01 05:08:29 +02:00
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// If we are here we are dealing with Non-Volatile Variables.
2007-07-19 12:09:07 +02:00
//
LinearOffset = ( UINTN ) FwVolHeader ;
CurrWritePtr = ( UINTN ) DataPtr ;
CurrWriteSize = DataSize ;
CurrBuffer = Buffer ;
LbaNumber = 0 ;
if ( CurrWritePtr < LinearOffset ) {
return EFI_INVALID_PARAMETER ;
}
2015-10-23 07:28:38 +02:00
for ( PtrBlockMapEntry = mNvFvHeaderCache - > BlockMap ; PtrBlockMapEntry - > NumBlocks ! = 0 ; PtrBlockMapEntry + + ) {
2007-07-19 12:09:07 +02:00
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
2010-12-10 10:27:54 +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
{
2015-07-01 05:08:29 +02:00
if ( ( CompareGuid ( & VarStoreHeader - > Signature , & gEfiAuthenticatedVariableGuid ) | |
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 ;
}
}
2015-07-01 05:08:29 +02:00
/**
This code gets the size of variable header .
@ return Size of variable header in bytes in type UINTN .
* */
UINTN
GetVariableHeaderSize (
VOID
)
{
UINTN Value ;
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
Value = sizeof ( AUTHENTICATED_VARIABLE_HEADER ) ;
} else {
Value = sizeof ( VARIABLE_HEADER ) ;
}
return Value ;
}
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 .
2010-12-10 10:27:54 +01:00
@ param Variable Pointer to the Variable Header .
2008-01-14 07:35:23 +01:00
2010-12-10 10:27:54 +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
{
2015-07-01 05:08:29 +02:00
AUTHENTICATED_VARIABLE_HEADER * AuthVariable ;
AuthVariable = ( AUTHENTICATED_VARIABLE_HEADER * ) Variable ;
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
if ( AuthVariable - > State = = ( UINT8 ) ( - 1 ) | |
AuthVariable - > DataSize = = ( UINT32 ) ( - 1 ) | |
AuthVariable - > NameSize = = ( UINT32 ) ( - 1 ) | |
AuthVariable - > Attributes = = ( UINT32 ) ( - 1 ) ) {
return 0 ;
}
return ( UINTN ) AuthVariable - > NameSize ;
} else {
if ( Variable - > State = = ( UINT8 ) ( - 1 ) | |
Variable - > DataSize = = ( UINT32 ) ( - 1 ) | |
Variable - > NameSize = = ( UINT32 ) ( - 1 ) | |
Variable - > Attributes = = ( UINT32 ) ( - 1 ) ) {
return 0 ;
}
return ( UINTN ) Variable - > NameSize ;
}
}
/**
This code sets the size of name of variable .
@ param [ in ] Variable Pointer to the Variable Header .
@ param [ in ] NameSize Name size to set .
* */
VOID
SetNameSizeOfVariable (
IN VARIABLE_HEADER * Variable ,
IN UINTN NameSize
)
{
AUTHENTICATED_VARIABLE_HEADER * AuthVariable ;
AuthVariable = ( AUTHENTICATED_VARIABLE_HEADER * ) Variable ;
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
AuthVariable - > NameSize = ( UINT32 ) NameSize ;
} else {
Variable - > NameSize = ( UINT32 ) NameSize ;
2008-01-14 07:35:23 +01:00
}
}
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
2010-12-10 10:27:54 +01:00
@ param Variable Pointer to the Variable Header .
2008-01-14 07:35:23 +01:00
2010-12-10 10:27:54 +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
{
2015-07-01 05:08:29 +02:00
AUTHENTICATED_VARIABLE_HEADER * AuthVariable ;
AuthVariable = ( AUTHENTICATED_VARIABLE_HEADER * ) Variable ;
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
if ( AuthVariable - > State = = ( UINT8 ) ( - 1 ) | |
AuthVariable - > DataSize = = ( UINT32 ) ( - 1 ) | |
AuthVariable - > NameSize = = ( UINT32 ) ( - 1 ) | |
AuthVariable - > Attributes = = ( UINT32 ) ( - 1 ) ) {
return 0 ;
}
return ( UINTN ) AuthVariable - > DataSize ;
} else {
if ( Variable - > State = = ( UINT8 ) ( - 1 ) | |
Variable - > DataSize = = ( UINT32 ) ( - 1 ) | |
Variable - > NameSize = = ( UINT32 ) ( - 1 ) | |
Variable - > Attributes = = ( UINT32 ) ( - 1 ) ) {
return 0 ;
}
return ( UINTN ) Variable - > DataSize ;
}
}
/**
This code sets the size of variable data .
@ param [ in ] Variable Pointer to the Variable Header .
@ param [ in ] DataSize Data size to set .
* */
VOID
SetDataSizeOfVariable (
IN VARIABLE_HEADER * Variable ,
IN UINTN DataSize
)
{
AUTHENTICATED_VARIABLE_HEADER * AuthVariable ;
AuthVariable = ( AUTHENTICATED_VARIABLE_HEADER * ) Variable ;
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
AuthVariable - > DataSize = ( UINT32 ) DataSize ;
} else {
Variable - > DataSize = ( UINT32 ) DataSize ;
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 pointer to the variable name .
2010-12-10 10:27:54 +01:00
@ param Variable Pointer to the Variable Header .
2008-01-14 07:35:23 +01:00
2010-12-10 10:27:54 +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
{
2015-07-01 05:08:29 +02:00
return ( CHAR16 * ) ( ( UINTN ) Variable + GetVariableHeaderSize ( ) ) ;
}
2008-01-14 07:35:23 +01:00
2015-07-01 05:08:29 +02:00
/**
This code gets the pointer to the variable guid .
@ param Variable Pointer to the Variable Header .
@ return A EFI_GUID * pointer to Vendor Guid .
* */
EFI_GUID *
GetVendorGuidPtr (
IN VARIABLE_HEADER * Variable
)
{
AUTHENTICATED_VARIABLE_HEADER * AuthVariable ;
AuthVariable = ( AUTHENTICATED_VARIABLE_HEADER * ) Variable ;
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
return & AuthVariable - > VendorGuid ;
} else {
return & Variable - > VendorGuid ;
}
2008-01-14 07:35:23 +01:00
}
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 .
2010-12-10 10:27:54 +01:00
@ param Variable Pointer to the Variable Header .
2007-07-19 12:09:07 +02:00
2010-12-10 10:27:54 +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 ;
2015-07-01 05:08:29 +02:00
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// Be careful about pad size for alignment.
2007-07-19 12:09:07 +02:00
//
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
}
2015-07-01 05:08:29 +02:00
/**
This code gets the variable data offset related to variable header .
@ param Variable Pointer to the Variable Header .
@ return Variable Data offset .
* */
UINTN
GetVariableDataOffset (
IN VARIABLE_HEADER * Variable
)
{
UINTN Value ;
//
// Be careful about pad size for alignment
//
Value = GetVariableHeaderSize ( ) ;
Value + = NameSizeOfVariable ( Variable ) ;
Value + = GET_PAD_SIZE ( NameSizeOfVariable ( Variable ) ) ;
return Value ;
}
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 .
2010-12-10 10:27:54 +01:00
@ param Variable Pointer to the Variable Header .
2007-07-19 12:09:07 +02:00
2010-12-10 10:27:54 +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 ;
Value = ( UINTN ) GetVariableDataPtr ( Variable ) ;
Value + = DataSizeOfVariable ( Variable ) ;
Value + = GET_PAD_SIZE ( DataSizeOfVariable ( Variable ) ) ;
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// Be careful about pad size for alignment.
2007-07-19 12:09:07 +02:00
//
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
2010-12-10 10:27:54 +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
{
//
2010-12-10 10:27:54 +01:00
// The end of variable store.
2008-01-10 05:26:13 +01:00
//
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
2010-12-10 10:27:54 +01:00
@ param VarStoreHeader Pointer to the Variable Store Header .
2007-07-19 12:09:07 +02:00
2015-07-01 05:08:29 +02: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
}
2015-01-27 09:42:47 +01:00
/**
Record variable error flag .
@ param [ in ] Flag Variable error flag to record .
@ param [ in ] VariableName Name of variable .
@ param [ in ] VendorGuid Guid of variable .
@ param [ in ] Attributes Attributes of the variable .
@ param [ in ] VariableSize Size of the variable .
* */
VOID
RecordVarErrorFlag (
IN VAR_ERROR_FLAG Flag ,
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
IN UINT32 Attributes ,
IN UINTN VariableSize
)
{
EFI_STATUS Status ;
VARIABLE_POINTER_TRACK Variable ;
VAR_ERROR_FLAG * VarErrFlag ;
VAR_ERROR_FLAG TempFlag ;
DEBUG_CODE (
DEBUG ( ( EFI_D_ERROR , " RecordVarErrorFlag (0x%02x) %s:%g - 0x%08x - 0x%x \n " , Flag , VariableName , VendorGuid , Attributes , VariableSize ) ) ;
if ( Flag = = VAR_ERROR_FLAG_SYSTEM_ERROR ) {
if ( AtRuntime ( ) ) {
DEBUG ( ( EFI_D_ERROR , " CommonRuntimeVariableSpace = 0x%x - CommonVariableTotalSize = 0x%x \n " , mVariableModuleGlobal - > CommonRuntimeVariableSpace , mVariableModuleGlobal - > CommonVariableTotalSize ) ) ;
} else {
DEBUG ( ( EFI_D_ERROR , " CommonVariableSpace = 0x%x - CommonVariableTotalSize = 0x%x \n " , mVariableModuleGlobal - > CommonVariableSpace , mVariableModuleGlobal - > CommonVariableTotalSize ) ) ;
}
} else {
DEBUG ( ( EFI_D_ERROR , " CommonMaxUserVariableSpace = 0x%x - CommonUserVariableTotalSize = 0x%x \n " , mVariableModuleGlobal - > CommonMaxUserVariableSpace , mVariableModuleGlobal - > CommonUserVariableTotalSize ) ) ;
}
) ;
2015-02-02 04:17:27 +01:00
if ( ! mEndOfDxe ) {
//
// Before EndOfDxe, just record the current boot variable error flag to local variable,
// and leave the variable error flag in NV flash as the last boot variable error flag.
// After EndOfDxe in InitializeVarErrorFlag (), the variable error flag in NV flash
// will be initialized to this local current boot variable error flag.
//
mCurrentBootVarErrFlag & = Flag ;
return ;
}
2015-01-27 09:42:47 +01:00
//
// Record error flag (it should have be initialized).
//
Status = FindVariable (
VAR_ERROR_FLAG_NAME ,
& gEdkiiVarErrorFlagGuid ,
& Variable ,
& mVariableModuleGlobal - > VariableGlobal ,
FALSE
) ;
if ( ! EFI_ERROR ( Status ) ) {
VarErrFlag = ( VAR_ERROR_FLAG * ) GetVariableDataPtr ( Variable . CurrPtr ) ;
TempFlag = * VarErrFlag ;
TempFlag & = Flag ;
if ( TempFlag = = * VarErrFlag ) {
return ;
}
Status = UpdateVariableStore (
& mVariableModuleGlobal - > VariableGlobal ,
FALSE ,
FALSE ,
mVariableModuleGlobal - > FvbInstance ,
( UINTN ) VarErrFlag - ( UINTN ) mNvVariableCache + ( UINTN ) mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ,
sizeof ( TempFlag ) ,
& TempFlag
) ;
if ( ! EFI_ERROR ( Status ) ) {
//
// Update the data in NV cache.
//
2015-12-29 10:04:55 +01:00
* VarErrFlag = TempFlag ;
2015-01-27 09:42:47 +01:00
}
}
}
/**
Initialize variable error flag .
Before EndOfDxe , the variable indicates the last boot variable error flag ,
then it means the last boot variable error flag must be got before EndOfDxe .
After EndOfDxe , the variable indicates the current boot variable error flag ,
then it means the current boot variable error flag must be got after EndOfDxe .
* */
VOID
InitializeVarErrorFlag (
VOID
)
{
EFI_STATUS Status ;
VARIABLE_POINTER_TRACK Variable ;
VAR_ERROR_FLAG Flag ;
VAR_ERROR_FLAG VarErrFlag ;
if ( ! mEndOfDxe ) {
return ;
}
2015-02-02 04:17:27 +01:00
Flag = mCurrentBootVarErrFlag ;
2015-01-27 09:42:47 +01:00
DEBUG ( ( EFI_D_INFO , " Initialize variable error flag (%02x) \n " , Flag ) ) ;
Status = FindVariable (
VAR_ERROR_FLAG_NAME ,
& gEdkiiVarErrorFlagGuid ,
& Variable ,
& mVariableModuleGlobal - > VariableGlobal ,
FALSE
) ;
if ( ! EFI_ERROR ( Status ) ) {
VarErrFlag = * ( ( VAR_ERROR_FLAG * ) GetVariableDataPtr ( Variable . CurrPtr ) ) ;
if ( VarErrFlag = = Flag ) {
return ;
}
}
UpdateVariable (
VAR_ERROR_FLAG_NAME ,
& gEdkiiVarErrorFlagGuid ,
& Flag ,
sizeof ( Flag ) ,
VARIABLE_ATTRIBUTE_NV_BS_RT ,
2015-07-01 05:08:29 +02:00
0 ,
0 ,
& Variable ,
NULL
2015-01-27 09:42:47 +01:00
) ;
}
/**
Is user variable ?
@ param [ in ] Variable Pointer to variable header .
@ retval TRUE User variable .
@ retval FALSE System variable .
* */
BOOLEAN
IsUserVariable (
IN VARIABLE_HEADER * Variable
)
{
VAR_CHECK_VARIABLE_PROPERTY Property ;
//
// Only after End Of Dxe, the variables belong to system variable are fixed.
// If PcdMaxUserNvStorageVariableSize is 0, it means user variable share the same NV storage with system variable,
// then no need to check if the variable is user variable or not specially.
//
if ( mEndOfDxe & & ( mVariableModuleGlobal - > CommonMaxUserVariableSpace ! = mVariableModuleGlobal - > CommonVariableSpace ) ) {
2015-08-25 05:01:56 +02:00
if ( VarCheckLibVariablePropertyGet ( GetVariableNamePtr ( Variable ) , GetVendorGuidPtr ( Variable ) , & Property ) = = EFI_NOT_FOUND ) {
2015-01-27 09:42:47 +01:00
return TRUE ;
}
}
return FALSE ;
}
/**
Calculate common user variable total size .
* */
VOID
CalculateCommonUserVariableTotalSize (
VOID
)
{
VARIABLE_HEADER * Variable ;
VARIABLE_HEADER * NextVariable ;
UINTN VariableSize ;
VAR_CHECK_VARIABLE_PROPERTY Property ;
//
// Only after End Of Dxe, the variables belong to system variable are fixed.
// If PcdMaxUserNvStorageVariableSize is 0, it means user variable share the same NV storage with system variable,
// then no need to calculate the common user variable total size specially.
//
if ( mEndOfDxe & & ( mVariableModuleGlobal - > CommonMaxUserVariableSpace ! = mVariableModuleGlobal - > CommonVariableSpace ) ) {
Variable = GetStartPointer ( mNvVariableCache ) ;
while ( IsValidVariableHeader ( Variable , GetEndPointer ( mNvVariableCache ) ) ) {
NextVariable = GetNextVariablePtr ( Variable ) ;
VariableSize = ( UINTN ) NextVariable - ( UINTN ) Variable ;
if ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
2015-08-25 05:01:56 +02:00
if ( VarCheckLibVariablePropertyGet ( GetVariableNamePtr ( Variable ) , GetVendorGuidPtr ( Variable ) , & Property ) = = EFI_NOT_FOUND ) {
2015-01-27 09:42:47 +01:00
//
// No property, it is user variable.
//
mVariableModuleGlobal - > CommonUserVariableTotalSize + = VariableSize ;
}
}
Variable = NextVariable ;
}
}
}
/**
Initialize variable quota .
* */
VOID
InitializeVariableQuota (
VOID
)
{
2015-08-25 05:01:56 +02:00
if ( ! mEndOfDxe ) {
2015-01-27 09:42:47 +01:00
return ;
}
InitializeVarErrorFlag ( ) ;
CalculateCommonUserVariableTotalSize ( ) ;
}
2007-10-05 16:40:23 +02:00
2008-12-12 10:27:17 +01:00
/**
Variable store garbage collection and reclaim operation .
2015-07-01 05:08:29 +02:00
@ param [ in ] VariableBase Base address of variable store .
@ param [ out ] LastVariableOffset Offset of last variable .
@ param [ in ] IsVolatile The variable store is volatile or not ;
if it is non - volatile , need FTW .
@ param [ in , out ] UpdatingPtrTrack Pointer to updating variable pointer track structure .
@ param [ in ] NewVariable Pointer to new variable .
@ param [ in ] NewVariableSize New variable size .
2008-12-12 10:27:17 +01:00
2015-07-01 05:08:29 +02:00
@ return EFI_SUCCESS Reclaim operation has finished successfully .
@ return EFI_OUT_OF_RESOURCES No enough memory resources or variable space .
@ return Others Unexpect error happened during reclaim operation .
2008-12-12 10:27:17 +01:00
* */
2007-07-19 12:09:07 +02:00
EFI_STATUS
Reclaim (
2015-07-01 05:08:29 +02:00
IN EFI_PHYSICAL_ADDRESS VariableBase ,
OUT UINTN * LastVariableOffset ,
IN BOOLEAN IsVolatile ,
IN OUT VARIABLE_POINTER_TRACK * UpdatingPtrTrack ,
IN VARIABLE_HEADER * NewVariable ,
IN UINTN NewVariableSize
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-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 ;
2012-08-06 05:20:10 +02:00
UINTN CommonVariableTotalSize ;
2015-01-27 09:42:47 +01:00
UINTN CommonUserVariableTotalSize ;
2012-08-06 05:20:10 +02:00
UINTN HwErrVariableTotalSize ;
2013-01-18 02:12:32 +01:00
VARIABLE_HEADER * UpdatingVariable ;
2013-11-04 04:13:54 +01:00
VARIABLE_HEADER * UpdatingInDeletedTransition ;
2013-01-18 02:12:32 +01:00
UpdatingVariable = NULL ;
2013-11-04 04:13:54 +01:00
UpdatingInDeletedTransition = NULL ;
2013-01-18 02:12:32 +01:00
if ( UpdatingPtrTrack ! = NULL ) {
UpdatingVariable = UpdatingPtrTrack - > CurrPtr ;
2013-11-04 04:13:54 +01:00
UpdatingInDeletedTransition = UpdatingPtrTrack - > InDeletedTransitionPtr ;
2013-01-18 02:12:32 +01:00
}
2007-07-19 12:09:07 +02:00
VariableStoreHeader = ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) VariableBase ) ;
2012-08-06 05:20:10 +02:00
CommonVariableTotalSize = 0 ;
2015-01-27 09:42:47 +01:00
CommonUserVariableTotalSize = 0 ;
2012-08-06 05:20:10 +02:00
HwErrVariableTotalSize = 0 ;
2007-07-19 12:09:07 +02:00
2013-11-12 14:31:43 +01:00
if ( IsVolatile ) {
//
// Start Pointers for the variable.
//
Variable = GetStartPointer ( VariableStoreHeader ) ;
MaximumBufferSize = sizeof ( VARIABLE_STORE_HEADER ) ;
2014-10-31 11:26:54 +01:00
while ( IsValidVariableHeader ( Variable , GetEndPointer ( VariableStoreHeader ) ) ) {
2013-11-12 14:31:43 +01:00
NextVariable = GetNextVariablePtr ( Variable ) ;
if ( ( Variable - > State = = VAR_ADDED | | Variable - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) & &
Variable ! = UpdatingVariable & &
Variable ! = UpdatingInDeletedTransition
) {
VariableSize = ( UINTN ) NextVariable - ( UINTN ) Variable ;
MaximumBufferSize + = VariableSize ;
}
2007-07-19 12:09:07 +02:00
2013-11-12 14:31:43 +01:00
Variable = NextVariable ;
2007-07-19 12:09:07 +02:00
}
2013-11-12 14:31:43 +01:00
if ( NewVariable ! = NULL ) {
//
// Add the new variable size.
//
MaximumBufferSize + = NewVariableSize ;
}
2007-07-19 12:09:07 +02:00
2013-11-04 04:13:54 +01:00
//
2013-11-12 14:31:43 +01:00
// Reserve the 1 Bytes with Oxff to identify the
// end of the variable buffer.
2013-11-04 04:13:54 +01:00
//
2013-11-12 14:31:43 +01:00
MaximumBufferSize + = 1 ;
ValidBuffer = AllocatePool ( MaximumBufferSize ) ;
if ( ValidBuffer = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
} else {
//
// For NV variable reclaim, don't allocate pool here and just use mNvVariableCache
// as the buffer to reduce SMRAM consumption for SMM variable driver.
//
MaximumBufferSize = mNvVariableCache - > Size ;
ValidBuffer = ( UINT8 * ) mNvVariableCache ;
2007-07-19 12:09:07 +02:00
}
2008-03-19 08:09:03 +01:00
SetMem ( ValidBuffer , MaximumBufferSize , 0xff ) ;
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// Copy variable store header.
2007-07-19 12:09:07 +02:00
//
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
//
2010-12-10 10:27:54 +01:00
// Reinstall all ADDED variables as long as they are not identical to Updating Variable.
2015-07-01 05:08:29 +02:00
//
2008-03-19 08:09:03 +01:00
Variable = GetStartPointer ( VariableStoreHeader ) ;
2014-10-31 11:26:54 +01:00
while ( IsValidVariableHeader ( Variable , GetEndPointer ( VariableStoreHeader ) ) ) {
2007-07-19 12:09:07 +02:00
NextVariable = GetNextVariablePtr ( Variable ) ;
2013-11-04 04:13:54 +01:00
if ( Variable ! = UpdatingVariable & & Variable - > State = = VAR_ADDED ) {
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 ) ) {
2012-08-06 05:20:10 +02:00
HwErrVariableTotalSize + = VariableSize ;
2009-04-07 08:42:12 +02:00
} else if ( ( ! IsVolatile ) & & ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
2012-08-06 05:20:10 +02:00
CommonVariableTotalSize + = VariableSize ;
2015-01-27 09:42:47 +01:00
if ( IsUserVariable ( Variable ) ) {
CommonUserVariableTotalSize + = VariableSize ;
}
2009-04-07 08:42:12 +02:00
}
2007-07-19 12:09:07 +02:00
}
Variable = NextVariable ;
}
2008-10-12 01:44:40 +02:00
2008-03-19 08:09:03 +01:00
//
2010-12-10 10:27:54 +01:00
// Reinstall all in delete transition variables.
2015-07-01 05:08:29 +02:00
//
2013-11-04 04:13:54 +01:00
Variable = GetStartPointer ( VariableStoreHeader ) ;
2014-10-31 11:26:54 +01:00
while ( IsValidVariableHeader ( Variable , GetEndPointer ( VariableStoreHeader ) ) ) {
2008-03-19 08:09:03 +01:00
NextVariable = GetNextVariablePtr ( Variable ) ;
2013-11-04 04:13:54 +01:00
if ( Variable ! = UpdatingVariable & & Variable ! = UpdatingInDeletedTransition & & Variable - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
2008-03-19 08:09:03 +01:00
//
2015-07-01 05:08:29 +02:00
// Buffer has cached all ADDED variable.
2008-03-19 08:09:03 +01:00
// Per IN_DELETED variable, we have to guarantee that
2015-07-01 05:08:29 +02:00
// no ADDED one in previous buffer.
//
2008-03-19 08:09:03 +01:00
FoundAdded = FALSE ;
AddedVariable = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ValidBuffer ) ;
2014-10-31 11:26:54 +01:00
while ( IsValidVariableHeader ( AddedVariable , GetEndPointer ( ( VARIABLE_STORE_HEADER * ) ValidBuffer ) ) ) {
2008-03-19 08:09:03 +01:00
NextAddedVariable = GetNextVariablePtr ( AddedVariable ) ;
NameSize = NameSizeOfVariable ( AddedVariable ) ;
2015-07-01 05:08:29 +02:00
if ( CompareGuid ( GetVendorGuidPtr ( AddedVariable ) , GetVendorGuidPtr ( Variable ) ) & &
2008-03-19 08:09:03 +01:00
NameSize = = NameSizeOfVariable ( Variable )
) {
Point0 = ( VOID * ) GetVariableNamePtr ( AddedVariable ) ;
Point1 = ( VOID * ) GetVariableNamePtr ( Variable ) ;
2013-01-18 02:12:32 +01:00
if ( CompareMem ( Point0 , Point1 , NameSize ) = = 0 ) {
2008-03-19 08:09:03 +01:00
FoundAdded = TRUE ;
break ;
}
}
AddedVariable = NextAddedVariable ;
}
if ( ! FoundAdded ) {
2008-10-12 01:44:40 +02:00
//
2010-12-10 10:27:54 +01:00
// Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
2008-10-12 01:44:40 +02:00
//
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 ) ) {
2012-08-06 05:20:10 +02:00
HwErrVariableTotalSize + = VariableSize ;
2009-04-07 08:42:12 +02:00
} else if ( ( ! IsVolatile ) & & ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
2012-08-06 05:20:10 +02:00
CommonVariableTotalSize + = VariableSize ;
2015-01-27 09:42:47 +01:00
if ( IsUserVariable ( Variable ) ) {
CommonUserVariableTotalSize + = VariableSize ;
}
2009-04-07 08:42:12 +02:00
}
2008-03-19 08:09:03 +01:00
}
}
Variable = NextVariable ;
}
2007-07-19 12:09:07 +02:00
2013-11-04 04:13:54 +01:00
//
// Install the new variable if it is not NULL.
//
if ( NewVariable ! = NULL ) {
if ( ( UINTN ) ( CurrPtr - ValidBuffer ) + NewVariableSize > VariableStoreHeader - > Size ) {
//
// No enough space to store the new variable.
//
Status = EFI_OUT_OF_RESOURCES ;
goto Done ;
}
if ( ! IsVolatile ) {
if ( ( NewVariable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
HwErrVariableTotalSize + = NewVariableSize ;
} else if ( ( NewVariable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
CommonVariableTotalSize + = NewVariableSize ;
2015-01-27 09:42:47 +01:00
if ( IsUserVariable ( NewVariable ) ) {
CommonUserVariableTotalSize + = NewVariableSize ;
}
2013-11-04 04:13:54 +01:00
}
if ( ( HwErrVariableTotalSize > PcdGet32 ( PcdHwErrStorageSize ) ) | |
2015-01-27 09:42:47 +01:00
( CommonVariableTotalSize > mVariableModuleGlobal - > CommonVariableSpace ) | |
( CommonUserVariableTotalSize > mVariableModuleGlobal - > CommonMaxUserVariableSpace ) ) {
2013-11-04 04:13:54 +01:00
//
// No enough space to store the new variable by NV or NV+HR attribute.
//
Status = EFI_OUT_OF_RESOURCES ;
goto Done ;
}
}
CopyMem ( CurrPtr , ( UINT8 * ) NewVariable , NewVariableSize ) ;
( ( VARIABLE_HEADER * ) CurrPtr ) - > State = VAR_ADDED ;
if ( UpdatingVariable ! = NULL ) {
UpdatingPtrTrack - > CurrPtr = ( VARIABLE_HEADER * ) ( ( UINTN ) UpdatingPtrTrack - > StartPtr + ( ( UINTN ) CurrPtr - ( UINTN ) GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ValidBuffer ) ) ) ;
UpdatingPtrTrack - > InDeletedTransitionPtr = NULL ;
}
CurrPtr + = NewVariableSize ;
}
2007-07-19 12:09:07 +02:00
if ( IsVolatile ) {
//
2010-12-10 10:27:54 +01:00
// If volatile variable store, just copy valid buffer.
2007-07-19 12:09:07 +02:00
//
SetMem ( ( UINT8 * ) ( UINTN ) VariableBase , VariableStoreHeader - > Size , 0xff ) ;
2013-11-04 04:13:54 +01:00
CopyMem ( ( UINT8 * ) ( UINTN ) VariableBase , ValidBuffer , ( UINTN ) ( CurrPtr - ValidBuffer ) ) ;
2013-11-12 14:31:43 +01:00
* LastVariableOffset = ( UINTN ) ( CurrPtr - ValidBuffer ) ;
2010-12-10 10:27:54 +01:00
Status = EFI_SUCCESS ;
2007-07-19 12:09:07 +02:00
} else {
//
// If non-volatile variable store, perform FTW here.
//
Status = FtwVariableSpace (
VariableBase ,
2013-11-12 14:31:43 +01:00
( VARIABLE_STORE_HEADER * ) ValidBuffer
2007-07-19 12:09:07 +02:00
) ;
2013-11-12 14:31:43 +01:00
if ( ! EFI_ERROR ( Status ) ) {
* LastVariableOffset = ( UINTN ) ( CurrPtr - ValidBuffer ) ;
2012-08-06 05:20:10 +02:00
mVariableModuleGlobal - > HwErrVariableTotalSize = HwErrVariableTotalSize ;
mVariableModuleGlobal - > CommonVariableTotalSize = CommonVariableTotalSize ;
2015-01-27 09:42:47 +01:00
mVariableModuleGlobal - > CommonUserVariableTotalSize = CommonUserVariableTotalSize ;
2013-11-12 14:31:43 +01:00
} else {
2015-12-29 10:00:58 +01:00
mVariableModuleGlobal - > HwErrVariableTotalSize = 0 ;
mVariableModuleGlobal - > CommonVariableTotalSize = 0 ;
mVariableModuleGlobal - > CommonUserVariableTotalSize = 0 ;
2015-01-27 09:42:47 +01:00
Variable = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) VariableBase ) ;
while ( IsValidVariableHeader ( Variable , GetEndPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) VariableBase ) ) ) {
NextVariable = GetNextVariablePtr ( Variable ) ;
VariableSize = ( UINTN ) NextVariable - ( UINTN ) Variable ;
2013-11-12 14:31:43 +01:00
if ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
2015-01-27 09:42:47 +01:00
mVariableModuleGlobal - > HwErrVariableTotalSize + = VariableSize ;
2013-11-12 14:31:43 +01:00
} else if ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
2015-01-27 09:42:47 +01:00
mVariableModuleGlobal - > CommonVariableTotalSize + = VariableSize ;
if ( IsUserVariable ( Variable ) ) {
mVariableModuleGlobal - > CommonUserVariableTotalSize + = VariableSize ;
}
2013-11-12 14:31:43 +01:00
}
2012-08-06 05:20:10 +02:00
2015-01-27 09:42:47 +01:00
Variable = NextVariable ;
2013-11-12 14:31:43 +01:00
}
2015-01-27 09:42:47 +01:00
* LastVariableOffset = ( UINTN ) Variable - ( UINTN ) VariableBase ;
2012-08-06 05:20:10 +02:00
}
2007-07-19 12:09:07 +02:00
}
2013-11-04 04:13:54 +01:00
Done :
2013-11-12 14:31:43 +01:00
if ( IsVolatile ) {
FreePool ( ValidBuffer ) ;
} else {
//
// For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back.
//
CopyMem ( mNvVariableCache , ( UINT8 * ) ( UINTN ) VariableBase , VariableStoreHeader - > Size ) ;
}
2008-03-19 08:09:03 +01:00
2007-07-19 12:09:07 +02:00
return Status ;
}
2011-10-14 07:19:39 +02:00
/**
Find the variable in the specified variable store .
2015-07-01 05:08:29 +02:00
@ param [ in ] VariableName Name of the variable to be found
@ param [ in ] VendorGuid Vendor GUID to be found .
@ param [ in ] IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
check at runtime when searching variable .
@ param [ in , out ] PtrTrack Variable Track Pointer structure that contains Variable Information .
2011-10-14 07:19:39 +02:00
2015-07-01 05:08:29 +02:00
@ retval EFI_SUCCESS Variable found successfully
@ retval EFI_NOT_FOUND Variable not found
2011-10-14 07:19:39 +02:00
* */
EFI_STATUS
FindVariableEx (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
2012-03-30 09:19:44 +02:00
IN BOOLEAN IgnoreRtCheck ,
2011-10-14 07:19:39 +02:00
IN OUT VARIABLE_POINTER_TRACK * PtrTrack
)
{
VARIABLE_HEADER * InDeletedVariable ;
VOID * Point ;
2013-01-18 02:12:32 +01:00
PtrTrack - > InDeletedTransitionPtr = NULL ;
2011-10-14 07:19:39 +02:00
//
// Find the variable by walk through HOB, volatile and non-volatile variable store.
//
InDeletedVariable = NULL ;
for ( PtrTrack - > CurrPtr = PtrTrack - > StartPtr
2014-10-31 11:26:54 +01:00
; IsValidVariableHeader ( PtrTrack - > CurrPtr , PtrTrack - > EndPtr )
2011-10-14 07:19:39 +02:00
; PtrTrack - > CurrPtr = GetNextVariablePtr ( PtrTrack - > CurrPtr )
) {
2015-07-01 05:08:29 +02:00
if ( PtrTrack - > CurrPtr - > State = = VAR_ADDED | |
2011-10-14 07:19:39 +02:00
PtrTrack - > CurrPtr - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED )
) {
2012-03-30 09:19:44 +02:00
if ( IgnoreRtCheck | | ! AtRuntime ( ) | | ( ( PtrTrack - > CurrPtr - > Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) ! = 0 ) ) {
2011-10-14 07:19:39 +02:00
if ( VariableName [ 0 ] = = 0 ) {
if ( PtrTrack - > CurrPtr - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
InDeletedVariable = PtrTrack - > CurrPtr ;
} else {
2013-01-18 02:12:32 +01:00
PtrTrack - > InDeletedTransitionPtr = InDeletedVariable ;
2011-10-14 07:19:39 +02:00
return EFI_SUCCESS ;
}
} else {
2015-07-01 05:08:29 +02:00
if ( CompareGuid ( VendorGuid , GetVendorGuidPtr ( PtrTrack - > CurrPtr ) ) ) {
2011-10-14 07:19:39 +02:00
Point = ( VOID * ) GetVariableNamePtr ( PtrTrack - > CurrPtr ) ;
ASSERT ( NameSizeOfVariable ( PtrTrack - > CurrPtr ) ! = 0 ) ;
if ( CompareMem ( VariableName , Point , NameSizeOfVariable ( PtrTrack - > CurrPtr ) ) = = 0 ) {
if ( PtrTrack - > CurrPtr - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
InDeletedVariable = PtrTrack - > CurrPtr ;
} else {
2013-01-18 02:12:32 +01:00
PtrTrack - > InDeletedTransitionPtr = InDeletedVariable ;
2011-10-14 07:19:39 +02:00
return EFI_SUCCESS ;
}
}
}
}
}
}
}
PtrTrack - > CurrPtr = InDeletedVariable ;
return ( PtrTrack - > CurrPtr = = NULL ) ? EFI_NOT_FOUND : EFI_SUCCESS ;
}
2007-10-04 23:01:21 +02:00
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 .
2012-03-30 09:19:44 +02:00
If IgnoreRtCheck is TRUE , then we ignore the EFI_VARIABLE_RUNTIME_ACCESS attribute check
at runtime when searching existing variable , only VariableName and VendorGuid are compared .
Otherwise , variables without EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime .
2008-12-12 10:27:17 +01:00
2015-07-01 05:08:29 +02:00
@ param [ in ] VariableName Name of the variable to be found .
@ param [ in ] VendorGuid Vendor GUID to be found .
@ param [ out ] PtrTrack VARIABLE_POINTER_TRACK structure for output ,
2008-12-12 10:27:17 +01:00
including the range searched and the target position .
2015-07-01 05:08:29 +02:00
@ param [ in ] Global Pointer to VARIABLE_GLOBAL structure , including
2008-12-12 10:27:17 +01:00
base of volatile variable storage area , base of
NV variable storage area , and a lock .
2015-07-01 05:08:29 +02:00
@ param [ in ] IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
2012-03-30 09:19:44 +02:00
check at runtime when searching variable .
2008-12-12 10:27:17 +01:00
@ retval EFI_INVALID_PARAMETER If VariableName is not an empty string , while
2010-12-10 10:27:54 +01:00
VendorGuid is NULL .
@ retval EFI_SUCCESS Variable successfully found .
2010-11-18 02:40:22 +01:00
@ retval EFI_NOT_FOUND 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 ,
2012-03-30 09:19:44 +02:00
IN VARIABLE_GLOBAL * Global ,
IN BOOLEAN IgnoreRtCheck
2007-07-19 12:09:07 +02:00
)
{
2011-10-14 07:19:39 +02:00
EFI_STATUS Status ;
VARIABLE_STORE_HEADER * VariableStoreHeader [ VariableStoreTypeMax ] ;
VARIABLE_STORE_TYPE Type ;
if ( VariableName [ 0 ] ! = 0 & & VendorGuid = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
2007-07-19 12:09:07 +02:00
//
2011-10-14 07:19:39 +02:00
// 0: Volatile, 1: HOB, 2: Non-Volatile.
2007-10-09 07:42:37 +02:00
// The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
2010-12-10 10:27:54 +01:00
// make use of this mapping to implement search algorithm.
2007-07-19 12:09:07 +02:00
//
2011-10-14 07:19:39 +02:00
VariableStoreHeader [ VariableStoreTypeVolatile ] = ( VARIABLE_STORE_HEADER * ) ( UINTN ) Global - > VolatileVariableBase ;
VariableStoreHeader [ VariableStoreTypeHob ] = ( VARIABLE_STORE_HEADER * ) ( UINTN ) Global - > HobVariableBase ;
VariableStoreHeader [ VariableStoreTypeNv ] = mNvVariableCache ;
2007-07-19 12:09:07 +02:00
//
2011-10-14 07:19:39 +02:00
// Find the variable by walk through HOB, volatile and non-volatile variable store.
2007-07-19 12:09:07 +02:00
//
2011-10-14 07:19:39 +02:00
for ( Type = ( VARIABLE_STORE_TYPE ) 0 ; Type < VariableStoreTypeMax ; Type + + ) {
if ( VariableStoreHeader [ Type ] = = NULL ) {
continue ;
}
2008-03-19 08:09:03 +01:00
2011-10-14 07:19:39 +02:00
PtrTrack - > StartPtr = GetStartPointer ( VariableStoreHeader [ Type ] ) ;
PtrTrack - > EndPtr = GetEndPointer ( VariableStoreHeader [ Type ] ) ;
PtrTrack - > Volatile = ( BOOLEAN ) ( Type = = VariableStoreTypeVolatile ) ;
2007-07-19 12:09:07 +02:00
2012-03-30 09:19:44 +02:00
Status = FindVariableEx ( VariableName , VendorGuid , IgnoreRtCheck , PtrTrack ) ;
2011-10-14 07:19:39 +02:00
if ( ! EFI_ERROR ( Status ) ) {
return Status ;
2008-03-19 08:09:03 +01:00
}
2007-07-19 12:09:07 +02:00
}
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
2010-12-10 10:27:54 +01: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
GetIndexFromSupportedLangCodes (
IN CHAR8 * SupportedLang ,
IN CHAR8 * Lang ,
IN BOOLEAN Iso639Language
2015-07-01 05:08:29 +02:00
)
2007-07-19 12:09:07 +02:00
{
2009-04-27 09:06:01 +02:00
UINTN Index ;
2010-11-18 02:40:22 +01:00
UINTN CompareLength ;
UINTN LanguageLength ;
2009-04-27 09:06:01 +02:00
if ( Iso639Language ) {
2010-11-18 02:40:22 +01:00
CompareLength = ISO_639_2_ENTRY_SIZE ;
2009-04-27 09:06:01 +02:00
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
//
2010-11-18 02:40:22 +01:00
Index = 0 ;
for ( LanguageLength = 0 ; Lang [ LanguageLength ] ! = ' \0 ' ; LanguageLength + + ) ;
for ( Index = 0 ; * SupportedLang ! = ' \0 ' ; Index + + , SupportedLang + = CompareLength ) {
2009-04-27 09:06:01 +02:00
//
2010-11-18 02:40:22 +01:00
// Skip ';' characters in SupportedLang
2009-04-27 09:06:01 +02:00
//
2010-11-18 02:40:22 +01:00
for ( ; * SupportedLang ! = ' \0 ' & & * SupportedLang = = ' ; ' ; SupportedLang + + ) ;
//
// Determine the length of the next language code in SupportedLang
//
for ( CompareLength = 0 ; SupportedLang [ CompareLength ] ! = ' \0 ' & & SupportedLang [ CompareLength ] ! = ' ; ' ; CompareLength + + ) ;
2015-07-01 05:08:29 +02:00
if ( ( CompareLength = = LanguageLength ) & &
2010-11-18 02:40:22 +01:00
( AsciiStrnCmp ( Lang , SupportedLang , CompareLength ) = = 0 ) ) {
2009-04-27 09:06:01 +02:00
//
// Successfully find the index of Lang string in SupportedLang string.
//
return 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 .
2010-12-10 10:27:54 +01:00
This code is used to get corresponding language strings 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 .
2010-12-10 10:27:54 +01:00
@ 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
2010-12-10 10:27:54 +01: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 *
GetLangFromSupportedLangCodes (
IN CHAR8 * SupportedLang ,
IN UINTN Index ,
IN BOOLEAN Iso639Language
)
{
UINTN SubIndex ;
2010-11-18 02:40:22 +01:00
UINTN CompareLength ;
2009-04-27 09:06:01 +02:00
CHAR8 * Supported ;
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
SubIndex = 0 ;
Supported = SupportedLang ;
if ( Iso639Language ) {
//
2010-12-10 10:27:54 +01:00
// According to the index of Lang string in SupportedLang string to get the language.
// This code will be invoked in RUNTIME, therefore there is not a memory allocate/free operation.
2009-04-27 09:06:01 +02:00
// In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
//
2010-11-18 02:40:22 +01:00
CompareLength = ISO_639_2_ENTRY_SIZE ;
mVariableModuleGlobal - > Lang [ CompareLength ] = ' \0 ' ;
2009-04-27 09:06:01 +02:00
return CopyMem ( mVariableModuleGlobal - > Lang , SupportedLang + Index * CompareLength , CompareLength ) ;
2011-10-19 11:30:43 +02:00
2007-07-19 12:09:07 +02:00
} else {
2009-04-27 09:06:01 +02:00
while ( TRUE ) {
//
2010-12-10 10:27:54 +01:00
// Take semicolon as delimitation, sequentially traverse supported language codes.
2009-04-27 09:06:01 +02:00
//
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 ) {
//
2010-12-10 10:27:54 +01:00
// According to the index of Lang string in SupportedLang string to get the language.
2009-04-27 09:06:01 +02:00
// 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.
//
2010-11-18 02:40:22 +01:00
mVariableModuleGlobal - > PlatformLang [ CompareLength ] = ' \0 ' ;
2009-04-27 09:06:01 +02:00
return CopyMem ( mVariableModuleGlobal - > PlatformLang , Supported - CompareLength , CompareLength ) ;
}
SubIndex + + ;
2010-12-10 10:27:54 +01:00
2010-11-25 08:04:04 +01:00
//
// Skip ';' characters in Supported
//
for ( ; * Supported ! = ' \0 ' & & * Supported = = ' ; ' ; Supported + + ) ;
2009-04-27 09:06:01 +02:00
}
2007-07-19 12:09:07 +02:00
}
}
2010-11-18 02:40:22 +01:00
/**
2015-07-01 05:08:29 +02:00
Returns a pointer to an allocated buffer that contains the best matching language
from a set of supported languages .
This function supports both ISO 639 - 2 and RFC 4646 language codes , but language
2010-11-18 02:40:22 +01:00
code types may not be mixed in a single call to this function . This function
supports a variable argument list that allows the caller to pass in a prioritized
list of language codes to test against all the language codes in SupportedLanguages .
If SupportedLanguages is NULL , then ASSERT ( ) .
@ param [ in ] SupportedLanguages A pointer to a Null - terminated ASCII string that
2015-07-01 05:08:29 +02:00
contains a set of language codes in the format
2010-11-18 02:40:22 +01:00
specified by Iso639Language .
@ param [ in ] Iso639Language If TRUE , then all language codes are assumed to be
in ISO 639 - 2 format . If FALSE , then all language
codes are assumed to be in RFC 4646 language format
2015-07-01 05:08:29 +02:00
@ param [ in ] . . . A variable argument list that contains pointers to
2010-11-18 02:40:22 +01:00
Null - terminated ASCII strings that contain one or more
language codes in the format specified by Iso639Language .
The first language code from each of these language
code lists is used to determine if it is an exact or
2015-07-01 05:08:29 +02:00
close match to any of the language codes in
2010-11-18 02:40:22 +01:00
SupportedLanguages . Close matches only apply to RFC 4646
language codes , and the matching algorithm from RFC 4647
2015-07-01 05:08:29 +02:00
is used to determine if a close match is present . If
2010-11-18 02:40:22 +01:00
an exact or close match is found , then the matching
language code from SupportedLanguages is returned . If
no matches are found , then the next variable argument
2015-07-01 05:08:29 +02:00
parameter is evaluated . The variable argument list
2010-11-18 02:40:22 +01:00
is terminated by a NULL .
@ retval NULL The best matching language could not be found in SupportedLanguages .
2015-07-01 05:08:29 +02:00
@ retval NULL There are not enough resources available to return the best matching
2010-11-18 02:40:22 +01:00
language .
2015-07-01 05:08:29 +02:00
@ retval Other A pointer to a Null - terminated ASCII string that is the best matching
2010-11-18 02:40:22 +01:00
language in SupportedLanguages .
* */
CHAR8 *
2010-12-06 07:04:38 +01:00
EFIAPI
2010-11-18 02:40:22 +01:00
VariableGetBestLanguage (
2015-07-01 05:08:29 +02:00
IN CONST CHAR8 * SupportedLanguages ,
2010-11-18 02:40:22 +01:00
IN BOOLEAN Iso639Language ,
. . .
)
{
VA_LIST Args ;
CHAR8 * Language ;
UINTN CompareLength ;
UINTN LanguageLength ;
CONST CHAR8 * Supported ;
CHAR8 * Buffer ;
2015-07-01 05:08:29 +02:00
if ( SupportedLanguages = = NULL ) {
return NULL ;
}
2010-11-18 02:40:22 +01:00
VA_START ( Args , Iso639Language ) ;
while ( ( Language = VA_ARG ( Args , CHAR8 * ) ) ! = NULL ) {
//
// Default to ISO 639-2 mode
//
CompareLength = 3 ;
LanguageLength = MIN ( 3 , AsciiStrLen ( Language ) ) ;
//
// If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language
//
if ( ! Iso639Language ) {
for ( LanguageLength = 0 ; Language [ LanguageLength ] ! = 0 & & Language [ LanguageLength ] ! = ' ; ' ; LanguageLength + + ) ;
}
//
// Trim back the length of Language used until it is empty
//
while ( LanguageLength > 0 ) {
//
// Loop through all language codes in SupportedLanguages
//
for ( Supported = SupportedLanguages ; * Supported ! = ' \0 ' ; Supported + = CompareLength ) {
//
// In RFC 4646 mode, then Loop through all language codes in SupportedLanguages
//
if ( ! Iso639Language ) {
//
// Skip ';' characters in Supported
//
for ( ; * Supported ! = ' \0 ' & & * Supported = = ' ; ' ; Supported + + ) ;
//
// Determine the length of the next language code in Supported
//
for ( CompareLength = 0 ; Supported [ CompareLength ] ! = 0 & & Supported [ CompareLength ] ! = ' ; ' ; CompareLength + + ) ;
//
// If Language is longer than the Supported, then skip to the next language
//
if ( LanguageLength > CompareLength ) {
continue ;
}
}
//
// See if the first LanguageLength characters in Supported match Language
//
if ( AsciiStrnCmp ( Supported , Language , LanguageLength ) = = 0 ) {
VA_END ( Args ) ;
Buffer = Iso639Language ? mVariableModuleGlobal - > Lang : mVariableModuleGlobal - > PlatformLang ;
Buffer [ CompareLength ] = ' \0 ' ;
return CopyMem ( Buffer , Supported , CompareLength ) ;
}
}
if ( Iso639Language ) {
//
// If ISO 639 mode, then each language can only be tested once
//
LanguageLength = 0 ;
} else {
//
2015-07-01 05:08:29 +02:00
// If RFC 4646 mode, then trim Language from the right to the next '-' character
2010-11-18 02:40:22 +01:00
//
for ( LanguageLength - - ; LanguageLength > 0 & & Language [ LanguageLength ] ! = ' - ' ; LanguageLength - - ) ;
}
}
}
VA_END ( Args ) ;
//
2015-07-01 05:08:29 +02:00
// No matches were found
2010-11-18 02:40:22 +01:00
//
return NULL ;
}
2014-03-25 07:56:55 +01:00
/**
This function is to check if the remaining variable space is enough to set
all Variables from argument list successfully . The purpose of the check
is to keep the consistency of the Variables to be in variable storage .
Note : Variables are assumed to be in same storage .
The set sequence of Variables will be same with the sequence of VariableEntry from argument list ,
so follow the argument sequence to check the Variables .
@ param [ in ] Attributes Variable attributes for Variable entries .
2015-07-01 05:08:29 +02:00
@ param [ in ] Marker VA_LIST style variable argument list .
The variable argument list with type VARIABLE_ENTRY_CONSISTENCY * .
A NULL terminates the list . The VariableSize of
2014-03-27 11:54:23 +01:00
VARIABLE_ENTRY_CONSISTENCY is the variable data size as input .
It will be changed to variable total size as output .
2014-03-25 07:56:55 +01:00
@ retval TRUE Have enough variable space to set the Variables successfully .
@ retval FALSE No enough variable space to set the Variables successfully .
* */
BOOLEAN
EFIAPI
2015-07-01 05:08:29 +02:00
CheckRemainingSpaceForConsistencyInternal (
2014-03-25 07:56:55 +01:00
IN UINT32 Attributes ,
2015-07-01 05:08:29 +02:00
IN VA_LIST Marker
2014-03-25 07:56:55 +01:00
)
{
EFI_STATUS Status ;
VA_LIST Args ;
VARIABLE_ENTRY_CONSISTENCY * VariableEntry ;
UINT64 MaximumVariableStorageSize ;
UINT64 RemainingVariableStorageSize ;
UINT64 MaximumVariableSize ;
UINTN TotalNeededSize ;
UINTN OriginalVarSize ;
VARIABLE_STORE_HEADER * VariableStoreHeader ;
VARIABLE_POINTER_TRACK VariablePtrTrack ;
VARIABLE_HEADER * NextVariable ;
2014-03-27 11:54:23 +01:00
UINTN VarNameSize ;
UINTN VarDataSize ;
2014-03-25 07:56:55 +01:00
//
// Non-Volatile related.
//
VariableStoreHeader = mNvVariableCache ;
Status = VariableServiceQueryVariableInfoInternal (
Attributes ,
& MaximumVariableStorageSize ,
& RemainingVariableStorageSize ,
& MaximumVariableSize
) ;
ASSERT_EFI_ERROR ( Status ) ;
TotalNeededSize = 0 ;
2015-12-18 11:11:25 +01:00
VA_COPY ( Args , Marker ) ;
2014-03-25 07:56:55 +01:00
VariableEntry = VA_ARG ( Args , VARIABLE_ENTRY_CONSISTENCY * ) ;
while ( VariableEntry ! = NULL ) {
2014-03-27 11:54:23 +01:00
//
// Calculate variable total size.
//
VarNameSize = StrSize ( VariableEntry - > Name ) ;
VarNameSize + = GET_PAD_SIZE ( VarNameSize ) ;
VarDataSize = VariableEntry - > VariableSize ;
VarDataSize + = GET_PAD_SIZE ( VarDataSize ) ;
2015-07-01 05:08:29 +02:00
VariableEntry - > VariableSize = HEADER_ALIGN ( GetVariableHeaderSize ( ) + VarNameSize + VarDataSize ) ;
2014-03-27 11:54:23 +01:00
2014-03-25 07:56:55 +01:00
TotalNeededSize + = VariableEntry - > VariableSize ;
VariableEntry = VA_ARG ( Args , VARIABLE_ENTRY_CONSISTENCY * ) ;
}
2016-05-16 17:49:12 +02:00
VA_END ( Args ) ;
2014-03-25 07:56:55 +01:00
if ( RemainingVariableStorageSize > = TotalNeededSize ) {
//
// Already have enough space.
//
return TRUE ;
} else if ( AtRuntime ( ) ) {
//
// At runtime, no reclaim.
// The original variable space of Variables can't be reused.
//
return FALSE ;
}
2015-12-18 11:11:25 +01:00
VA_COPY ( Args , Marker ) ;
2014-03-25 07:56:55 +01:00
VariableEntry = VA_ARG ( Args , VARIABLE_ENTRY_CONSISTENCY * ) ;
while ( VariableEntry ! = NULL ) {
//
// Check if Variable[Index] has been present and get its size.
//
OriginalVarSize = 0 ;
VariablePtrTrack . StartPtr = GetStartPointer ( VariableStoreHeader ) ;
VariablePtrTrack . EndPtr = GetEndPointer ( VariableStoreHeader ) ;
Status = FindVariableEx (
VariableEntry - > Name ,
VariableEntry - > Guid ,
FALSE ,
& VariablePtrTrack
) ;
if ( ! EFI_ERROR ( Status ) ) {
//
// Get size of Variable[Index].
//
NextVariable = GetNextVariablePtr ( VariablePtrTrack . CurrPtr ) ;
OriginalVarSize = ( UINTN ) NextVariable - ( UINTN ) VariablePtrTrack . CurrPtr ;
//
// Add the original size of Variable[Index] to remaining variable storage size.
//
RemainingVariableStorageSize + = OriginalVarSize ;
}
if ( VariableEntry - > VariableSize > RemainingVariableStorageSize ) {
//
// No enough space for Variable[Index].
//
return FALSE ;
}
//
// Sub the (new) size of Variable[Index] from remaining variable storage size.
//
RemainingVariableStorageSize - = VariableEntry - > VariableSize ;
VariableEntry = VA_ARG ( Args , VARIABLE_ENTRY_CONSISTENCY * ) ;
}
2016-05-16 17:49:12 +02:00
VA_END ( Args ) ;
2014-03-25 07:56:55 +01:00
return TRUE ;
}
2015-07-01 05:08:29 +02:00
/**
This function is to check if the remaining variable space is enough to set
all Variables from argument list successfully . The purpose of the check
is to keep the consistency of the Variables to be in variable storage .
Note : Variables are assumed to be in same storage .
The set sequence of Variables will be same with the sequence of VariableEntry from argument list ,
so follow the argument sequence to check the Variables .
@ param [ in ] Attributes Variable attributes for Variable entries .
@ param . . . The variable argument list with type VARIABLE_ENTRY_CONSISTENCY * .
A NULL terminates the list . The VariableSize of
VARIABLE_ENTRY_CONSISTENCY is the variable data size as input .
It will be changed to variable total size as output .
@ retval TRUE Have enough variable space to set the Variables successfully .
@ retval FALSE No enough variable space to set the Variables successfully .
* */
BOOLEAN
EFIAPI
CheckRemainingSpaceForConsistency (
IN UINT32 Attributes ,
. . .
)
{
VA_LIST Marker ;
BOOLEAN Return ;
VA_START ( Marker , Attributes ) ;
Return = CheckRemainingSpaceForConsistencyInternal ( Attributes , Marker ) ;
VA_END ( Marker ) ;
return Return ;
}
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
2010-12-10 10:27:54 +01:00
@ param [ in ] VariableName Name of variable .
2007-07-19 12:09:07 +02:00
2010-12-10 10:27:54 +01:00
@ param [ in ] Data Variable data .
2007-07-19 12:09:07 +02:00
2010-12-10 10:27:54 +01:00
@ param [ in ] DataSize Size of data . 0 means delete .
2009-04-27 09:06:01 +02:00
2014-03-20 03:07:48 +01:00
@ retval EFI_SUCCESS The update operation is successful or ignored .
@ retval EFI_WRITE_PROTECTED Update PlatformLangCodes / LangCodes at runtime .
@ retval EFI_OUT_OF_RESOURCES No enough variable space to do the update operation .
@ retval Others Other errors happened during the update operation .
2008-12-12 10:27:17 +01:00
* */
2014-03-20 03:07:48 +01:00
EFI_STATUS
2011-12-12 20:00:59 +01:00
AutoUpdateLangVariable (
2009-04-27 09:06:01 +02:00
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
{
2010-11-18 02:40:22 +01:00
EFI_STATUS Status ;
CHAR8 * BestPlatformLang ;
CHAR8 * BestLang ;
UINTN Index ;
UINT32 Attributes ;
2009-04-27 09:06:01 +02:00
VARIABLE_POINTER_TRACK Variable ;
2010-11-18 02:40:22 +01:00
BOOLEAN SetLanguageCodes ;
2014-03-25 07:56:55 +01:00
VARIABLE_ENTRY_CONSISTENCY VariableEntry [ 2 ] ;
2007-07-19 12:09:07 +02:00
2009-04-27 09:06:01 +02:00
//
2010-11-18 02:40:22 +01:00
// Don't do updates for delete operation
2009-04-27 09:06:01 +02:00
//
2010-11-18 02:40:22 +01:00
if ( DataSize = = 0 ) {
2014-03-20 03:07:48 +01:00
return EFI_SUCCESS ;
2010-11-18 02:40:22 +01:00
}
SetLanguageCodes = FALSE ;
2007-07-19 12:09:07 +02:00
2013-08-19 07:16:45 +02:00
if ( StrCmp ( VariableName , EFI_PLATFORM_LANG_CODES_VARIABLE_NAME ) = = 0 ) {
2010-11-18 02:40:22 +01:00
//
// PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
//
2010-12-10 10:27:54 +01:00
if ( AtRuntime ( ) ) {
2014-03-20 03:07:48 +01:00
return EFI_WRITE_PROTECTED ;
2010-11-18 02:40:22 +01:00
}
SetLanguageCodes = TRUE ;
2009-04-27 09:06:01 +02:00
//
// 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.
//
2010-11-18 02:40:22 +01:00
if ( mVariableModuleGlobal - > PlatformLangCodes ! = NULL ) {
FreePool ( mVariableModuleGlobal - > PlatformLangCodes ) ;
}
mVariableModuleGlobal - > PlatformLangCodes = AllocateRuntimeCopyPool ( DataSize , Data ) ;
ASSERT ( mVariableModuleGlobal - > PlatformLangCodes ! = NULL ) ;
2009-04-27 09:06:01 +02:00
//
2015-07-01 05:08:29 +02:00
// PlatformLang holds a single language from PlatformLangCodes,
2010-11-18 02:40:22 +01:00
// so the size of PlatformLangCodes is enough for the PlatformLang.
2009-04-27 09:06:01 +02:00
//
2010-11-18 02:40:22 +01:00
if ( mVariableModuleGlobal - > PlatformLang ! = NULL ) {
FreePool ( mVariableModuleGlobal - > PlatformLang ) ;
}
mVariableModuleGlobal - > PlatformLang = AllocateRuntimePool ( DataSize ) ;
ASSERT ( mVariableModuleGlobal - > PlatformLang ! = NULL ) ;
2008-01-09 11:10:16 +01:00
2013-08-19 07:16:45 +02:00
} else if ( StrCmp ( VariableName , EFI_LANG_CODES_VARIABLE_NAME ) = = 0 ) {
2009-04-27 09:06:01 +02:00
//
2010-11-18 02:40:22 +01:00
// LangCodes is a volatile variable, so it can not be updated at runtime.
2009-04-27 09:06:01 +02:00
//
2010-12-10 10:27:54 +01:00
if ( AtRuntime ( ) ) {
2014-03-20 03:07:48 +01:00
return EFI_WRITE_PROTECTED ;
2010-11-18 02:40:22 +01:00
}
SetLanguageCodes = TRUE ;
2007-07-19 12:09:07 +02:00
//
2010-11-18 02:40:22 +01:00
// 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.
2007-07-19 12:09:07 +02:00
//
2010-11-18 02:40:22 +01:00
if ( mVariableModuleGlobal - > LangCodes ! = NULL ) {
FreePool ( mVariableModuleGlobal - > LangCodes ) ;
}
mVariableModuleGlobal - > LangCodes = AllocateRuntimeCopyPool ( DataSize , Data ) ;
ASSERT ( mVariableModuleGlobal - > LangCodes ! = NULL ) ;
}
2007-07-19 12:09:07 +02:00
2015-07-01 05:08:29 +02:00
if ( SetLanguageCodes
2010-11-18 02:40:22 +01:00
& & ( mVariableModuleGlobal - > PlatformLangCodes ! = NULL )
& & ( mVariableModuleGlobal - > LangCodes ! = NULL ) ) {
2007-07-19 12:09:07 +02:00
//
2010-11-18 02:40:22 +01:00
// Update Lang if PlatformLang is already set
// Update PlatformLang if Lang is already set
2007-07-19 12:09:07 +02:00
//
2013-08-19 07:16:45 +02:00
Status = FindVariable ( EFI_PLATFORM_LANG_VARIABLE_NAME , & gEfiGlobalVariableGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal , FALSE ) ;
2010-11-18 02:40:22 +01:00
if ( ! EFI_ERROR ( Status ) ) {
//
// Update Lang
//
2013-08-19 07:16:45 +02:00
VariableName = EFI_PLATFORM_LANG_VARIABLE_NAME ;
2010-11-18 02:40:22 +01:00
Data = GetVariableDataPtr ( Variable . CurrPtr ) ;
2015-07-01 05:08:29 +02:00
DataSize = DataSizeOfVariable ( Variable . CurrPtr ) ;
2010-11-18 02:40:22 +01:00
} else {
2013-08-19 07:16:45 +02:00
Status = FindVariable ( EFI_LANG_VARIABLE_NAME , & gEfiGlobalVariableGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal , FALSE ) ;
2010-11-18 02:40:22 +01:00
if ( ! EFI_ERROR ( Status ) ) {
//
// Update PlatformLang
//
2013-08-19 07:16:45 +02:00
VariableName = EFI_LANG_VARIABLE_NAME ;
2010-11-18 02:40:22 +01:00
Data = GetVariableDataPtr ( Variable . CurrPtr ) ;
2015-07-01 05:08:29 +02:00
DataSize = DataSizeOfVariable ( Variable . CurrPtr ) ;
2010-11-18 02:40:22 +01:00
} else {
//
// Neither PlatformLang nor Lang is set, directly return
//
2014-03-20 03:07:48 +01:00
return EFI_SUCCESS ;
2010-11-18 02:40:22 +01:00
}
}
}
2014-03-20 03:07:48 +01:00
Status = EFI_SUCCESS ;
2010-11-18 02:40:22 +01: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
2013-08-19 07:16:45 +02:00
if ( StrCmp ( VariableName , EFI_PLATFORM_LANG_VARIABLE_NAME ) = = 0 ) {
2007-07-19 12:09:07 +02:00
//
2010-11-18 02:40:22 +01:00
// Update Lang when PlatformLangCodes/LangCodes were set.
2007-07-19 12:09:07 +02:00
//
2010-11-18 02:40:22 +01:00
if ( ( mVariableModuleGlobal - > PlatformLangCodes ! = NULL ) & & ( mVariableModuleGlobal - > LangCodes ! = NULL ) ) {
//
// When setting PlatformLang, firstly get most matched language string from supported language codes.
//
BestPlatformLang = VariableGetBestLanguage ( mVariableModuleGlobal - > PlatformLangCodes , FALSE , Data , NULL ) ;
if ( BestPlatformLang ! = NULL ) {
//
// Get the corresponding index in language codes.
//
Index = GetIndexFromSupportedLangCodes ( mVariableModuleGlobal - > PlatformLangCodes , BestPlatformLang , FALSE ) ;
2008-01-09 11:10:16 +01:00
2010-11-18 02:40:22 +01:00
//
// Get the corresponding ISO639 language tag according to RFC4646 language tag.
//
BestLang = GetLangFromSupportedLangCodes ( mVariableModuleGlobal - > LangCodes , Index , TRUE ) ;
2007-07-19 12:09:07 +02:00
2010-11-18 02:40:22 +01:00
//
2014-03-27 11:54:23 +01:00
// Check the variable space for both Lang and PlatformLang variable.
2014-03-25 07:56:55 +01:00
//
2014-03-27 11:54:23 +01:00
VariableEntry [ 0 ] . VariableSize = ISO_639_2_ENTRY_SIZE + 1 ;
2014-03-25 07:56:55 +01:00
VariableEntry [ 0 ] . Guid = & gEfiGlobalVariableGuid ;
VariableEntry [ 0 ] . Name = EFI_LANG_VARIABLE_NAME ;
2015-07-01 05:08:29 +02:00
2014-03-27 11:54:23 +01:00
VariableEntry [ 1 ] . VariableSize = AsciiStrSize ( BestPlatformLang ) ;
2014-03-25 07:56:55 +01:00
VariableEntry [ 1 ] . Guid = & gEfiGlobalVariableGuid ;
VariableEntry [ 1 ] . Name = EFI_PLATFORM_LANG_VARIABLE_NAME ;
if ( ! CheckRemainingSpaceForConsistency ( VARIABLE_ATTRIBUTE_NV_BS_RT , & VariableEntry [ 0 ] , & VariableEntry [ 1 ] , NULL ) ) {
//
// No enough variable space to set both Lang and PlatformLang successfully.
//
Status = EFI_OUT_OF_RESOURCES ;
} else {
//
// Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
//
FindVariable ( EFI_LANG_VARIABLE_NAME , & gEfiGlobalVariableGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal , FALSE ) ;
2007-07-19 12:09:07 +02:00
2014-03-25 07:56:55 +01:00
Status = UpdateVariable ( EFI_LANG_VARIABLE_NAME , & gEfiGlobalVariableGuid , BestLang ,
2015-07-01 05:08:29 +02:00
ISO_639_2_ENTRY_SIZE + 1 , Attributes , 0 , 0 , & Variable , NULL ) ;
2014-03-25 07:56:55 +01:00
}
2007-07-19 12:09:07 +02:00
2014-03-25 07:56:55 +01:00
DEBUG ( ( EFI_D_INFO , " Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a Status: %r \n " , BestPlatformLang , BestLang , Status ) ) ;
2010-11-18 02:40:22 +01:00
}
}
2009-04-27 09:06:01 +02:00
2013-08-19 07:16:45 +02:00
} else if ( StrCmp ( VariableName , EFI_LANG_VARIABLE_NAME ) = = 0 ) {
2009-04-27 09:06:01 +02:00
//
2010-11-18 02:40:22 +01:00
// Update PlatformLang when PlatformLangCodes/LangCodes were set.
2009-04-27 09:06:01 +02:00
//
2010-11-18 02:40:22 +01:00
if ( ( mVariableModuleGlobal - > PlatformLangCodes ! = NULL ) & & ( mVariableModuleGlobal - > LangCodes ! = NULL ) ) {
//
// When setting Lang, firstly get most matched language string from supported language codes.
//
BestLang = VariableGetBestLanguage ( mVariableModuleGlobal - > LangCodes , TRUE , Data , NULL ) ;
if ( BestLang ! = NULL ) {
//
// Get the corresponding index in language codes.
//
Index = GetIndexFromSupportedLangCodes ( mVariableModuleGlobal - > LangCodes , BestLang , TRUE ) ;
2009-04-27 09:06:01 +02:00
2010-11-18 02:40:22 +01:00
//
// Get the corresponding RFC4646 language tag according to ISO639 language tag.
//
BestPlatformLang = GetLangFromSupportedLangCodes ( mVariableModuleGlobal - > PlatformLangCodes , Index , FALSE ) ;
//
2014-03-27 11:54:23 +01:00
// Check the variable space for both PlatformLang and Lang variable.
2014-03-25 07:56:55 +01:00
//
2014-03-27 11:54:23 +01:00
VariableEntry [ 0 ] . VariableSize = AsciiStrSize ( BestPlatformLang ) ;
2014-03-25 07:56:55 +01:00
VariableEntry [ 0 ] . Guid = & gEfiGlobalVariableGuid ;
VariableEntry [ 0 ] . Name = EFI_PLATFORM_LANG_VARIABLE_NAME ;
2014-03-27 11:54:23 +01:00
VariableEntry [ 1 ] . VariableSize = ISO_639_2_ENTRY_SIZE + 1 ;
2014-03-25 07:56:55 +01:00
VariableEntry [ 1 ] . Guid = & gEfiGlobalVariableGuid ;
VariableEntry [ 1 ] . Name = EFI_LANG_VARIABLE_NAME ;
if ( ! CheckRemainingSpaceForConsistency ( VARIABLE_ATTRIBUTE_NV_BS_RT , & VariableEntry [ 0 ] , & VariableEntry [ 1 ] , NULL ) ) {
//
// No enough variable space to set both PlatformLang and Lang successfully.
//
Status = EFI_OUT_OF_RESOURCES ;
} else {
//
// Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
//
FindVariable ( EFI_PLATFORM_LANG_VARIABLE_NAME , & gEfiGlobalVariableGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal , FALSE ) ;
2009-04-27 09:06:01 +02:00
2015-07-01 05:08:29 +02:00
Status = UpdateVariable ( EFI_PLATFORM_LANG_VARIABLE_NAME , & gEfiGlobalVariableGuid , BestPlatformLang ,
AsciiStrSize ( BestPlatformLang ) , Attributes , 0 , 0 , & Variable , NULL ) ;
2014-03-25 07:56:55 +01:00
}
2009-04-27 09:06:01 +02:00
2014-03-20 03:07:48 +01:00
DEBUG ( ( EFI_D_INFO , " Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r \n " , BestLang , BestPlatformLang , Status ) ) ;
2010-11-18 02:40:22 +01:00
}
}
2009-04-27 09:06:01 +02:00
}
2014-03-20 03:07:48 +01:00
2014-03-25 07:56:55 +01:00
if ( SetLanguageCodes ) {
//
// Continue to set PlatformLangCodes or LangCodes.
//
return EFI_SUCCESS ;
} else {
return Status ;
}
2007-07-19 12:09:07 +02:00
}
2008-12-12 10:27:17 +01:00
/**
2015-07-01 05:08:29 +02:00
Compare two EFI_TIME data .
@ param FirstTime A pointer to the first EFI_TIME data .
@ param SecondTime A pointer to the second EFI_TIME data .
@ retval TRUE The FirstTime is not later than the SecondTime .
@ retval FALSE The FirstTime is later than the SecondTime .
* */
BOOLEAN
VariableCompareTimeStampInternal (
IN EFI_TIME * FirstTime ,
IN EFI_TIME * SecondTime
)
{
if ( FirstTime - > Year ! = SecondTime - > Year ) {
return ( BOOLEAN ) ( FirstTime - > Year < SecondTime - > Year ) ;
} else if ( FirstTime - > Month ! = SecondTime - > Month ) {
return ( BOOLEAN ) ( FirstTime - > Month < SecondTime - > Month ) ;
} else if ( FirstTime - > Day ! = SecondTime - > Day ) {
return ( BOOLEAN ) ( FirstTime - > Day < SecondTime - > Day ) ;
} else if ( FirstTime - > Hour ! = SecondTime - > Hour ) {
return ( BOOLEAN ) ( FirstTime - > Hour < SecondTime - > Hour ) ;
} else if ( FirstTime - > Minute ! = SecondTime - > Minute ) {
return ( BOOLEAN ) ( FirstTime - > Minute < SecondTime - > Minute ) ;
}
return ( BOOLEAN ) ( FirstTime - > Second < = SecondTime - > Second ) ;
}
/**
Update the variable region with Variable information . If EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set ,
index of associated public key is needed .
2007-10-05 16:40:23 +02:00
2010-12-10 10:27:54 +01:00
@ 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 .
2015-07-01 05:08:29 +02:00
@ param [ in ] Attributes Attributes of the variable .
@ param [ in ] KeyIndex Index of associated public key .
@ param [ in ] MonotonicCount Value of associated monotonic count .
2013-01-18 02:12:32 +01:00
@ param [ in , out ] CacheVariable The variable information which is used to keep track of variable usage .
2015-07-01 05:08:29 +02:00
@ param [ in ] TimeStamp Value of associated TimeStamp .
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 .
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
2009-04-27 09:06:01 +02:00
UpdateVariable (
2010-12-10 10:27:54 +01:00
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
IN VOID * Data ,
IN UINTN DataSize ,
IN UINT32 Attributes OPTIONAL ,
2015-07-01 05:08:29 +02:00
IN UINT32 KeyIndex OPTIONAL ,
IN UINT64 MonotonicCount OPTIONAL ,
IN OUT VARIABLE_POINTER_TRACK * CacheVariable ,
IN EFI_TIME * TimeStamp OPTIONAL
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 ;
2015-07-01 05:08:29 +02:00
UINTN MaxDataSize ;
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 ;
2010-12-10 10:27:54 +01:00
VARIABLE_POINTER_TRACK * Variable ;
VARIABLE_POINTER_TRACK NvVariable ;
VARIABLE_STORE_HEADER * VariableStoreHeader ;
UINTN CacheOffset ;
2015-07-01 05:08:29 +02:00
UINT8 * BufferForMerge ;
UINTN MergedBufSize ;
BOOLEAN DataReady ;
UINTN DataOffset ;
2015-01-27 09:42:47 +01:00
BOOLEAN IsCommonVariable ;
BOOLEAN IsCommonUserVariable ;
2015-07-01 05:08:29 +02:00
AUTHENTICATED_VARIABLE_HEADER * AuthVariable ;
2008-01-09 11:10:16 +01:00
2015-07-01 05:08:29 +02:00
if ( mVariableModuleGlobal - > FvbInstance = = NULL ) {
2010-12-22 08:33:13 +01:00
//
2015-07-01 05:08:29 +02:00
// The FVB protocol is not ready, so the EFI_VARIABLE_WRITE_ARCH_PROTOCOL is not installed.
2010-12-22 08:33:13 +01:00
//
2015-07-01 05:08:29 +02:00
if ( ( Attributes & EFI_VARIABLE_NON_VOLATILE ) ! = 0 ) {
//
// Trying to update NV variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL
//
DEBUG ( ( EFI_D_ERROR , " Update NV variable before EFI_VARIABLE_WRITE_ARCH_PROTOCOL ready - %r \n " , EFI_NOT_AVAILABLE_YET ) ) ;
return EFI_NOT_AVAILABLE_YET ;
} else if ( ( Attributes & VARIABLE_ATTRIBUTE_AT_AW ) ! = 0 ) {
//
// Trying to update volatile authenticated variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL
// The authenticated variable perhaps is not initialized, just return here.
//
DEBUG ( ( EFI_D_ERROR , " Update AUTH variable before EFI_VARIABLE_WRITE_ARCH_PROTOCOL ready - %r \n " , EFI_NOT_AVAILABLE_YET ) ) ;
return EFI_NOT_AVAILABLE_YET ;
}
2010-12-22 08:33:13 +01:00
}
2015-08-17 04:30:43 +02:00
//
// Check if CacheVariable points to the variable in variable HOB.
// If yes, let CacheVariable points to the variable in NV variable cache.
//
if ( ( CacheVariable - > CurrPtr ! = NULL ) & &
( mVariableModuleGlobal - > VariableGlobal . HobVariableBase ! = 0 ) & &
( CacheVariable - > StartPtr = = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) mVariableModuleGlobal - > VariableGlobal . HobVariableBase ) )
) {
CacheVariable - > StartPtr = GetStartPointer ( mNvVariableCache ) ;
CacheVariable - > EndPtr = GetEndPointer ( mNvVariableCache ) ;
CacheVariable - > Volatile = FALSE ;
Status = FindVariableEx ( VariableName , VendorGuid , FALSE , CacheVariable ) ;
if ( CacheVariable - > CurrPtr = = NULL | | EFI_ERROR ( Status ) ) {
//
// There is no matched variable in NV variable cache.
//
if ( ( ( ( Attributes & EFI_VARIABLE_APPEND_WRITE ) = = 0 ) & & ( DataSize = = 0 ) ) | | ( Attributes = = 0 ) ) {
//
// It is to delete variable,
// go to delete this variable in variable HOB and
// try to flush other variables from HOB to flash.
//
2015-12-30 06:09:50 +01:00
UpdateVariableInfo ( VariableName , VendorGuid , FALSE , FALSE , FALSE , TRUE , FALSE ) ;
2015-08-17 04:30:43 +02:00
FlushHobVariableToFlash ( VariableName , VendorGuid ) ;
return EFI_SUCCESS ;
}
}
}
2010-12-22 08:33:13 +01:00
if ( ( CacheVariable - > CurrPtr = = NULL ) | | CacheVariable - > Volatile ) {
2010-12-10 10:27:54 +01:00
Variable = CacheVariable ;
} else {
//
2010-12-22 08:33:13 +01:00
// Update/Delete existing NV variable.
2010-12-10 10:27:54 +01:00
// CacheVariable points to the variable in the memory copy of Flash area
// Now let Variable points to the same variable in Flash area.
//
VariableStoreHeader = ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ) ;
2015-07-01 05:08:29 +02:00
Variable = & NvVariable ;
2010-12-10 10:27:54 +01:00
Variable - > StartPtr = GetStartPointer ( VariableStoreHeader ) ;
2015-10-23 07:28:38 +02:00
Variable - > EndPtr = ( VARIABLE_HEADER * ) ( ( UINTN ) Variable - > StartPtr + ( ( UINTN ) CacheVariable - > EndPtr - ( UINTN ) CacheVariable - > StartPtr ) ) ;
2010-12-22 08:33:13 +01:00
Variable - > CurrPtr = ( VARIABLE_HEADER * ) ( ( UINTN ) Variable - > StartPtr + ( ( UINTN ) CacheVariable - > CurrPtr - ( UINTN ) CacheVariable - > StartPtr ) ) ;
2013-01-18 02:12:32 +01:00
if ( CacheVariable - > InDeletedTransitionPtr ! = NULL ) {
Variable - > InDeletedTransitionPtr = ( VARIABLE_HEADER * ) ( ( UINTN ) Variable - > StartPtr + ( ( UINTN ) CacheVariable - > InDeletedTransitionPtr - ( UINTN ) CacheVariable - > StartPtr ) ) ;
} else {
Variable - > InDeletedTransitionPtr = NULL ;
}
2010-12-22 08:33:13 +01:00
Variable - > Volatile = FALSE ;
2015-07-01 05:08:29 +02:00
}
2010-12-22 08:33:13 +01:00
Fvb = mVariableModuleGlobal - > FvbInstance ;
2008-01-09 11:10:16 +01:00
2015-07-01 05:08:29 +02:00
//
// Tricky part: Use scratch data area at the end of volatile variable store
// as a temporary storage.
//
NextVariable = GetEndPointer ( ( VARIABLE_STORE_HEADER * ) ( ( UINTN ) mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ) ) ;
ScratchSize = mVariableModuleGlobal - > ScratchBufferSize ;
SetMem ( NextVariable , ScratchSize , 0xff ) ;
DataReady = FALSE ;
2009-04-27 09:06:01 +02:00
if ( Variable - > CurrPtr ! = NULL ) {
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// Update/Delete existing variable.
2007-07-19 12:09:07 +02:00
//
2015-07-01 05:08:29 +02:00
if ( AtRuntime ( ) ) {
2007-09-17 05:50:40 +02:00
//
2015-07-01 05:08:29 +02:00
// If AtRuntime and the variable is Volatile and Runtime Access,
// the volatile is ReadOnly, and SetVariable should be aborted and
2007-09-17 05:50:40 +02:00
// 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 ;
}
//
2015-07-01 05:08:29 +02:00
// Only variable that have NV attributes can be updated/deleted in Runtime.
//
2015-10-23 07:28:38 +02:00
if ( ( CacheVariable - > CurrPtr - > Attributes & EFI_VARIABLE_NON_VOLATILE ) = = 0 ) {
2015-07-01 05:08:29 +02:00
Status = EFI_INVALID_PARAMETER ;
goto Done ;
}
//
// Only variable that have RT attributes can be updated/deleted in Runtime.
2007-09-17 05:50:40 +02:00
//
2015-10-23 07:28:38 +02:00
if ( ( CacheVariable - > CurrPtr - > Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) = = 0 ) {
2007-09-17 05:50:40 +02:00
Status = EFI_INVALID_PARAMETER ;
2015-07-01 05:08:29 +02:00
goto Done ;
2007-09-17 05:50:40 +02:00
}
}
2010-12-10 10:27:54 +01:00
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
2010-12-10 10:27:54 +01:00
// causes it to be deleted.
2015-07-01 05:08:29 +02:00
// When the EFI_VARIABLE_APPEND_WRITE attribute is set, DataSize of zero will
// not delete the variable.
2007-07-19 12:09:07 +02:00
//
2015-07-01 05:08:29 +02:00
if ( ( ( ( Attributes & EFI_VARIABLE_APPEND_WRITE ) = = 0 ) & & ( DataSize = = 0 ) ) | | ( ( Attributes & ( EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS ) ) = = 0 ) ) {
2013-01-18 02:12:32 +01:00
if ( Variable - > InDeletedTransitionPtr ! = NULL ) {
//
// Both ADDED and IN_DELETED_TRANSITION variable are present,
// set IN_DELETED_TRANSITION one to DELETED state first.
//
2015-10-28 01:48:43 +01:00
ASSERT ( CacheVariable - > InDeletedTransitionPtr ! = NULL ) ;
2015-10-23 07:28:38 +02:00
State = CacheVariable - > InDeletedTransitionPtr - > State ;
2013-01-18 02:12:32 +01:00
State & = VAR_DELETED ;
Status = UpdateVariableStore (
& mVariableModuleGlobal - > VariableGlobal ,
Variable - > Volatile ,
FALSE ,
Fvb ,
( UINTN ) & Variable - > InDeletedTransitionPtr - > State ,
sizeof ( UINT8 ) ,
& State
) ;
if ( ! EFI_ERROR ( Status ) ) {
if ( ! Variable - > Volatile ) {
CacheVariable - > InDeletedTransitionPtr - > State = State ;
}
} else {
goto Done ;
}
}
2015-10-23 07:28:38 +02:00
State = CacheVariable - > 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
2015-07-01 05:08:29 +02:00
) ;
2007-10-04 23:01:21 +02:00
if ( ! EFI_ERROR ( Status ) ) {
2010-12-10 10:27:54 +01:00
UpdateVariableInfo ( VariableName , VendorGuid , Variable - > Volatile , FALSE , FALSE , TRUE , FALSE ) ;
if ( ! Variable - > Volatile ) {
CacheVariable - > CurrPtr - > State = State ;
2013-01-04 13:21:59 +01:00
FlushHobVariableToFlash ( VariableName , VendorGuid ) ;
2010-12-10 10:27:54 +01:00
}
2007-10-04 23:01:21 +02:00
}
2015-07-01 05:08:29 +02:00
goto Done ;
2007-09-17 05:50:40 +02:00
}
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// If the variable is marked valid, and the same data has been passed in,
2007-09-17 05:50:40 +02:00
// then return to the caller immediately.
2007-07-19 12:09:07 +02:00
//
2015-10-23 07:28:38 +02:00
if ( DataSizeOfVariable ( CacheVariable - > CurrPtr ) = = DataSize & &
( CompareMem ( Data , GetVariableDataPtr ( CacheVariable - > CurrPtr ) , DataSize ) = = 0 ) & &
2015-07-01 05:08:29 +02:00
( ( Attributes & EFI_VARIABLE_APPEND_WRITE ) = = 0 ) & &
( TimeStamp = = NULL ) ) {
//
// Variable content unchanged and no need to update timestamp, just return.
//
2010-12-10 10:27:54 +01:00
UpdateVariableInfo ( VariableName , VendorGuid , Variable - > Volatile , FALSE , TRUE , FALSE , FALSE ) ;
2007-09-17 05:50:40 +02:00
Status = EFI_SUCCESS ;
goto Done ;
2015-10-23 07:28:38 +02:00
} else if ( ( CacheVariable - > CurrPtr - > State = = VAR_ADDED ) | |
( CacheVariable - > CurrPtr - > State = = ( VAR_ADDED & VAR_IN_DELETED_TRANSITION ) ) ) {
2008-03-19 08:09:03 +01:00
2015-07-01 05:08:29 +02:00
//
// EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable.
//
if ( ( Attributes & EFI_VARIABLE_APPEND_WRITE ) ! = 0 ) {
//
// NOTE: From 0 to DataOffset of NextVariable is reserved for Variable Header and Name.
// From DataOffset of NextVariable is to save the existing variable data.
//
2015-10-23 07:28:38 +02:00
DataOffset = GetVariableDataOffset ( CacheVariable - > CurrPtr ) ;
2015-07-01 05:08:29 +02:00
BufferForMerge = ( UINT8 * ) ( ( UINTN ) NextVariable + DataOffset ) ;
2015-10-23 07:28:38 +02:00
CopyMem ( BufferForMerge , ( UINT8 * ) ( ( UINTN ) CacheVariable - > CurrPtr + DataOffset ) , DataSizeOfVariable ( CacheVariable - > CurrPtr ) ) ;
2015-07-01 05:08:29 +02:00
//
// Set Max Common/Auth Variable Data Size as default MaxDataSize.
//
if ( ( Attributes & VARIABLE_ATTRIBUTE_AT_AW ) ! = 0 ) {
MaxDataSize = mVariableModuleGlobal - > MaxAuthVariableSize - DataOffset ;
} else {
MaxDataSize = mVariableModuleGlobal - > MaxVariableSize - DataOffset ;
}
//
// Append the new data to the end of existing data.
// Max Harware error record variable data size is different from common/auth variable.
//
if ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
MaxDataSize = PcdGet32 ( PcdMaxHardwareErrorVariableSize ) - DataOffset ;
}
2015-10-23 07:28:38 +02:00
if ( DataSizeOfVariable ( CacheVariable - > CurrPtr ) + DataSize > MaxDataSize ) {
2015-07-01 05:08:29 +02:00
//
// Existing data size + new data size exceed maximum variable size limitation.
//
Status = EFI_INVALID_PARAMETER ;
goto Done ;
}
2015-10-23 07:28:38 +02:00
CopyMem ( ( UINT8 * ) ( ( UINTN ) BufferForMerge + DataSizeOfVariable ( CacheVariable - > CurrPtr ) ) , Data , DataSize ) ;
MergedBufSize = DataSizeOfVariable ( CacheVariable - > CurrPtr ) + DataSize ;
2015-07-01 05:08:29 +02:00
//
// BufferForMerge(from DataOffset of NextVariable) has included the merged existing and new data.
//
Data = BufferForMerge ;
DataSize = MergedBufSize ;
DataReady = TRUE ;
}
2007-09-17 05:50:40 +02:00
//
2010-12-10 10:27:54 +01:00
// Mark the old variable as in delete transition.
2007-09-17 05:50:40 +02:00
//
2015-10-23 07:28:38 +02:00
State = CacheVariable - > 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
2015-07-01 05:08:29 +02:00
) ;
2007-09-17 05:50:40 +02:00
if ( EFI_ERROR ( Status ) ) {
2015-07-01 05:08:29 +02:00
goto Done ;
}
2010-12-10 10:27:54 +01:00
if ( ! Variable - > Volatile ) {
CacheVariable - > CurrPtr - > State = State ;
}
2015-07-01 05:08:29 +02:00
}
2009-04-27 09:06:01 +02:00
} else {
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// Not found existing variable. Create a new variable.
2015-07-01 05:08:29 +02:00
//
if ( ( DataSize = = 0 ) & & ( ( Attributes & EFI_VARIABLE_APPEND_WRITE ) ! = 0 ) ) {
Status = EFI_SUCCESS ;
goto Done ;
}
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.
2015-07-01 05:08:29 +02:00
// Setting a data variable with zero DataSize or no access 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 ;
}
2015-07-01 05:08:29 +02:00
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// Only variable have NV|RT attribute can be created in Runtime.
2007-09-17 05:50:40 +02:00
//
2010-12-10 10:27:54 +01:00
if ( AtRuntime ( ) & &
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 ;
2015-07-01 05:08:29 +02:00
}
2007-09-17 05:50:40 +02:00
}
//
// Function part - create a new variable and copy the data.
// Both update a variable and create a variable will come here.
//
NextVariable - > StartId = VARIABLE_DATA ;
//
// NextVariable->State = VAR_ADDED;
//
2010-12-10 10:27:54 +01:00
NextVariable - > Reserved = 0 ;
2015-07-01 05:08:29 +02:00
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
AuthVariable = ( AUTHENTICATED_VARIABLE_HEADER * ) NextVariable ;
AuthVariable - > PubKeyIndex = KeyIndex ;
AuthVariable - > MonotonicCount = MonotonicCount ;
ZeroMem ( & AuthVariable - > TimeStamp , sizeof ( EFI_TIME ) ) ;
if ( ( ( Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS ) ! = 0 ) & &
( TimeStamp ! = NULL ) ) {
if ( ( Attributes & EFI_VARIABLE_APPEND_WRITE ) = = 0 ) {
CopyMem ( & AuthVariable - > TimeStamp , TimeStamp , sizeof ( EFI_TIME ) ) ;
} else {
//
// In the case when the EFI_VARIABLE_APPEND_WRITE attribute is set, only
// when the new TimeStamp value is later than the current timestamp associated
// with the variable, we need associate the new timestamp with the updated value.
//
if ( Variable - > CurrPtr ! = NULL ) {
2015-10-23 07:28:38 +02:00
if ( VariableCompareTimeStampInternal ( & ( ( ( AUTHENTICATED_VARIABLE_HEADER * ) CacheVariable - > CurrPtr ) - > TimeStamp ) , TimeStamp ) ) {
2015-07-01 05:08:29 +02:00
CopyMem ( & AuthVariable - > TimeStamp , TimeStamp , sizeof ( EFI_TIME ) ) ;
}
}
}
}
}
//
// The EFI_VARIABLE_APPEND_WRITE attribute will never be set in the returned
// Attributes bitmask parameter of a GetVariable() call.
//
NextVariable - > Attributes = Attributes & ( ~ EFI_VARIABLE_APPEND_WRITE ) ;
VarNameOffset = GetVariableHeaderSize ( ) ;
2010-12-10 10:27:54 +01:00
VarNameSize = StrSize ( VariableName ) ;
2007-09-17 05:50:40 +02:00
CopyMem (
( UINT8 * ) ( ( UINTN ) NextVariable + VarNameOffset ) ,
VariableName ,
VarNameSize
) ;
VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE ( VarNameSize ) ;
2015-07-01 05:08:29 +02:00
//
// If DataReady is TRUE, it means the variable data has been saved into
// NextVariable during EFI_VARIABLE_APPEND_WRITE operation preparation.
//
if ( ! DataReady ) {
CopyMem (
( UINT8 * ) ( ( UINTN ) NextVariable + VarDataOffset ) ,
Data ,
DataSize
) ;
}
CopyMem ( GetVendorGuidPtr ( NextVariable ) , VendorGuid , sizeof ( EFI_GUID ) ) ;
2007-09-17 05:50:40 +02:00
//
// There will be pad bytes after Data, the NextVariable->NameSize and
// NextVariable->DataSize should not include pad size so that variable
2010-12-10 10:27:54 +01:00
// service can get actual size in GetVariable.
2007-09-17 05:50:40 +02:00
//
2015-07-01 05:08:29 +02:00
SetNameSizeOfVariable ( NextVariable , VarNameSize ) ;
SetDataSizeOfVariable ( NextVariable , DataSize ) ;
2007-09-17 05:50:40 +02:00
//
// 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
//
2010-12-10 10:27:54 +01:00
// Create a nonvolatile variable.
2007-07-19 12:09:07 +02:00
//
2007-10-06 19:02:23 +02:00
Volatile = FALSE ;
2015-01-27 09:42:47 +01:00
IsCommonVariable = FALSE ;
IsCommonUserVariable = FALSE ;
if ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = 0 ) {
IsCommonVariable = TRUE ;
IsCommonUserVariable = IsUserVariable ( NextVariable ) ;
}
if ( ( ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = 0 )
2010-01-30 00:39:48 +01:00
& & ( ( VarSize + mVariableModuleGlobal - > HwErrVariableTotalSize ) > PcdGet32 ( PcdHwErrStorageSize ) ) )
2015-01-27 09:42:47 +01:00
| | ( IsCommonVariable & & ( ( VarSize + mVariableModuleGlobal - > CommonVariableTotalSize ) > mVariableModuleGlobal - > CommonVariableSpace ) )
| | ( IsCommonVariable & & AtRuntime ( ) & & ( ( VarSize + mVariableModuleGlobal - > CommonVariableTotalSize ) > mVariableModuleGlobal - > CommonRuntimeVariableSpace ) )
| | ( IsCommonUserVariable & & ( ( VarSize + mVariableModuleGlobal - > CommonUserVariableTotalSize ) > mVariableModuleGlobal - > CommonMaxUserVariableSpace ) ) ) {
2010-12-10 10:27:54 +01:00
if ( AtRuntime ( ) ) {
2015-01-27 09:42:47 +01:00
if ( IsCommonUserVariable & & ( ( VarSize + mVariableModuleGlobal - > CommonUserVariableTotalSize ) > mVariableModuleGlobal - > CommonMaxUserVariableSpace ) ) {
RecordVarErrorFlag ( VAR_ERROR_FLAG_USER_ERROR , VariableName , VendorGuid , Attributes , VarSize ) ;
}
if ( IsCommonVariable & & ( ( VarSize + mVariableModuleGlobal - > CommonVariableTotalSize ) > mVariableModuleGlobal - > CommonRuntimeVariableSpace ) ) {
RecordVarErrorFlag ( VAR_ERROR_FLAG_SYSTEM_ERROR , VariableName , VendorGuid , Attributes , VarSize ) ;
}
2007-09-17 05:50:40 +02:00
Status = EFI_OUT_OF_RESOURCES ;
goto Done ;
}
//
2013-11-04 04:13:54 +01:00
// Perform garbage collection & reclaim operation, and integrate the new variable at the same time.
2007-09-17 05:50:40 +02:00
//
2015-07-01 05:08:29 +02:00
Status = Reclaim (
mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ,
& mVariableModuleGlobal - > NonVolatileLastVariableOffset ,
FALSE ,
Variable ,
NextVariable ,
HEADER_ALIGN ( VarSize )
) ;
2013-11-04 04:13:54 +01:00
if ( ! EFI_ERROR ( Status ) ) {
//
// The new variable has been integrated successfully during reclaiming.
//
if ( Variable - > CurrPtr ! = NULL ) {
CacheVariable - > CurrPtr = ( VARIABLE_HEADER * ) ( ( UINTN ) CacheVariable - > StartPtr + ( ( UINTN ) Variable - > CurrPtr - ( UINTN ) Variable - > StartPtr ) ) ;
CacheVariable - > InDeletedTransitionPtr = NULL ;
}
UpdateVariableInfo ( VariableName , VendorGuid , FALSE , FALSE , TRUE , FALSE , FALSE ) ;
FlushHobVariableToFlash ( VariableName , VendorGuid ) ;
2015-01-27 09:42:47 +01:00
} else {
if ( IsCommonUserVariable & & ( ( VarSize + mVariableModuleGlobal - > CommonUserVariableTotalSize ) > mVariableModuleGlobal - > CommonMaxUserVariableSpace ) ) {
RecordVarErrorFlag ( VAR_ERROR_FLAG_USER_ERROR , VariableName , VendorGuid , Attributes , VarSize ) ;
}
if ( IsCommonVariable & & ( ( VarSize + mVariableModuleGlobal - > CommonVariableTotalSize ) > mVariableModuleGlobal - > CommonVariableSpace ) ) {
RecordVarErrorFlag ( VAR_ERROR_FLAG_SYSTEM_ERROR , VariableName , VendorGuid , Attributes , VarSize ) ;
}
2013-01-18 02:12:32 +01:00
}
2013-11-04 04:13:54 +01:00
goto Done ;
2007-07-19 12:09:07 +02:00
}
//
2010-12-10 10:27:54 +01:00
// Four steps
2007-09-17 05:50:40 +02:00
// 1. Write variable header
2015-07-01 05:08:29 +02:00
// 2. Set variable state to header valid
2008-01-14 07:35:23 +01:00
// 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
//
2010-12-10 10:27:54 +01:00
CacheOffset = mVariableModuleGlobal - > NonVolatileLastVariableOffset ;
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 ,
2015-07-01 05:08:29 +02:00
( UINT32 ) GetVariableHeaderSize ( ) ,
2007-09-17 05:50:40 +02:00
( 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 ,
2010-12-10 10:27:54 +01:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset + OFFSET_OF ( VARIABLE_HEADER , State ) ,
sizeof ( UINT8 ) ,
& NextVariable - > State
2008-01-14 07:35:23 +01:00
) ;
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 ,
2015-07-01 05:08:29 +02:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset + GetVariableHeaderSize ( ) ,
( UINT32 ) ( VarSize - GetVariableHeaderSize ( ) ) ,
( UINT8 * ) NextVariable + GetVariableHeaderSize ( )
2007-09-17 05:50:40 +02:00
) ;
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 ,
2010-12-10 10:27:54 +01:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset + OFFSET_OF ( VARIABLE_HEADER , State ) ,
sizeof ( UINT8 ) ,
& NextVariable - > State
2007-09-17 05:50:40 +02:00
) ;
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 ) ;
2015-01-27 09:42:47 +01:00
if ( IsCommonUserVariable ) {
mVariableModuleGlobal - > CommonUserVariableTotalSize + = HEADER_ALIGN ( VarSize ) ;
}
2009-04-07 08:42:12 +02:00
}
2010-12-10 10:27:54 +01:00
//
// update the memory copy of Flash region.
//
CopyMem ( ( UINT8 * ) mNvVariableCache + CacheOffset , ( UINT8 * ) NextVariable , VarSize ) ;
2007-09-17 05:50:40 +02:00
} else {
//
2010-12-10 10:27:54 +01:00
// Create a volatile variable.
2015-07-01 05:08:29 +02:00
//
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
//
2013-11-04 04:13:54 +01:00
// Perform garbage collection & reclaim operation, and integrate the new variable at the same time.
2007-07-19 12:09:07 +02:00
//
2015-07-01 05:08:29 +02:00
Status = Reclaim (
mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ,
& mVariableModuleGlobal - > VolatileLastVariableOffset ,
TRUE ,
Variable ,
NextVariable ,
HEADER_ALIGN ( VarSize )
) ;
2013-11-04 04:13:54 +01:00
if ( ! EFI_ERROR ( Status ) ) {
//
// The new variable has been integrated successfully during reclaiming.
//
if ( Variable - > CurrPtr ! = NULL ) {
CacheVariable - > CurrPtr = ( VARIABLE_HEADER * ) ( ( UINTN ) CacheVariable - > StartPtr + ( ( UINTN ) Variable - > CurrPtr - ( UINTN ) Variable - > StartPtr ) ) ;
CacheVariable - > InDeletedTransitionPtr = NULL ;
}
UpdateVariableInfo ( VariableName , VendorGuid , TRUE , FALSE , TRUE , FALSE , FALSE ) ;
2013-01-18 02:12:32 +01:00
}
2013-11-04 04:13:54 +01:00
goto Done ;
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
//
2010-12-10 10:27:54 +01:00
// Mark the old variable as deleted.
2007-09-17 05:50:40 +02:00
//
2013-01-18 02:12:32 +01:00
if ( ! EFI_ERROR ( Status ) & & Variable - > CurrPtr ! = NULL ) {
if ( Variable - > InDeletedTransitionPtr ! = NULL ) {
//
// Both ADDED and IN_DELETED_TRANSITION old variable are present,
// set IN_DELETED_TRANSITION one to DELETED state first.
//
2015-10-28 01:48:43 +01:00
ASSERT ( CacheVariable - > InDeletedTransitionPtr ! = NULL ) ;
2015-10-23 07:28:38 +02:00
State = CacheVariable - > InDeletedTransitionPtr - > State ;
2013-01-18 02:12:32 +01:00
State & = VAR_DELETED ;
Status = UpdateVariableStore (
& mVariableModuleGlobal - > VariableGlobal ,
Variable - > Volatile ,
FALSE ,
Fvb ,
( UINTN ) & Variable - > InDeletedTransitionPtr - > State ,
sizeof ( UINT8 ) ,
& State
) ;
if ( ! EFI_ERROR ( Status ) ) {
if ( ! Variable - > Volatile ) {
CacheVariable - > InDeletedTransitionPtr - > State = State ;
}
} else {
goto Done ;
}
}
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 (
2009-04-27 09:06:01 +02:00
& mVariableModuleGlobal - > VariableGlobal ,
Variable - > Volatile ,
FALSE ,
Fvb ,
( UINTN ) & Variable - > CurrPtr - > State ,
sizeof ( UINT8 ) ,
& State
) ;
2015-07-01 05:08:29 +02:00
if ( ! EFI_ERROR ( Status ) & & ! Variable - > Volatile ) {
2010-12-10 10:27:54 +01:00
CacheVariable - > CurrPtr - > State = State ;
}
2009-04-27 09:06:01 +02:00
}
if ( ! EFI_ERROR ( Status ) ) {
UpdateVariableInfo ( VariableName , VendorGuid , Volatile , FALSE , TRUE , FALSE , FALSE ) ;
2013-01-04 13:21:59 +01:00
if ( ! Volatile ) {
FlushHobVariableToFlash ( VariableName , VendorGuid ) ;
}
2009-04-27 09:06:01 +02:00
}
Done :
return Status ;
}
/**
This code finds variable in storage blocks ( Volatile or Non - Volatile ) .
2014-11-19 02:08:23 +01:00
Caution : This function may receive untrusted input .
This function may be invoked in SMM mode , and datasize is external input .
This function will do basic validation , before parse the data .
2009-04-27 09:06:01 +02:00
@ 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 .
2016-01-29 10:15:43 +01:00
@ param Data The buffer to return the contents of the variable . May be NULL
with a zero DataSize in order to determine the size buffer needed .
2015-07-01 05:08:29 +02:00
2010-12-10 10:27:54 +01:00
@ 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 .
2009-04-27 09:06:01 +02:00
* */
EFI_STATUS
EFIAPI
2010-12-10 10:27:54 +01:00
VariableServiceGetVariable (
2009-04-27 09:06:01 +02:00
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
OUT UINT32 * Attributes OPTIONAL ,
IN OUT UINTN * DataSize ,
2016-01-29 10:15:43 +01:00
OUT VOID * Data OPTIONAL
2009-04-27 09:06:01 +02:00
)
{
EFI_STATUS Status ;
VARIABLE_POINTER_TRACK Variable ;
UINTN VarDataSize ;
if ( VariableName = = NULL | | VendorGuid = = NULL | | DataSize = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
2016-05-13 07:00:01 +02:00
if ( VariableName [ 0 ] = = 0 ) {
return EFI_NOT_FOUND ;
}
2009-04-27 09:06:01 +02:00
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
2015-07-01 05:08:29 +02:00
2012-03-30 09:19:44 +02:00
Status = FindVariable ( VariableName , VendorGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal , FALSE ) ;
2009-04-27 09:06:01 +02:00
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 ) ;
2015-07-01 05:08:29 +02:00
2009-04-27 09:06:01 +02:00
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 .
2014-11-19 02:08:23 +01:00
Caution : This function may receive untrusted input .
This function may be invoked in SMM mode . This function will do basic validation , before parse the data .
2015-07-01 05:08:29 +02:00
@ param [ in ] VariableName Pointer to variable name .
@ param [ in ] VendorGuid Variable Vendor Guid .
@ param [ out ] VariablePtr Pointer to variable header address .
2009-04-27 09:06:01 +02:00
2015-07-01 05:08:29 +02:00
@ return EFI_SUCCESS Find the specified variable .
@ return EFI_NOT_FOUND Not found .
2009-04-27 09:06:01 +02:00
* */
EFI_STATUS
EFIAPI
2015-07-01 05:08:29 +02:00
VariableServiceGetNextVariableInternal (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid ,
OUT VARIABLE_HEADER * * VariablePtr
2009-04-27 09:06:01 +02:00
)
{
2011-10-14 07:19:39 +02:00
VARIABLE_STORE_TYPE Type ;
2009-04-27 09:06:01 +02:00
VARIABLE_POINTER_TRACK Variable ;
2011-10-14 07:19:39 +02:00
VARIABLE_POINTER_TRACK VariableInHob ;
2013-01-18 02:12:32 +01:00
VARIABLE_POINTER_TRACK VariablePtrTrack ;
2009-04-27 09:06:01 +02:00
EFI_STATUS Status ;
2011-10-14 07:19:39 +02:00
VARIABLE_STORE_HEADER * VariableStoreHeader [ VariableStoreTypeMax ] ;
2009-04-27 09:06:01 +02:00
2012-03-30 09:19:44 +02:00
Status = FindVariable ( VariableName , VendorGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal , FALSE ) ;
2009-04-27 09:06:01 +02:00
if ( Variable . CurrPtr = = NULL | | EFI_ERROR ( Status ) ) {
goto Done ;
}
if ( VariableName [ 0 ] ! = 0 ) {
//
2010-12-10 10:27:54 +01:00
// If variable name is not NULL, get next variable.
2009-04-27 09:06:01 +02:00
//
Variable . CurrPtr = GetNextVariablePtr ( Variable . CurrPtr ) ;
}
2011-10-14 07:19:39 +02:00
//
// 0: Volatile, 1: HOB, 2: Non-Volatile.
// The index and attributes mapping must be kept in this order as FindVariable
// makes use of this mapping to implement search algorithm.
//
VariableStoreHeader [ VariableStoreTypeVolatile ] = ( VARIABLE_STORE_HEADER * ) ( UINTN ) mVariableModuleGlobal - > VariableGlobal . VolatileVariableBase ;
VariableStoreHeader [ VariableStoreTypeHob ] = ( VARIABLE_STORE_HEADER * ) ( UINTN ) mVariableModuleGlobal - > VariableGlobal . HobVariableBase ;
VariableStoreHeader [ VariableStoreTypeNv ] = mNvVariableCache ;
2009-04-27 09:06:01 +02:00
while ( TRUE ) {
//
2011-10-14 07:19:39 +02:00
// Switch from Volatile to HOB, to Non-Volatile.
2009-04-27 09:06:01 +02:00
//
2014-10-31 11:26:54 +01:00
while ( ! IsValidVariableHeader ( Variable . CurrPtr , Variable . EndPtr ) ) {
2011-10-14 07:19:39 +02:00
//
// Find current storage index
//
for ( Type = ( VARIABLE_STORE_TYPE ) 0 ; Type < VariableStoreTypeMax ; Type + + ) {
if ( ( VariableStoreHeader [ Type ] ! = NULL ) & & ( Variable . StartPtr = = GetStartPointer ( VariableStoreHeader [ Type ] ) ) ) {
break ;
}
}
ASSERT ( Type < VariableStoreTypeMax ) ;
//
// Switch to next storage
//
for ( Type + + ; Type < VariableStoreTypeMax ; Type + + ) {
if ( VariableStoreHeader [ Type ] ! = NULL ) {
break ;
}
}
//
2015-07-01 05:08:29 +02:00
// Capture the case that
2011-10-14 07:19:39 +02:00
// 1. current storage is the last one, or
// 2. no further storage
//
if ( Type = = VariableStoreTypeMax ) {
2009-04-27 09:06:01 +02:00
Status = EFI_NOT_FOUND ;
goto Done ;
}
2011-10-14 07:19:39 +02:00
Variable . StartPtr = GetStartPointer ( VariableStoreHeader [ Type ] ) ;
Variable . EndPtr = GetEndPointer ( VariableStoreHeader [ Type ] ) ;
Variable . CurrPtr = Variable . StartPtr ;
2009-04-27 09:06:01 +02:00
}
2011-10-14 07:19:39 +02:00
2009-04-27 09:06:01 +02:00
//
// Variable is found
//
2013-01-18 02:12:32 +01:00
if ( Variable . CurrPtr - > State = = VAR_ADDED | | Variable . CurrPtr - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
if ( ! AtRuntime ( ) | | ( ( Variable . CurrPtr - > Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) ! = 0 ) ) {
if ( Variable . CurrPtr - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
//
// If it is a IN_DELETED_TRANSITION variable,
// and there is also a same ADDED one at the same time,
// don't return it.
//
VariablePtrTrack . StartPtr = Variable . StartPtr ;
VariablePtrTrack . EndPtr = Variable . EndPtr ;
Status = FindVariableEx (
GetVariableNamePtr ( Variable . CurrPtr ) ,
2015-07-01 05:08:29 +02:00
GetVendorGuidPtr ( Variable . CurrPtr ) ,
2013-01-18 02:12:32 +01:00
FALSE ,
& VariablePtrTrack
) ;
if ( ! EFI_ERROR ( Status ) & & VariablePtrTrack . CurrPtr - > State = = VAR_ADDED ) {
Variable . CurrPtr = GetNextVariablePtr ( Variable . CurrPtr ) ;
continue ;
}
}
2011-10-14 07:19:39 +02:00
//
// Don't return NV variable when HOB overrides it
//
2015-07-01 05:08:29 +02:00
if ( ( VariableStoreHeader [ VariableStoreTypeHob ] ! = NULL ) & & ( VariableStoreHeader [ VariableStoreTypeNv ] ! = NULL ) & &
2011-10-14 07:19:39 +02:00
( Variable . StartPtr = = GetStartPointer ( VariableStoreHeader [ VariableStoreTypeNv ] ) )
) {
VariableInHob . StartPtr = GetStartPointer ( VariableStoreHeader [ VariableStoreTypeHob ] ) ;
VariableInHob . EndPtr = GetEndPointer ( VariableStoreHeader [ VariableStoreTypeHob ] ) ;
Status = FindVariableEx (
GetVariableNamePtr ( Variable . CurrPtr ) ,
2015-07-01 05:08:29 +02:00
GetVendorGuidPtr ( Variable . CurrPtr ) ,
2012-03-30 09:19:44 +02:00
FALSE ,
2011-10-14 07:19:39 +02:00
& VariableInHob
) ;
if ( ! EFI_ERROR ( Status ) ) {
Variable . CurrPtr = GetNextVariablePtr ( Variable . CurrPtr ) ;
continue ;
}
}
2015-07-01 05:08:29 +02:00
* VariablePtr = Variable . CurrPtr ;
Status = EFI_SUCCESS ;
2009-04-27 09:06:01 +02:00
goto Done ;
}
}
Variable . CurrPtr = GetNextVariablePtr ( Variable . CurrPtr ) ;
}
2007-10-04 23:01:21 +02:00
2007-07-19 12:09:07 +02:00
Done :
2015-07-01 05:08:29 +02:00
return Status ;
}
/**
This code Finds the Next available variable .
Caution : This function may receive untrusted input .
This function may be invoked in SMM mode . This function will do basic validation , before parse the data .
@ 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
VariableServiceGetNextVariableName (
IN OUT UINTN * VariableNameSize ,
IN OUT CHAR16 * VariableName ,
IN OUT EFI_GUID * VendorGuid
)
{
EFI_STATUS Status ;
UINTN VarNameSize ;
VARIABLE_HEADER * VariablePtr ;
if ( VariableNameSize = = NULL | | VariableName = = NULL | | VendorGuid = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
Status = VariableServiceGetNextVariableInternal ( VariableName , VendorGuid , & VariablePtr ) ;
if ( ! EFI_ERROR ( Status ) ) {
VarNameSize = NameSizeOfVariable ( VariablePtr ) ;
ASSERT ( VarNameSize ! = 0 ) ;
if ( VarNameSize < = * VariableNameSize ) {
CopyMem ( VariableName , GetVariableNamePtr ( VariablePtr ) , VarNameSize ) ;
CopyMem ( VendorGuid , GetVendorGuidPtr ( VariablePtr ) , sizeof ( EFI_GUID ) ) ;
Status = EFI_SUCCESS ;
} else {
Status = EFI_BUFFER_TOO_SMALL ;
}
* VariableNameSize = VarNameSize ;
}
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 ) .
2014-11-19 02:08:23 +01:00
Caution : This function may receive untrusted input .
This function may be invoked in SMM mode , and datasize and data are external input .
This function will do basic validation , before parse the data .
2015-07-01 05:08:29 +02:00
This function will parse the authentication carefully to avoid security issues , like
buffer overflow , integer overflow .
This function will check attribute carefully to avoid authentication bypass .
2014-11-19 02:08:23 +01:00
2010-12-10 10:27:54 +01:00
@ param VariableName Name of Variable to be found .
@ param VendorGuid Variable vendor GUID .
2009-04-27 09:06:01 +02:00
@ 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 .
2010-12-10 10:27:54 +01:00
@ param Data Data pointer .
2009-04-27 09:06:01 +02:00
2010-12-10 10:27:54 +01:00
@ 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 .
2009-04-27 09:06:01 +02:00
* */
EFI_STATUS
EFIAPI
2010-12-10 10:27:54 +01:00
VariableServiceSetVariable (
2009-04-27 09:06:01 +02:00
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 ;
2015-07-01 05:08:29 +02:00
UINTN PayloadSize ;
2009-04-27 09:06:01 +02:00
//
2010-12-10 10:27:54 +01:00
// Check input parameters.
2009-04-27 09:06:01 +02:00
//
if ( VariableName = = NULL | | VariableName [ 0 ] = = 0 | | VendorGuid = = NULL ) {
return EFI_INVALID_PARAMETER ;
2015-07-01 05:08:29 +02:00
}
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
//
2015-07-01 05:08:29 +02:00
// Check for reserverd bit in variable attribute.
2010-03-18 09:58:48 +01:00
//
2015-07-01 05:08:29 +02:00
if ( ( Attributes & ( ~ EFI_VARIABLE_ATTRIBUTES_MASK ) ) ! = 0 ) {
2010-03-18 09:58:48 +01:00
return EFI_INVALID_PARAMETER ;
}
2009-04-27 09:06:01 +02:00
//
2010-12-10 10:27:54 +01:00
// Make sure if runtime bit is set, boot service bit is set also.
2009-04-27 09:06:01 +02:00
//
if ( ( Attributes & ( EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS ) ) = = EFI_VARIABLE_RUNTIME_ACCESS ) {
return EFI_INVALID_PARAMETER ;
2015-07-01 05:08:29 +02:00
} else if ( ( Attributes & VARIABLE_ATTRIBUTE_AT_AW ) ! = 0 ) {
if ( ! mVariableModuleGlobal - > VariableGlobal . AuthSupport ) {
//
// Not support authenticated variable write.
//
return EFI_INVALID_PARAMETER ;
}
} else if ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = 0 ) {
if ( PcdGet32 ( PcdHwErrStorageSize ) = = 0 ) {
//
// Not support harware error record variable variable.
//
return EFI_INVALID_PARAMETER ;
}
}
//
// EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS and EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute
// cannot be set both.
//
if ( ( ( Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS ) = = EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS )
& & ( ( Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS ) = = EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS ) ) {
return EFI_INVALID_PARAMETER ;
2009-04-27 09:06:01 +02:00
}
2015-07-01 05:08:29 +02:00
if ( ( Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS ) = = EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS ) {
if ( DataSize < AUTHINFO_SIZE ) {
//
// Try to write Authenticated Variable without AuthInfo.
//
return EFI_SECURITY_VIOLATION ;
}
PayloadSize = DataSize - AUTHINFO_SIZE ;
} else if ( ( Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS ) = = EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS ) {
//
// Sanity check for EFI_VARIABLE_AUTHENTICATION_2 descriptor.
//
if ( DataSize < OFFSET_OF_AUTHINFO2_CERT_DATA | |
( ( EFI_VARIABLE_AUTHENTICATION_2 * ) Data ) - > AuthInfo . Hdr . dwLength > DataSize - ( OFFSET_OF ( EFI_VARIABLE_AUTHENTICATION_2 , AuthInfo ) ) | |
( ( EFI_VARIABLE_AUTHENTICATION_2 * ) Data ) - > AuthInfo . Hdr . dwLength < OFFSET_OF ( WIN_CERTIFICATE_UEFI_GUID , CertData ) ) {
return EFI_SECURITY_VIOLATION ;
}
PayloadSize = DataSize - AUTHINFO2_SIZE ( Data ) ;
} else {
PayloadSize = DataSize ;
}
if ( ( UINTN ) ( ~ 0 ) - PayloadSize < StrSize ( VariableName ) ) {
//
// Prevent whole variable size overflow
2013-04-22 10:52:58 +02:00
//
return EFI_INVALID_PARAMETER ;
}
2009-04-27 09:06:01 +02:00
//
// 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)
2015-07-01 05:08:29 +02:00
// bytes for HwErrRec#### variable.
2009-04-27 09:06:01 +02:00
//
if ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
2015-07-01 05:08:29 +02:00
if ( StrSize ( VariableName ) + PayloadSize > PcdGet32 ( PcdMaxHardwareErrorVariableSize ) - GetVariableHeaderSize ( ) ) {
2009-04-27 09:06:01 +02:00
return EFI_INVALID_PARAMETER ;
}
} else {
//
// The size of the VariableName, including the Unicode Null in bytes plus
2015-07-01 05:08:29 +02:00
// the DataSize is limited to maximum size of Max(Auth)VariableSize bytes.
2009-04-27 09:06:01 +02:00
//
2015-07-01 05:08:29 +02:00
if ( ( Attributes & VARIABLE_ATTRIBUTE_AT_AW ) ! = 0 ) {
if ( StrSize ( VariableName ) + PayloadSize > mVariableModuleGlobal - > MaxAuthVariableSize - GetVariableHeaderSize ( ) ) {
return EFI_INVALID_PARAMETER ;
}
} else {
if ( StrSize ( VariableName ) + PayloadSize > mVariableModuleGlobal - > MaxVariableSize - GetVariableHeaderSize ( ) ) {
return EFI_INVALID_PARAMETER ;
}
2015-01-05 04:38:36 +01:00
}
2013-08-19 07:16:45 +02:00
}
2016-01-19 14:22:05 +01:00
//
// Special Handling for MOR Lock variable.
//
Status = SetVariableCheckHandlerMor ( VariableName , VendorGuid , Attributes , PayloadSize , ( VOID * ) ( ( UINTN ) Data + DataSize - PayloadSize ) ) ;
if ( Status = = EFI_ALREADY_STARTED ) {
//
// EFI_ALREADY_STARTED means the SetVariable() action is handled inside of SetVariableCheckHandlerMor().
// Variable driver can just return SUCCESS.
//
return EFI_SUCCESS ;
}
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
2015-08-25 05:01:56 +02:00
Status = VarCheckLibSetVariableCheck ( VariableName , VendorGuid , Attributes , PayloadSize , ( VOID * ) ( ( UINTN ) Data + DataSize - PayloadSize ) , mRequestSource ) ;
2015-07-01 05:08:29 +02:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
2009-04-27 09:06:01 +02:00
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
//
2010-12-10 10:27:54 +01:00
// Consider reentrant in MCA/INIT/NMI. It needs be reupdated.
2009-04-27 09:06:01 +02:00
//
if ( 1 < InterlockedIncrement ( & mVariableModuleGlobal - > VariableGlobal . ReentrantState ) ) {
2010-12-10 10:27:54 +01:00
Point = mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ;
2009-04-27 09:06:01 +02:00
//
2010-12-10 10:27:54 +01:00
// Parse non-volatile variable data and get last variable offset.
2009-04-27 09:06:01 +02:00
//
NextVariable = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) Point ) ;
2014-10-31 11:26:54 +01:00
while ( IsValidVariableHeader ( NextVariable , GetEndPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) Point ) ) ) {
2009-04-27 09:06:01 +02:00
NextVariable = GetNextVariablePtr ( NextVariable ) ;
}
mVariableModuleGlobal - > NonVolatileLastVariableOffset = ( UINTN ) NextVariable - ( UINTN ) Point ;
}
//
2010-12-10 10:27:54 +01:00
// Check whether the input variable is already existed.
2009-04-27 09:06:01 +02:00
//
2012-03-30 09:19:44 +02:00
Status = FindVariable ( VariableName , VendorGuid , & Variable , & mVariableModuleGlobal - > VariableGlobal , TRUE ) ;
if ( ! EFI_ERROR ( Status ) ) {
if ( ( ( Variable . CurrPtr - > Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) = = 0 ) & & AtRuntime ( ) ) {
2013-05-17 05:49:35 +02:00
Status = EFI_WRITE_PROTECTED ;
goto Done ;
2012-03-30 09:19:44 +02:00
}
2015-07-01 05:08:29 +02:00
if ( Attributes ! = 0 & & ( Attributes & ( ~ EFI_VARIABLE_APPEND_WRITE ) ) ! = Variable . CurrPtr - > Attributes ) {
2013-08-16 05:19:45 +02:00
//
// If a preexisting variable is rewritten with different attributes, SetVariable() shall not
// modify the variable and shall return EFI_INVALID_PARAMETER. Two exceptions to this rule:
// 1. No access attributes specified
// 2. The only attribute differing is EFI_VARIABLE_APPEND_WRITE
//
Status = EFI_INVALID_PARAMETER ;
2015-01-27 09:42:47 +01:00
DEBUG ( ( EFI_D_INFO , " [Variable]: Rewritten a preexisting variable(0x%08x) with different attributes(0x%08x) - %g:%s \n " , Variable . CurrPtr - > Attributes , Attributes , VendorGuid , VariableName ) ) ;
2013-08-16 05:19:45 +02:00
goto Done ;
}
2012-03-30 09:19:44 +02:00
}
2009-04-27 09:06:01 +02:00
2014-03-25 07:56:55 +01:00
if ( ! FeaturePcdGet ( PcdUefiVariableDefaultLangDeprecate ) ) {
2014-03-20 03:07:48 +01:00
//
2014-03-25 07:56:55 +01:00
// Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
2014-03-20 03:07:48 +01:00
//
2014-03-25 07:56:55 +01:00
Status = AutoUpdateLangVariable ( VariableName , Data , DataSize ) ;
if ( EFI_ERROR ( Status ) ) {
//
// The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang.
//
goto Done ;
}
2014-03-20 03:07:48 +01:00
}
2009-04-27 09:06:01 +02:00
2015-07-01 05:08:29 +02:00
if ( mVariableModuleGlobal - > VariableGlobal . AuthSupport ) {
Status = AuthVariableLibProcessVariable ( VariableName , VendorGuid , Data , DataSize , Attributes ) ;
} else {
Status = UpdateVariable ( VariableName , VendorGuid , Data , DataSize , Attributes , 0 , 0 , & Variable , NULL ) ;
}
2009-04-27 09:06:01 +02:00
2013-05-17 05:49:35 +02:00
Done :
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
2015-07-01 05:08:29 +02:00
if ( ! AtRuntime ( ) ) {
if ( ! EFI_ERROR ( Status ) ) {
SecureBootHook (
VariableName ,
VendorGuid
) ;
}
}
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 .
2014-11-19 02:08:23 +01:00
Caution : This function may receive untrusted input .
This function may be invoked in SMM mode . This function will do basic validation , before parse the data .
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_SUCCESS Query successfully .
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
2014-03-25 07:56:55 +01:00
VariableServiceQueryVariableInfoInternal (
2007-10-05 16:40:23 +02:00
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 ;
2014-03-25 07:56:55 +01:00
EFI_STATUS Status ;
VARIABLE_POINTER_TRACK VariablePtrTrack ;
2009-04-07 08:42:12 +02:00
CommonVariableTotalSize = 0 ;
HwErrVariableTotalSize = 0 ;
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.
//
2010-12-10 10:27:54 +01:00
VariableStoreHeader = mNvVariableCache ;
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 ) ;
2015-07-01 05:08:29 +02:00
* MaximumVariableSize = PcdGet32 ( PcdMaxHardwareErrorVariableSize ) - GetVariableHeaderSize ( ) ;
2009-04-07 08:42:12 +02:00
} else {
if ( ( Attributes & EFI_VARIABLE_NON_VOLATILE ) ! = 0 ) {
2015-01-27 09:42:47 +01:00
if ( AtRuntime ( ) ) {
* MaximumVariableStorageSize = mVariableModuleGlobal - > CommonRuntimeVariableSpace ;
} else {
* MaximumVariableStorageSize = mVariableModuleGlobal - > CommonVariableSpace ;
}
2009-04-07 08:42:12 +02:00
}
//
2015-07-01 05:08:29 +02:00
// Let *MaximumVariableSize be Max(Auth)VariableSize with the exception of the variable header size.
2009-04-07 08:42:12 +02:00
//
2015-07-01 05:08:29 +02:00
if ( ( Attributes & VARIABLE_ATTRIBUTE_AT_AW ) ! = 0 ) {
* MaximumVariableSize = mVariableModuleGlobal - > MaxAuthVariableSize - GetVariableHeaderSize ( ) ;
} else {
* MaximumVariableSize = mVariableModuleGlobal - > MaxVariableSize - GetVariableHeaderSize ( ) ;
}
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.
//
2014-10-31 11:26:54 +01:00
while ( IsValidVariableHeader ( Variable , GetEndPointer ( VariableStoreHeader ) ) ) {
2007-07-19 12:09:07 +02:00
NextVariable = GetNextVariablePtr ( Variable ) ;
VariableSize = ( UINT64 ) ( UINTN ) NextVariable - ( UINT64 ) ( UINTN ) Variable ;
2010-12-10 10:27:54 +01:00
if ( AtRuntime ( ) ) {
2007-07-19 12:09:07 +02:00
//
2010-12-10 10:27:54 +01:00
// We don't take the state of the variables in mind
2007-07-19 12:09:07 +02:00
// when calculating RemainingVariableStorageSize,
// since the space occupied by variables not marked with
// VAR_ADDED is not allowed to be reclaimed in Runtime.
//
2011-04-27 07:43:09 +02:00
if ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
2009-04-07 08:42:12 +02:00
HwErrVariableTotalSize + = VariableSize ;
} else {
CommonVariableTotalSize + = VariableSize ;
}
2007-07-19 12:09:07 +02:00
} else {
//
2010-12-10 10:27:54 +01:00
// Only care about Variables with State VAR_ADDED, because
2007-07-19 12:09:07 +02:00
// the space not marked as VAR_ADDED is reclaimable now.
//
if ( Variable - > State = = VAR_ADDED ) {
2011-04-27 07:43:09 +02:00
if ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
2009-04-07 08:42:12 +02:00
HwErrVariableTotalSize + = VariableSize ;
} else {
CommonVariableTotalSize + = VariableSize ;
}
2014-03-25 07:56:55 +01:00
} else if ( Variable - > State = = ( VAR_IN_DELETED_TRANSITION & VAR_ADDED ) ) {
//
// If it is a IN_DELETED_TRANSITION variable,
// and there is not also a same ADDED one at the same time,
// this IN_DELETED_TRANSITION variable is valid.
//
VariablePtrTrack . StartPtr = GetStartPointer ( VariableStoreHeader ) ;
VariablePtrTrack . EndPtr = GetEndPointer ( VariableStoreHeader ) ;
Status = FindVariableEx (
GetVariableNamePtr ( Variable ) ,
2015-07-01 05:08:29 +02:00
GetVendorGuidPtr ( Variable ) ,
2014-03-25 07:56:55 +01:00
FALSE ,
& VariablePtrTrack
) ;
if ( ! EFI_ERROR ( Status ) & & VariablePtrTrack . CurrPtr - > State ! = VAR_ADDED ) {
if ( ( Variable - > Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) = = EFI_VARIABLE_HARDWARE_ERROR_RECORD ) {
HwErrVariableTotalSize + = VariableSize ;
} else {
CommonVariableTotalSize + = VariableSize ;
}
}
2007-07-19 12:09:07 +02:00
}
}
//
2010-12-10 10:27:54 +01:00
// Go to the next one.
2007-07-19 12:09:07 +02:00
//
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 ;
2015-01-27 09:42:47 +01:00
} else {
if ( * MaximumVariableStorageSize < CommonVariableTotalSize ) {
* RemainingVariableStorageSize = 0 ;
} else {
* RemainingVariableStorageSize = * MaximumVariableStorageSize - CommonVariableTotalSize ;
}
2009-04-07 08:42:12 +02:00
}
2015-07-01 05:08:29 +02:00
if ( * RemainingVariableStorageSize < GetVariableHeaderSize ( ) ) {
2007-09-17 05:50:40 +02:00
* MaximumVariableSize = 0 ;
2015-07-01 05:08:29 +02:00
} else if ( ( * RemainingVariableStorageSize - GetVariableHeaderSize ( ) ) < * MaximumVariableSize ) {
* MaximumVariableSize = * RemainingVariableStorageSize - GetVariableHeaderSize ( ) ;
2007-09-17 05:50:40 +02:00
}
2007-07-19 12:09:07 +02:00
return EFI_SUCCESS ;
}
2014-03-25 07:56:55 +01:00
/**
This code returns information about the EFI variables .
2014-11-19 02:08:23 +01:00
Caution : This function may receive untrusted input .
This function may be invoked in SMM mode . This function will do basic validation , before parse the data .
2014-03-25 07:56:55 +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 .
@ 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 .
* */
EFI_STATUS
EFIAPI
VariableServiceQueryVariableInfo (
IN UINT32 Attributes ,
OUT UINT64 * MaximumVariableStorageSize ,
OUT UINT64 * RemainingVariableStorageSize ,
OUT UINT64 * MaximumVariableSize
)
{
EFI_STATUS Status ;
if ( MaximumVariableStorageSize = = NULL | | RemainingVariableStorageSize = = NULL | | MaximumVariableSize = = NULL | | Attributes = = 0 ) {
return EFI_INVALID_PARAMETER ;
}
2015-07-01 05:08:29 +02:00
if ( ( Attributes & EFI_VARIABLE_ATTRIBUTES_MASK ) = = 0 ) {
2014-03-25 07:56:55 +01:00
//
// Make sure the Attributes combination is supported by the platform.
//
return EFI_UNSUPPORTED ;
} 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 ;
} else if ( AtRuntime ( ) & & ( ( Attributes & EFI_VARIABLE_RUNTIME_ACCESS ) = = 0 ) ) {
//
// Make sure RT Attribute is set if we are in Runtime phase.
//
return EFI_INVALID_PARAMETER ;
} 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 ;
2015-07-01 05:08:29 +02:00
} else if ( ( Attributes & VARIABLE_ATTRIBUTE_AT_AW ) ! = 0 ) {
if ( ! mVariableModuleGlobal - > VariableGlobal . AuthSupport ) {
//
// Not support authenticated variable write.
//
return EFI_UNSUPPORTED ;
}
} else if ( ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ! = 0 ) {
if ( PcdGet32 ( PcdHwErrStorageSize ) = = 0 ) {
//
// Not support harware error record variable variable.
//
return EFI_UNSUPPORTED ;
}
2014-03-25 07:56:55 +01:00
}
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
Status = VariableServiceQueryVariableInfoInternal (
Attributes ,
MaximumVariableStorageSize ,
RemainingVariableStorageSize ,
MaximumVariableSize
) ;
ReleaseLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
return Status ;
}
2008-12-12 10:27:17 +01:00
/**
2010-12-10 10:27:54 +01:00
This function reclaims variable storage if free size is below the threshold .
2014-11-19 02:08:23 +01:00
Caution : This function may be invoked at SMM mode .
Care must be taken to make sure not security issue .
2008-12-12 10:27:17 +01:00
* */
2008-01-17 10:59:51 +01:00
VOID
ReclaimForOS (
2010-12-10 10:27:54 +01:00
VOID
2008-01-17 10:59:51 +01:00
)
{
2009-09-10 08:51:55 +02:00
EFI_STATUS Status ;
2015-01-27 09:42:47 +01:00
UINTN RemainingCommonRuntimeVariableSpace ;
2009-04-07 08:42:12 +02:00
UINTN RemainingHwErrVariableSpace ;
2015-02-02 10:30:34 +01:00
STATIC BOOLEAN Reclaimed ;
//
// This function will be called only once at EndOfDxe or ReadyToBoot event.
//
if ( Reclaimed ) {
return ;
}
Reclaimed = TRUE ;
2008-01-17 10:59:51 +01:00
2015-01-27 09:42:47 +01:00
Status = EFI_SUCCESS ;
2008-01-17 10:59:51 +01:00
2015-01-27 09:42:47 +01:00
if ( mVariableModuleGlobal - > CommonRuntimeVariableSpace < mVariableModuleGlobal - > CommonVariableTotalSize ) {
RemainingCommonRuntimeVariableSpace = 0 ;
} else {
RemainingCommonRuntimeVariableSpace = mVariableModuleGlobal - > CommonRuntimeVariableSpace - mVariableModuleGlobal - > CommonVariableTotalSize ;
}
2009-04-07 08:42:12 +02:00
RemainingHwErrVariableSpace = PcdGet32 ( PcdHwErrStorageSize ) - mVariableModuleGlobal - > HwErrVariableTotalSize ;
2015-07-01 05:08:29 +02:00
2008-01-17 10:59:51 +01:00
//
2015-01-27 09:42:47 +01:00
// Check if the free area is below a threshold.
2008-01-17 10:59:51 +01:00
//
2015-07-01 05:08:29 +02:00
if ( ( ( RemainingCommonRuntimeVariableSpace < mVariableModuleGlobal - > MaxVariableSize ) | |
( RemainingCommonRuntimeVariableSpace < mVariableModuleGlobal - > MaxAuthVariableSize ) ) | |
( ( PcdGet32 ( PcdHwErrStorageSize ) ! = 0 ) & &
2009-09-10 08:51:55 +02:00
( 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 ,
2013-01-04 13:21:59 +01:00
NULL ,
2013-11-04 04:13:54 +01:00
NULL ,
0
2009-04-07 08:42:12 +02:00
) ;
2008-01-17 10:59:51 +01:00
ASSERT_EFI_ERROR ( Status ) ;
}
}
2015-07-01 05:08:29 +02:00
/**
Get non - volatile maximum variable size .
@ return Non - volatile maximum variable size .
* */
UINTN
GetNonVolatileMaxVariableSize (
VOID
)
{
if ( PcdGet32 ( PcdHwErrStorageSize ) ! = 0 ) {
return MAX ( MAX ( PcdGet32 ( PcdMaxVariableSize ) , PcdGet32 ( PcdMaxAuthVariableSize ) ) ,
PcdGet32 ( PcdMaxHardwareErrorVariableSize ) ) ;
} else {
return MAX ( PcdGet32 ( PcdMaxVariableSize ) , PcdGet32 ( PcdMaxAuthVariableSize ) ) ;
}
}
2013-07-03 11:08:40 +02:00
/**
Init non - volatile variable store .
2015-07-01 05:08:29 +02:00
@ param [ out ] NvFvHeader Output pointer to non - volatile FV header address .
2013-07-03 11:08:40 +02:00
@ retval EFI_SUCCESS Function successfully executed .
@ retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource .
@ retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted .
* */
EFI_STATUS
InitNonVolatileVariableStore (
2015-07-01 05:08:29 +02:00
OUT EFI_FIRMWARE_VOLUME_HEADER * * NvFvHeader
2013-07-03 11:08:40 +02:00
)
{
EFI_FIRMWARE_VOLUME_HEADER * FvHeader ;
2015-01-27 09:42:47 +01:00
VARIABLE_HEADER * Variable ;
2013-07-03 11:08:40 +02:00
VARIABLE_HEADER * NextVariable ;
EFI_PHYSICAL_ADDRESS VariableStoreBase ;
UINT64 VariableStoreLength ;
UINTN VariableSize ;
EFI_HOB_GUID_TYPE * GuidHob ;
EFI_PHYSICAL_ADDRESS NvStorageBase ;
UINT8 * NvStorageData ;
UINT32 NvStorageSize ;
FAULT_TOLERANT_WRITE_LAST_WRITE_DATA * FtwLastWriteData ;
UINT32 BackUpOffset ;
UINT32 BackUpSize ;
2015-01-27 09:42:47 +01:00
UINT32 HwErrStorageSize ;
UINT32 MaxUserNvVariableSpaceSize ;
UINT32 BoottimeReservedNvVariableSpaceSize ;
2015-12-30 06:09:16 +01:00
EFI_STATUS Status ;
VOID * FtwProtocol ;
2013-07-03 11:08:40 +02:00
mVariableModuleGlobal - > FvbInstance = NULL ;
//
// Allocate runtime memory used for a memory copy of the FLASH region.
// Keep the memory and the FLASH in sync as updates occur.
//
NvStorageSize = PcdGet32 ( PcdFlashNvStorageVariableSize ) ;
NvStorageData = AllocateRuntimeZeroPool ( NvStorageSize ) ;
if ( NvStorageData = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
NvStorageBase = ( EFI_PHYSICAL_ADDRESS ) PcdGet64 ( PcdFlashNvStorageVariableBase64 ) ;
if ( NvStorageBase = = 0 ) {
NvStorageBase = ( EFI_PHYSICAL_ADDRESS ) PcdGet32 ( PcdFlashNvStorageVariableBase ) ;
}
//
// Copy NV storage data to the memory buffer.
//
CopyMem ( NvStorageData , ( UINT8 * ) ( UINTN ) NvStorageBase , NvStorageSize ) ;
2015-12-30 06:09:16 +01:00
Status = GetFtwProtocol ( ( VOID * * ) & FtwProtocol ) ;
2013-07-03 11:08:40 +02:00
//
2015-12-30 06:09:16 +01:00
// If FTW protocol has been installed, no need to check FTW last write data hob.
2013-07-03 11:08:40 +02:00
//
2015-12-30 06:09:16 +01:00
if ( EFI_ERROR ( Status ) ) {
//
// Check the FTW last write data hob.
//
GuidHob = GetFirstGuidHob ( & gEdkiiFaultTolerantWriteGuid ) ;
if ( GuidHob ! = NULL ) {
FtwLastWriteData = ( FAULT_TOLERANT_WRITE_LAST_WRITE_DATA * ) GET_GUID_HOB_DATA ( GuidHob ) ;
if ( FtwLastWriteData - > TargetAddress = = NvStorageBase ) {
DEBUG ( ( EFI_D_INFO , " Variable: NV storage is backed up in spare block: 0x%x \n " , ( UINTN ) FtwLastWriteData - > SpareAddress ) ) ;
//
// Copy the backed up NV storage data to the memory buffer from spare block.
//
CopyMem ( NvStorageData , ( UINT8 * ) ( UINTN ) ( FtwLastWriteData - > SpareAddress ) , NvStorageSize ) ;
} else if ( ( FtwLastWriteData - > TargetAddress > NvStorageBase ) & &
( FtwLastWriteData - > TargetAddress < ( NvStorageBase + NvStorageSize ) ) ) {
//
// Flash NV storage from the Offset is backed up in spare block.
//
BackUpOffset = ( UINT32 ) ( FtwLastWriteData - > TargetAddress - NvStorageBase ) ;
BackUpSize = NvStorageSize - BackUpOffset ;
DEBUG ( ( EFI_D_INFO , " Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x \n " , BackUpOffset , ( UINTN ) FtwLastWriteData - > SpareAddress ) ) ;
//
// Copy the partial backed up NV storage data to the memory buffer from spare block.
//
CopyMem ( NvStorageData + BackUpOffset , ( UINT8 * ) ( UINTN ) FtwLastWriteData - > SpareAddress , BackUpSize ) ;
}
2013-07-03 11:08:40 +02:00
}
}
FvHeader = ( EFI_FIRMWARE_VOLUME_HEADER * ) NvStorageData ;
//
// Check if the Firmware Volume is not corrupted
//
if ( ( FvHeader - > Signature ! = EFI_FVH_SIGNATURE ) | | ( ! CompareGuid ( & gEfiSystemNvDataFvGuid , & FvHeader - > FileSystemGuid ) ) ) {
FreePool ( NvStorageData ) ;
DEBUG ( ( EFI_D_ERROR , " Firmware Volume for Variable Store is corrupted \n " ) ) ;
return EFI_VOLUME_CORRUPTED ;
}
VariableStoreBase = ( EFI_PHYSICAL_ADDRESS ) ( ( UINTN ) FvHeader + FvHeader - > HeaderLength ) ;
VariableStoreLength = ( UINT64 ) ( NvStorageSize - FvHeader - > HeaderLength ) ;
2015-10-23 07:28:38 +02:00
mNvFvHeaderCache = FvHeader ;
2013-07-03 11:08:40 +02:00
mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase = VariableStoreBase ;
mNvVariableCache = ( VARIABLE_STORE_HEADER * ) ( UINTN ) VariableStoreBase ;
if ( GetVariableStoreStatus ( mNvVariableCache ) ! = EfiValid ) {
FreePool ( NvStorageData ) ;
2015-10-23 07:28:38 +02:00
mNvFvHeaderCache = NULL ;
mNvVariableCache = NULL ;
2013-07-03 11:08:40 +02:00
DEBUG ( ( EFI_D_ERROR , " Variable Store header is corrupted \n " ) ) ;
return EFI_VOLUME_CORRUPTED ;
}
ASSERT ( mNvVariableCache - > Size = = VariableStoreLength ) ;
2015-01-27 09:42:47 +01:00
ASSERT ( sizeof ( VARIABLE_STORE_HEADER ) < = VariableStoreLength ) ;
2015-07-01 05:08:29 +02:00
mVariableModuleGlobal - > VariableGlobal . AuthFormat = ( BOOLEAN ) ( CompareGuid ( & mNvVariableCache - > Signature , & gEfiAuthenticatedVariableGuid ) ) ;
2015-01-27 09:42:47 +01:00
HwErrStorageSize = PcdGet32 ( PcdHwErrStorageSize ) ;
MaxUserNvVariableSpaceSize = PcdGet32 ( PcdMaxUserNvVariableSpaceSize ) ;
BoottimeReservedNvVariableSpaceSize = PcdGet32 ( PcdBoottimeReservedNvVariableSpaceSize ) ;
//
// 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 the value of
2015-07-01 05:08:29 +02:00
// (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
2015-01-27 09:42:47 +01:00
//
ASSERT ( HwErrStorageSize < ( VariableStoreLength - sizeof ( VARIABLE_STORE_HEADER ) ) ) ;
//
// Ensure that the value of PcdMaxUserNvVariableSpaceSize is less than the value of
2015-07-01 05:08:29 +02:00
// (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
2015-01-27 09:42:47 +01:00
//
ASSERT ( MaxUserNvVariableSpaceSize < ( VariableStoreLength - sizeof ( VARIABLE_STORE_HEADER ) - HwErrStorageSize ) ) ;
//
// Ensure that the value of PcdBoottimeReservedNvVariableSpaceSize is less than the value of
2015-07-01 05:08:29 +02:00
// (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
2015-01-27 09:42:47 +01:00
//
ASSERT ( BoottimeReservedNvVariableSpaceSize < ( VariableStoreLength - sizeof ( VARIABLE_STORE_HEADER ) - HwErrStorageSize ) ) ;
mVariableModuleGlobal - > CommonVariableSpace = ( ( UINTN ) VariableStoreLength - sizeof ( VARIABLE_STORE_HEADER ) - HwErrStorageSize ) ;
mVariableModuleGlobal - > CommonMaxUserVariableSpace = ( ( MaxUserNvVariableSpaceSize ! = 0 ) ? MaxUserNvVariableSpaceSize : mVariableModuleGlobal - > CommonVariableSpace ) ;
mVariableModuleGlobal - > CommonRuntimeVariableSpace = mVariableModuleGlobal - > CommonVariableSpace - BoottimeReservedNvVariableSpaceSize ;
DEBUG ( ( EFI_D_INFO , " Variable driver common space: 0x%x 0x%x 0x%x \n " , mVariableModuleGlobal - > CommonVariableSpace , mVariableModuleGlobal - > CommonMaxUserVariableSpace , mVariableModuleGlobal - > CommonRuntimeVariableSpace ) ) ;
2013-07-03 11:08:40 +02:00
//
2015-07-01 05:08:29 +02:00
// The max NV variable size should be < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
2013-07-03 11:08:40 +02:00
//
2015-07-01 05:08:29 +02:00
ASSERT ( GetNonVolatileMaxVariableSize ( ) < ( VariableStoreLength - sizeof ( VARIABLE_STORE_HEADER ) ) ) ;
mVariableModuleGlobal - > MaxVariableSize = PcdGet32 ( PcdMaxVariableSize ) ;
mVariableModuleGlobal - > MaxAuthVariableSize = ( ( PcdGet32 ( PcdMaxAuthVariableSize ) ! = 0 ) ? PcdGet32 ( PcdMaxAuthVariableSize ) : mVariableModuleGlobal - > MaxVariableSize ) ;
2013-07-03 11:08:40 +02:00
//
// Parse non-volatile variable data and get last variable offset.
//
2015-01-27 09:42:47 +01:00
Variable = GetStartPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) VariableStoreBase ) ;
while ( IsValidVariableHeader ( Variable , GetEndPointer ( ( VARIABLE_STORE_HEADER * ) ( UINTN ) VariableStoreBase ) ) ) {
NextVariable = GetNextVariablePtr ( Variable ) ;
VariableSize = ( UINTN ) NextVariable - ( UINTN ) Variable ;
if ( ( Variable - > Attributes & ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) = = ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD ) ) {
mVariableModuleGlobal - > HwErrVariableTotalSize + = VariableSize ;
2013-07-03 11:08:40 +02:00
} else {
2015-01-27 09:42:47 +01:00
mVariableModuleGlobal - > CommonVariableTotalSize + = VariableSize ;
2013-07-03 11:08:40 +02:00
}
2015-01-27 09:42:47 +01:00
Variable = NextVariable ;
2013-07-03 11:08:40 +02:00
}
2015-01-27 09:42:47 +01:00
mVariableModuleGlobal - > NonVolatileLastVariableOffset = ( UINTN ) Variable - ( UINTN ) VariableStoreBase ;
2013-07-03 11:08:40 +02:00
2015-07-01 05:08:29 +02:00
* NvFvHeader = FvHeader ;
2013-07-03 11:08:40 +02:00
return EFI_SUCCESS ;
}
2013-01-04 13:21:59 +01:00
/**
Flush the HOB variable to flash .
@ param [ in ] VariableName Name of variable has been updated or deleted .
@ param [ in ] VendorGuid Guid of variable has been updated or deleted .
* */
VOID
FlushHobVariableToFlash (
IN CHAR16 * VariableName ,
IN EFI_GUID * VendorGuid
)
{
EFI_STATUS Status ;
VARIABLE_STORE_HEADER * VariableStoreHeader ;
VARIABLE_HEADER * Variable ;
VOID * VariableData ;
2015-08-17 04:30:43 +02:00
VARIABLE_POINTER_TRACK VariablePtrTrack ;
2013-01-04 13:21:59 +01:00
BOOLEAN ErrorFlag ;
ErrorFlag = FALSE ;
//
// Flush the HOB variable to flash.
//
if ( mVariableModuleGlobal - > VariableGlobal . HobVariableBase ! = 0 ) {
VariableStoreHeader = ( VARIABLE_STORE_HEADER * ) ( UINTN ) mVariableModuleGlobal - > VariableGlobal . HobVariableBase ;
//
// Set HobVariableBase to 0, it can avoid SetVariable to call back.
//
mVariableModuleGlobal - > VariableGlobal . HobVariableBase = 0 ;
for ( Variable = GetStartPointer ( VariableStoreHeader )
2014-10-31 11:26:54 +01:00
; IsValidVariableHeader ( Variable , GetEndPointer ( VariableStoreHeader ) )
2013-01-04 13:21:59 +01:00
; Variable = GetNextVariablePtr ( Variable )
) {
if ( Variable - > State ! = VAR_ADDED ) {
//
// The HOB variable has been set to DELETED state in local.
//
continue ;
}
ASSERT ( ( Variable - > Attributes & EFI_VARIABLE_NON_VOLATILE ) ! = 0 ) ;
if ( VendorGuid = = NULL | | VariableName = = NULL | |
2015-07-01 05:08:29 +02:00
! CompareGuid ( VendorGuid , GetVendorGuidPtr ( Variable ) ) | |
2013-01-04 13:21:59 +01:00
StrCmp ( VariableName , GetVariableNamePtr ( Variable ) ) ! = 0 ) {
VariableData = GetVariableDataPtr ( Variable ) ;
2015-08-17 04:30:43 +02:00
FindVariable ( GetVariableNamePtr ( Variable ) , GetVendorGuidPtr ( Variable ) , & VariablePtrTrack , & mVariableModuleGlobal - > VariableGlobal , FALSE ) ;
Status = UpdateVariable (
2013-01-04 13:21:59 +01:00
GetVariableNamePtr ( Variable ) ,
2015-07-01 05:08:29 +02:00
GetVendorGuidPtr ( Variable ) ,
2015-08-17 04:30:43 +02:00
VariableData ,
2015-07-01 05:08:29 +02:00
DataSizeOfVariable ( Variable ) ,
2015-08-17 04:30:43 +02:00
Variable - > Attributes ,
0 ,
0 ,
& VariablePtrTrack ,
NULL
) ;
2015-07-01 05:08:29 +02:00
DEBUG ( ( EFI_D_INFO , " Variable driver flush the HOB variable to flash: %g %s %r \n " , GetVendorGuidPtr ( Variable ) , GetVariableNamePtr ( Variable ) , Status ) ) ;
2013-01-04 13:21:59 +01:00
} else {
//
2015-08-17 04:30:43 +02:00
// The updated or deleted variable is matched with this HOB variable.
2013-01-04 13:21:59 +01:00
// Don't break here because we will try to set other HOB variables
// since this variable could be set successfully.
//
Status = EFI_SUCCESS ;
}
if ( ! EFI_ERROR ( Status ) ) {
//
// If set variable successful, or the updated or deleted variable is matched with the HOB variable,
// set the HOB variable to DELETED state in local.
//
2015-07-01 05:08:29 +02:00
DEBUG ( ( EFI_D_INFO , " Variable driver set the HOB variable to DELETED state in local: %g %s \n " , GetVendorGuidPtr ( Variable ) , GetVariableNamePtr ( Variable ) ) ) ;
2013-01-04 13:21:59 +01:00
Variable - > State & = VAR_DELETED ;
} else {
ErrorFlag = TRUE ;
}
}
if ( ErrorFlag ) {
//
// We still have HOB variable(s) not flushed in flash.
//
mVariableModuleGlobal - > VariableGlobal . HobVariableBase = ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) VariableStoreHeader ;
} else {
//
// All HOB variables have been flushed in flash.
//
DEBUG ( ( EFI_D_INFO , " Variable driver: all HOB variables have been flushed in flash. \n " ) ) ;
if ( ! AtRuntime ( ) ) {
FreePool ( ( VOID * ) VariableStoreHeader ) ;
}
}
}
}
2010-12-10 10:27:54 +01:00
2008-12-12 10:27:17 +01:00
/**
2013-07-03 11:08:40 +02:00
Initializes variable write service after FTW was ready .
2008-12-12 10:27:17 +01:00
2010-12-10 10:27:54 +01:00
@ retval EFI_SUCCESS Function successfully executed .
@ retval Others Fail to initialize the variable service .
* */
EFI_STATUS
VariableWriteServiceInitialize (
VOID
)
{
EFI_STATUS Status ;
UINTN Index ;
UINT8 Data ;
EFI_PHYSICAL_ADDRESS VariableStoreBase ;
2013-07-03 11:08:40 +02:00
EFI_PHYSICAL_ADDRESS NvStorageBase ;
2015-07-01 05:08:29 +02:00
VARIABLE_ENTRY_PROPERTY * VariableEntry ;
2010-12-10 10:27:54 +01:00
2015-08-17 04:30:43 +02:00
AcquireLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
2013-07-03 11:08:40 +02:00
NvStorageBase = ( EFI_PHYSICAL_ADDRESS ) PcdGet64 ( PcdFlashNvStorageVariableBase64 ) ;
if ( NvStorageBase = = 0 ) {
NvStorageBase = ( EFI_PHYSICAL_ADDRESS ) PcdGet32 ( PcdFlashNvStorageVariableBase ) ;
}
2015-10-23 07:28:38 +02:00
VariableStoreBase = NvStorageBase + ( mNvFvHeaderCache - > HeaderLength ) ;
2013-07-03 11:08:40 +02:00
//
// Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.
//
mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase = VariableStoreBase ;
2015-07-01 05:08:29 +02:00
2010-12-10 10:27:54 +01:00
//
// Check if the free area is really free.
//
2015-10-23 07:28:38 +02:00
for ( Index = mVariableModuleGlobal - > NonVolatileLastVariableOffset ; Index < mNvVariableCache - > Size ; Index + + ) {
2010-12-10 10:27:54 +01:00
Data = ( ( UINT8 * ) mNvVariableCache ) [ Index ] ;
if ( Data ! = 0xff ) {
//
// There must be something wrong in variable store, do reclaim operation.
//
Status = Reclaim (
mVariableModuleGlobal - > VariableGlobal . NonVolatileVariableBase ,
& mVariableModuleGlobal - > NonVolatileLastVariableOffset ,
FALSE ,
2013-01-04 13:21:59 +01:00
NULL ,
2013-11-04 04:13:54 +01:00
NULL ,
0
2010-12-10 10:27:54 +01:00
) ;
if ( EFI_ERROR ( Status ) ) {
2015-08-17 04:30:43 +02:00
ReleaseLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
2010-12-10 10:27:54 +01:00
return Status ;
}
break ;
}
}
2013-01-04 13:21:59 +01:00
FlushHobVariableToFlash ( NULL , NULL ) ;
2011-10-14 07:19:39 +02:00
2015-07-01 05:08:29 +02:00
Status = EFI_SUCCESS ;
2015-08-25 05:01:56 +02:00
ZeroMem ( & mAuthContextOut , sizeof ( mAuthContextOut ) ) ;
2015-07-01 05:08:29 +02:00
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
//
// Authenticated variable initialize.
//
2015-08-25 05:01:56 +02:00
mAuthContextIn . StructSize = sizeof ( AUTH_VAR_LIB_CONTEXT_IN ) ;
mAuthContextIn . MaxAuthVariableSize = mVariableModuleGlobal - > MaxAuthVariableSize - GetVariableHeaderSize ( ) ;
Status = AuthVariableLibInitialize ( & mAuthContextIn , & mAuthContextOut ) ;
2015-07-01 05:08:29 +02:00
if ( ! EFI_ERROR ( Status ) ) {
DEBUG ( ( EFI_D_INFO , " Variable driver will work with auth variable support! \n " ) ) ;
mVariableModuleGlobal - > VariableGlobal . AuthSupport = TRUE ;
2015-08-25 05:01:56 +02:00
if ( mAuthContextOut . AuthVarEntry ! = NULL ) {
for ( Index = 0 ; Index < mAuthContextOut . AuthVarEntryCount ; Index + + ) {
VariableEntry = & mAuthContextOut . AuthVarEntry [ Index ] ;
Status = VarCheckLibVariablePropertySet (
2015-07-01 05:08:29 +02:00
VariableEntry - > Name ,
VariableEntry - > Guid ,
& VariableEntry - > VariableProperty
) ;
ASSERT_EFI_ERROR ( Status ) ;
}
}
} else if ( Status = = EFI_UNSUPPORTED ) {
DEBUG ( ( EFI_D_INFO , " NOTICE - AuthVariableLibInitialize() returns %r! \n " , Status ) ) ;
DEBUG ( ( EFI_D_INFO , " Variable driver will continue to work without auth variable support! \n " ) ) ;
mVariableModuleGlobal - > VariableGlobal . AuthSupport = FALSE ;
Status = EFI_SUCCESS ;
}
}
if ( ! EFI_ERROR ( Status ) ) {
2016-10-26 19:15:27 +02:00
for ( Index = 0 ; Index < ARRAY_SIZE ( mVariableEntryProperty ) ; Index + + ) {
2015-07-01 05:08:29 +02:00
VariableEntry = & mVariableEntryProperty [ Index ] ;
2015-08-25 05:01:56 +02:00
Status = VarCheckLibVariablePropertySet ( VariableEntry - > Name , VariableEntry - > Guid , & VariableEntry - > VariableProperty ) ;
2015-07-01 05:08:29 +02:00
ASSERT_EFI_ERROR ( Status ) ;
}
}
2015-08-17 04:30:43 +02:00
ReleaseLockOnlyAtBootTime ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock ) ;
2016-01-19 14:22:05 +01:00
//
// Initialize MOR Lock variable.
//
MorLockInit ( ) ;
2015-07-01 05:08:29 +02:00
return Status ;
2010-12-10 10:27:54 +01:00
}
/**
Initializes variable store area for non - volatile and volatile variable .
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 (
2010-12-10 10:27:54 +01:00
VOID
2007-07-19 12:09:07 +02:00
)
{
EFI_STATUS Status ;
VARIABLE_STORE_HEADER * VolatileVariableStore ;
VARIABLE_STORE_HEADER * VariableStoreHeader ;
2007-10-05 16:40:23 +02:00
UINT64 VariableStoreLength ;
2009-04-07 08:42:12 +02:00
UINTN ScratchSize ;
2011-10-14 07:19:39 +02:00
EFI_HOB_GUID_TYPE * GuidHob ;
2015-07-01 05:08:29 +02:00
EFI_GUID * VariableGuid ;
EFI_FIRMWARE_VOLUME_HEADER * NvFvHeader ;
2007-07-19 12:09:07 +02:00
2008-01-17 10:59:51 +01:00
//
// 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
2010-12-10 10:27:54 +01:00
InitializeLock ( & mVariableModuleGlobal - > VariableGlobal . VariableServicesLock , TPL_NOTIFY ) ;
2007-07-19 12:09:07 +02:00
2015-07-01 05:08:29 +02:00
//
// Init non-volatile variable store.
//
2015-07-29 13:11:34 +02:00
NvFvHeader = NULL ;
2015-07-01 05:08:29 +02:00
Status = InitNonVolatileVariableStore ( & NvFvHeader ) ;
if ( EFI_ERROR ( Status ) ) {
FreePool ( mVariableModuleGlobal ) ;
return Status ;
}
//
// mVariableModuleGlobal->VariableGlobal.AuthFormat
// has been initialized in InitNonVolatileVariableStore().
//
if ( mVariableModuleGlobal - > VariableGlobal . AuthFormat ) {
DEBUG ( ( EFI_D_INFO , " Variable driver will work with auth variable format! \n " ) ) ;
//
// Set AuthSupport to FALSE first, VariableWriteServiceInitialize() will initialize it.
//
mVariableModuleGlobal - > VariableGlobal . AuthSupport = FALSE ;
VariableGuid = & gEfiAuthenticatedVariableGuid ;
} else {
DEBUG ( ( EFI_D_INFO , " Variable driver will work without auth variable support! \n " ) ) ;
mVariableModuleGlobal - > VariableGlobal . AuthSupport = FALSE ;
VariableGuid = & gEfiVariableGuid ;
}
2011-10-14 07:19:39 +02:00
//
// Get HOB variable store.
//
2015-07-01 05:08:29 +02:00
GuidHob = GetFirstGuidHob ( VariableGuid ) ;
2011-10-14 07:19:39 +02:00
if ( GuidHob ! = NULL ) {
2011-10-19 11:30:43 +02:00
VariableStoreHeader = GET_GUID_HOB_DATA ( GuidHob ) ;
2013-01-04 13:21:59 +01:00
VariableStoreLength = ( UINT64 ) ( GuidHob - > Header . HobLength - sizeof ( EFI_HOB_GUID_TYPE ) ) ;
2011-10-19 11:30:43 +02:00
if ( GetVariableStoreStatus ( VariableStoreHeader ) = = EfiValid ) {
2013-01-04 13:21:59 +01:00
mVariableModuleGlobal - > VariableGlobal . HobVariableBase = ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) AllocateRuntimeCopyPool ( ( UINTN ) VariableStoreLength , ( VOID * ) VariableStoreHeader ) ;
if ( mVariableModuleGlobal - > VariableGlobal . HobVariableBase = = 0 ) {
2015-07-01 05:08:29 +02:00
FreePool ( NvFvHeader ) ;
2013-07-03 11:08:40 +02:00
FreePool ( mVariableModuleGlobal ) ;
2013-01-04 13:21:59 +01:00
return EFI_OUT_OF_RESOURCES ;
}
2011-10-19 11:30:43 +02:00
} else {
DEBUG ( ( EFI_D_ERROR , " HOB Variable Store header is corrupted! \n " ) ) ;
}
2011-10-14 07:19:39 +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
//
2015-07-01 05:08:29 +02:00
ScratchSize = GetNonVolatileMaxVariableSize ( ) ;
mVariableModuleGlobal - > ScratchBufferSize = ScratchSize ;
2010-01-30 00:39:48 +01:00
VolatileVariableStore = AllocateRuntimePool ( PcdGet32 ( PcdVariableStoreSize ) + ScratchSize ) ;
2007-07-19 12:09:07 +02:00
if ( VolatileVariableStore = = NULL ) {
2013-07-03 11:08:40 +02:00
if ( mVariableModuleGlobal - > VariableGlobal . HobVariableBase ! = 0 ) {
FreePool ( ( VOID * ) ( UINTN ) mVariableModuleGlobal - > VariableGlobal . HobVariableBase ) ;
}
2015-07-01 05:08:29 +02:00
FreePool ( NvFvHeader ) ;
2007-07-19 12:09:07 +02:00
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
//
2010-12-10 10:27:54 +01:00
// Initialize Variable Specific Data.
2007-07-19 12:09:07 +02:00
//
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 ;
2007-07-19 12:09:07 +02:00
2015-07-01 05:08:29 +02:00
CopyGuid ( & VolatileVariableStore - > Signature , VariableGuid ) ;
2010-12-10 10:27:54 +01:00
VolatileVariableStore - > Size = PcdGet32 ( PcdVariableStoreSize ) ;
VolatileVariableStore - > Format = VARIABLE_STORE_FORMATTED ;
VolatileVariableStore - > State = VARIABLE_STORE_HEALTHY ;
VolatileVariableStore - > Reserved = 0 ;
VolatileVariableStore - > Reserved1 = 0 ;
2007-07-19 12:09:07 +02:00
2015-07-01 05:08:29 +02:00
return EFI_SUCCESS ;
2007-07-19 12:09:07 +02:00
}
2007-10-05 16:40:23 +02:00
2010-01-15 09:03:23 +01:00
/**
2010-12-10 10:27:54 +01:00
Get the proper fvb handle and / or fvb protocol by the given Flash address .
2010-01-15 09:03:23 +01:00
2015-07-01 05:08:29 +02:00
@ param [ in ] Address The Flash address .
2010-12-10 10:27:54 +01:00
@ param [ out ] FvbHandle In output , if it is not NULL , it points to the proper FVB handle .
@ param [ out ] FvbProtocol In output , if it is not NULL , it points to the proper FVB protocol .
2010-01-15 09:03:23 +01:00
* */
2010-12-10 10:27:54 +01:00
EFI_STATUS
GetFvbInfoByAddress (
IN EFI_PHYSICAL_ADDRESS Address ,
OUT EFI_HANDLE * FvbHandle OPTIONAL ,
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL * * FvbProtocol OPTIONAL
2009-03-09 07:39:13 +01:00
)
{
2010-12-10 10:27:54 +01:00
EFI_STATUS Status ;
EFI_HANDLE * HandleBuffer ;
UINTN HandleCount ;
UINTN Index ;
EFI_PHYSICAL_ADDRESS FvbBaseAddress ;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL * Fvb ;
EFI_FVB_ATTRIBUTES_2 Attributes ;
2014-12-31 02:46:50 +01:00
UINTN BlockSize ;
UINTN NumberOfBlocks ;
2014-07-28 09:52:57 +02:00
HandleBuffer = NULL ;
2009-03-09 07:39:13 +01:00
//
2010-12-10 10:27:54 +01:00
// Get all FVB handles.
2009-03-09 07:39:13 +01:00
//
2010-12-10 10:27:54 +01:00
Status = GetFvbCountAndBuffer ( & HandleCount , & HandleBuffer ) ;
2009-03-09 07:39:13 +01:00
if ( EFI_ERROR ( Status ) ) {
2010-12-10 10:27:54 +01:00
return EFI_NOT_FOUND ;
2009-03-09 07:39:13 +01:00
}
2010-12-10 10:27:54 +01:00
2009-03-09 07:39:13 +01:00
//
2010-12-10 10:27:54 +01:00
// Get the FVB to access variable store.
2009-03-09 07:39:13 +01:00
//
2010-12-10 10:27:54 +01:00
Fvb = NULL ;
2009-03-10 09:40:29 +01:00
for ( Index = 0 ; Index < HandleCount ; Index + = 1 , Status = EFI_NOT_FOUND , Fvb = NULL ) {
2010-12-10 10:27:54 +01:00
Status = GetFvbByHandle ( HandleBuffer [ Index ] , & Fvb ) ;
2009-03-09 07:39:13 +01:00
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 ) ) {
2014-12-31 02:46:50 +01:00
continue ;
2009-03-09 07:39:13 +01:00
}
2014-12-31 02:46:50 +01:00
2009-03-09 07:39:13 +01:00
//
2010-12-10 10:27:54 +01:00
// Compare the address and select the right one.
2009-03-09 07:39:13 +01:00
//
Status = Fvb - > GetPhysicalAddress ( Fvb , & FvbBaseAddress ) ;
if ( EFI_ERROR ( Status ) ) {
continue ;
}
2014-12-31 02:46:50 +01:00
//
// Assume one FVB has one type of BlockSize.
//
Status = Fvb - > GetBlockSize ( Fvb , 0 , & BlockSize , & NumberOfBlocks ) ;
if ( EFI_ERROR ( Status ) ) {
continue ;
}
if ( ( Address > = FvbBaseAddress ) & & ( Address < ( FvbBaseAddress + BlockSize * NumberOfBlocks ) ) ) {
2010-12-10 10:27:54 +01:00
if ( FvbHandle ! = NULL ) {
* FvbHandle = HandleBuffer [ Index ] ;
}
if ( FvbProtocol ! = NULL ) {
* FvbProtocol = Fvb ;
}
Status = EFI_SUCCESS ;
2009-03-09 07:39:13 +01:00
break ;
}
}
FreePool ( HandleBuffer ) ;
2009-03-19 04:13:08 +01:00
2010-12-10 10:27:54 +01:00
if ( Fvb = = NULL ) {
Status = EFI_NOT_FOUND ;
2009-03-09 07:39:13 +01:00
}
2015-07-01 05:08:29 +02:00
return Status ;
2007-10-05 16:40:23 +02:00
}